Django中Q对象的使用方法

在Django程序中查询数据库操作一般都是在QuerySet里进行,随着程序越来越复杂,查询的条件也跟着复杂起来,简单的通过一个filter来进行查询的条件将导致我们的查询语句越来越长,阅读代码十分不友好。而使用Q对象,就是将这些查询条件分别创建后,组合到一起传给filter,实现复杂查询简单化。

目录

一、环境条件

二、引入Q对象

三、Q对象的使用

四、OR检索

五、AND检索

六、否定

七、总结

一、环境条件

还是用自己的Zinnia博客项目中的Entry类作为例子。Entry类简化为:

from django.db import models
class Entry(models.Model):
    title = models.CharField(_('title'), max_length=255)
    content = models.TextField(_('content'), blank=True)

在Zinnia项目的Entry类中有两个字段title和content,在我的项目中,Entry表中有现成的内容,所以可以直接使用检索。以上就是环境条件。

二、引入Q对象

其实就是下面一行代码:

from django.db.models import Q

Django的Q对象源码位于位于/django/db/models/query_utils.py ,可以看到定义:

classQ(tree.Node):

可知Q对象继承自Node,所以Q也可以使用Node的方法add,后面我们会说到。

三、Q对象的使用

打开命令行,进入Django的shell环境。

python manage.py shell
>>>from zinnia.models.entry import Entry
>>> entry =Entry.objects.filter(Q(title__icontains='odoo')).all()
>>> print([en.title for en in entry])
#输入结果:['[odoo] - 创建模块','[odoo] - Windows下从源代码执行Odoo']

在这里,Q对象作为filter的参数,参数的内容就是title包含odoo字段的标题,执行后则去数据库检索并输出结果。

四、OR检索

Q对象使用’|’符号作为或运算符的操作符进行OR检索,或者使用add方法,在该方法中传入Q.OR参数,一样的效果。一行一行敲太麻烦,而且容易出错,后面把脚本放入项目的目录中,在shell中执行脚本,就可以得到整个脚本的输出。

>>>exec(open('myscript.py').read())

如我们想得到标题含有“odoo”以及“CSS”的文章,

# 方法1
Entry= Entry.objects.filter(Q(title__icontains='odoo')|Q(title__icontains='CSS')).all()
print([en.title for en in entry])
#方法2
q = Q()
q.add(Q(title__icontains='odoo'), Q.OR)
q.add(Q(title__icontains='CSS'), Q.OR)
entry =Entry.objects.filter(q).all()
print([en.title for en in entry])

上面代码的方法1、方法2效果一样

五、AND检索

AND检索是既...又...关系,比如我们找一个既包含“Django”,又包含“Ajax”的标题。如下:

#方法1
entry =Entry.objects.filter(Q(title__icontains='Django')&Q(title__icontains='Ajax')).all()
print([en.title for en in entry])
#方法2
q = Q()
q.add(Q(title__icontains='Django'), Q.AND)
q.add(Q(title__icontains='Ajax'), Q.AND)
entry = Entry.objects.filter(q).all()
print([en.title for en in entry])

六、否定

Q对象使用“~”运算符表示否定条件,数据库查询中一般表示不包含的意思。

如下例子,找到不包含“Django”单词的标题。

entry = Entry.objects.filter(~Q(title__icontains='Django')).all()
print([en.title for en in entry])

还有不包含“Django”且不包含“odoo”单词的标题,可以看出~运算符可以与&、|运算符一起使用,但是~运算符的优先级比&、|运算符高。

entry = Entry.objects.filter(~Q(title__icontains='Django')&~Q(title__icontains='odoo')).all()

七、总结

本文简单介绍了Q对象的使用方法,在实践中,尤其在条件比较复杂的时候,使用Q对象更能发挥效果。

文章同步更新至微信公众号:Django编程

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章