Py006-01-21F查询和Q查询

其他查询

  • F查询
  • Q查询

我们为book表新增两个字段

  • zan 赞的次数
  • cai 踩的次数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Book

class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=32)
publishDate = models.DateField()
price = models.DecimalField(max_digits=5,decimal_places=2)

zan = models.IntegerField()
cai = models.IntegerField()


publish = models.ForeignKey(to="Publish",to_field='nid',on_delete=models.CASCADE)

authors = models.ManyToManyField(to="Author");

# 此时执行数据库迁徙操作
python3 manage.py makemigrations
# 警告如下信息
'''
You are trying to add a non-nullable field 'zan' to book without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
意思是新增的两个字段 没有设置默认值
'''

# 修改代码如下 设置初始默认值
zan = models.IntegerField(default=0)
cai = models.IntegerField(default=0)

# 继续数据库迁徙
python3 manage.py makemigrations
python3 manage.py migrate

F查询

在之前所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较

如果我们要对两个字段的值做比较,那该怎么做呢?

1
Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

查询点赞数大于踩数的书籍

1
2
3
from django.db.models import F

res = Book.objects.filter(zan__gt=F('cai'))

Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。

1
2
# 查询点赞数大于踩数2倍的书籍
Book.objects.filter(zan__lt=F('cai')*2)

修改操作也可以使用F函数,比如将每一本书的价格提高30元:

1
Book.objects.all().update(price=F("price")+30)

Q查询

filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象。

1
2
from django.db.models import Q
Q(title__startswith='Py')

Q 对象可以使用& 和| 操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。

1
bookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="egon"))

等同于下面的SQL WHERE 子句:

1
WHERE name ="yuan" OR name ="egon"

你可以组合& 和| 操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询:

1
bookList=Book.objects.filter(Q(authors__name="alex") & ~Q(publishDate__year=2017)).values_list("title")

查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将”AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。例如:

1
2
3
bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017),
title__icontains="python"
)