基础条件查询
这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
在本指南(以及参考资料)中,我们将参考以下模型,
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
def __str__(self):
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
number_of_comments = models.IntegerField()
number_of_pingbacks = models.IntegerField()
rating = models.IntegerField()
def __str__(self):
return self.headline
1 基本查询
get查询单一结果,如果不存在会抛出模型类.DoesNotExist异常。
all查询多个结果。
count查询结果数量。
>>> Blog.objects.get(id=1)
>>> Blog.objects.all()
>>> Blog.objects.count()
2 过滤查询
- filter过滤出多个结果,返回一个新的
QuerySet,包含的对象满足给定查询参数 - exclude排除掉符合条件剩下的结果,返回一个新的
QuerySet,包含的对象 不 满足给定查询参数 - get过滤单一结果
2.1 filter
要包含获取 2006 年的博客条目(entries blog)的 QuerySet,像这样使用 filter():
Entry.objects.filter(pub_date__year=2006)
Entry.objects.all().filter(pub_date__year=2006)
链式过滤器
精炼 QuerySet的结果本身还是一个 QuerySet,所以能串联精炼过程。例子:
>>> Entry.objects.filter(
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.date.today()
... ).filter(
... pub_date__gte=datetime.date(2005, 1, 30)
... ) # (每个QuerySet是唯一的,是惰性的【执行最后面的】)
2.2 get
用 get() 检索单个对象
filter() 总是返回一个 QuerySet,即便只有一个对象满足查询条件 —— 这种情况下, QuerySet只包含了一个元素。
若你知道只会有一个对象满足查询条件,你可以在 Manager 上使用 get() 方法,它会直接返回这个对象:
>>> one_entry = Entry.objects.get(pk=1)
2.3 exclude
>>> q1 = Entry.objects.filter(headline__startswith="What")
>>> q2 = q1.exclude(pub_date__gte=datetime.date.today()) [惰性]
3 过滤条件的表达语法如下:
属性名称__比较运算符=值
# 属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线
1)相等
exact:表示判等。
例:查询编号为1的。
Blog.objects.filter(id__exact=1)
可简写为:
Bog.objects.filter(id=1)
iexact:不分大小写的匹配,查询语句:
```
>>> Blog.objects.get(name__iexact="beatles blog")
```
2)模糊查询
contains:是否包含。
说明:如果要包含%无需转义,直接写即可。
例:查询书名包含'传'的图书。
BookInfo.objects.filter(name__contains='传')
<QuerySet [<BookInfo: 射雕英雄传>]>
大小写不敏感的版本, icontains。
startswith、endswith:以指定值开头或结尾。
>>> Blog.objects.filter(name__endswith='a')
以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.
3) 空查询
isnull:是否为null。
>>> Blog.objects.filter(name__isnull=True)
4) 范围查询
in:是否包含在范围内。
>>> Blog.objects.filter(id__in=[1,3,5])
5)比较查询
- gt大于 (greater then)
- gte大于等于 (greater then equal)
- lt小于 (less then)
- lte小于等于 (less then equal)
例:查询编号大于3的
Blog.objects.filter(id__gt=3)
不等于的运算符,使用exclude()过滤器。
例:查询编号不等于3的
>>> Blog.objects.exclude(id__gt=3)
6)日期查询
year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。
例:查询1980年发表的。
>>> Blog.objects.filter(pub_date__year=1980)
例:查询1990年1月1日后发表的。
>>> Blog.objects.filter(pub_date__gt='1990-1-1')
7)主键 (pk) 查询快捷方式
出于方便的目的,Django 提供了一种 pk 查询快捷方式, pk 表示主键 "primary key"。
示例 Blog 模型中,主键是 id 字段,所以这 3 个语句是等效的:
>>> Blog.objects.get(id__exact=14) # Explicit form
>>> Blog.objects.get(id=14) # __exact is implied
>>> Blog.objects.get(pk=14) # pk implies id__exact
pk 的使用并不仅限于 __exact 查询——任何的查询项都能接在 pk 后面,执行对模型主键的查询:
# Get blogs entries with id 1, 4 and 7
>>> Blog.objects.filter(pk__in=[1,4,7])
# Get all blog entries with id > 14
>>> Blog.objects.filter(pk__gt=14)
pk 查找也支持跨连接。例如,以下 3 个语句是等效的:
>>> Entry.objects.filter(blog__id__exact=3) # Explicit form
>>> Entry.objects.filter(blog__id=3) # __exact is implied
>>> Entry.objects.filter(blog__pk=3) # __pk implies __id__exact