Q对象:
优势:可以实现 与|或|非 组合查询。
给几个小例子就一目了然了:
Book.objects.filter(id__gt=2,bread__gt=20) #and关系
Book.objects.filter(Q(bread__gt=20) & Q(id__gt=2)) #and关系
Book.objects.filter(Q(bread__gt=20) | Q(id__gt=2)) #or关系
Book.objects.filter.(~Q(id=3)) # ~表示not,查询编号不等于3的图书
F对象:
优势:能利用当前obj的值进行比较。
Book.objects.filter(bread__gt=F('bcomment')*2) #阅读量大于评论量的图书*2,可以在F对象上使用算术运算
以前你可能经常只进行Book.objects.filter(bread__gt=20)这样的查询 ,有了F对象你就可以和当前obj的属性值进行比较了。
实际开发中遇到的问题:
如果事情都按照示例那样进行就好了,然而开发中总会遇到一些坑。
比如下面这个是我实际开发中遇到的问题:
user = request.user
Interviewer.object.filter(Q(interviewer_1=user) | Q(interviewer_2=user) | Q(interviewer_3=user))
目的是想查一面或者二面或者三面的面试官包含user的面试。
其中interviewer_1、interviewer_2、interviewer_3是Interviewer表中的三个多对多字段的外键。
结果可能让意想不到,结果是一个包含多个重复值的查询集,置于为什么会重复,我并没用做深入调查,但是这在django ORM多表查询中会经常遇到,这就是网上说的一般的情况下,QuerySet 中不会出来重复的,重复是很罕见的,但是当跨越多张表进行检索后,结果并到一起,可能会出来重复的值。
那么要怎么解决这个问题呢?很简单,后面加个.distinct()作用就是去重。
user = request.user
Interviewer.object.filter(Q(interviewer_1=user) | Q(interviewer_2=user) | Q(interviewer_3=user)).distinct()