在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 条评论) “” |