django中的Q()函数:应用于model数据查询的与(and)或(or)操作

问题背景

之前用django的时候,数据库这一块也没有涉及到比较复杂一点的查询,一般就是一个filter()或者一个get()就搞定了,前几天做一个可视化的项目时,遇到了多条件复合查询,看了下文档,django的orm还是挺好用的,Q()函数可以解决这个问题。

比如我要查询id为1或者id为2的一个数据,在filter里面,是不能够这么直接来的:filter(id=1,id=2),只能使用Q函数。为了更深入地理解Q函数,我参考官方文档,整理一下它的用法。

文档位置:https://docs.djangoproject.com/en/1.9/topics/db/queries/#complex-lookups-with-q-objects

django中Q()函数的介绍

如果你需要进行复杂的查询(比如or条件),你可以使用Q对象。

Q对象是用来封装查询参数的,比如,它可以仅仅用来封装单独一个like查询:

from django.db.models import Q
Q(question__startswith='What')

Q函数可以通过逻辑符号连接

Q对象可以和&|这两个符号一起来使用,即and和or。下面这个例子就用or将两个查询组合在了一起:

Q(question__startswith='Who') | Q(question__startswith='What')

相当于以下sql语句:

WHERE question LIKE 'Who%' OR question LIKE 'What%'

另外,还可以使用非符号~,比如:

Q(question__startswith='Who') | ~Q(pub_date__year=2005)

Q函数用于数据库查询

以上介绍了Q的组合方法,那么怎么把它应用到数据库的查询呢?一般而言,可以把它们放到filter(),get()或者exclude()里面,比如:

Poll.objects().filter(Q(question__startswith='Who') | ~Q(pub_date__year=2005))

Q函数和关键字参数混合使用

另外,Q对象还可以和关键字参数一起使用,不过Q一定要放在前面,以下是正确例子:

Poll.objects.get(
    Q(question__startswith='Who'),
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)

相当于sql查询语句如下:

SELECT * from polls WHERE question LIKE 'Who%'
    AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

关键字参数放在前面是错误的用法!!如下是错误的!

# 错误用法
Poll.objects.get(
    question__startswith='Who',
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)

我的实践

我喜欢这样来用Q对象。先在外面将条件组合好,然后再传入filter()get()或者exclude()里面,代码片段如下:

from django.db.models import Q
my_filter = Q()
my_filter = my_filter | Q(id=1)
my_filter = my_filter | Q(name="lipengfei")
result = People.objects.filter(my_filter)