Django中Q查询及Q()对象
问题
一般我们在Django程序中查询数据库操作都是在QuerySet里进行进行,例如下面代码:
>>> q1 = Entry.objects.filter(headline__startswith="What")
>>> q2 = q1.exclude(pub_date__gte=datetime.date.today())
>>> q3 = q1.filter(pub_date__gte=datetime.date.today())
或者将其组合起来,例如:
>>>q1 = Entry.objects.filter(headline_startswith="What").exclude(pub_date_gte=datetime.date.today())
随着我们的程序越来越复杂,查询的条件也跟着复杂起来,这样简单的通过一个filter()来进行查询的条件将导致我们的查询越来越长。
Q()对象就是为了将这些条件组合起来。
当我们在查询的条件中需要组合条件时(例如两个条件“且”或者“或”)时。我们可以使用Q()查询对象。例如下面的代码
fromdjango.db.modelsimports Q
q=Q(question_startswith="What")
这样就生成了一个Q()对象,我们可以使用符号&或者|将多个Q()对象组合起来传递给filter(),exclude(),get()等函数。当多个Q()对象组合起来时,Django会自动生成一个新的Q()。例如下面代码就将两个条件组合成了一个
Q(question__startswith='Who') | Q(question__startswith='What')
使用上述代码可以使用SQL语句这么理解:
WHEREquestionLIKE 'Who%' ORquestionLIKE 'What%'
我们可以在Q()对象的前面使用字符“~”来代表意义“非”,例如下面代码:
Q(question__startswith='Who') | ~Q(pub_date__year=2005)
对应SQL语句可以理解为:
WHEREquestionlike "Who%" ORyear(pub_date) !=2005
这样我们可以使用 “&”或者“|”还有括号来对条件进行分组从而组合成更加复杂的查询逻辑。
也可以传递多个Q()对象给查询函数,例如下面代码:
News.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
多个Q()对象之间的关系Django会自动理解成“且(and)”关系。如上面代码使用SQL语句理解将会是:
SELECT * fromnewsWHEREquestionLIKE 'Who%' AND (pub_date = '2005-05-02' ORpub_date = '2005-05-06')
Q()对象可以结合关键字参数一起传递给查询函数,不过需要注意的是要将Q()对象放在关键字参数的前面,看下面代码
#正确的做法
News.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who')
#错误的做法,代码将关键字参数放在了Q()对象的前面。
News.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
使用Q 对象进行复杂的查询
filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象。
Q 对象 (django.db.models.Q) 对象用于封装一组关键字参数。这些关键字参数就是上文“字段查询” 中所提及的那些。
例如,下面的Q 对象封装一个LIKE 查询:
from django.db.models import Q
Q(question__startswith='What')
Q 对象可以使用& 和| 操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。
例如,下面的语句产生一个Q 对象,表示两个"question__startswith" 查询的“OR” :
Q(question__startswith='Who') | Q(question__startswith='What')
它等同于下面的SQL WHERE 子句:
WHERE question LIKE 'Who%' OR question LIKE 'What%'
你可以组合& 和| 操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询:
Q(question__startswith='Who') | ~Q(pub_date__year=2005)
每个接受关键字参数的查询函数(例如filter()、exclude()、get())都可以传递一个或多个Q 对象作为位置(不带名的)参数。如果一个查询函数有多个Q 对象参数,这些参数的逻辑关系为“AND"。例如:
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')
查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。例如:
Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who')
... 是一个合法的查询,等同于前面的例子;但是:
# INVALID QUERY
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
... 是不合法的。
另见
Django 单元测试中的OR 查询示例演示了几种Q 的用法。
Django的Q对象实现的源码中:
# 位于/django/db/models/query_utils.py
class Q(tree.Node):
"""
Encapsulates filters as objects that can then be combined logically (using
& and |).
"""
# Connection types
AND = 'AND'
OR = 'OR'
default = AND
def __init__(self, *args, **kwargs):
super(Q, self).__init__(children=list(args) + kwargs.items())
def _combine(self, other, conn):
if not isinstance(other, Q):
raise TypeError(other)
obj = type(self)()
obj.add(self, conn)
obj.add(other, conn)
return obj
def __or__(self, other):
return self._combine(other, self.OR)
def __and__(self, other):
return self._combine(other, self.AND)
def __invert__(self):
obj = type(self)()
obj.add(self, self.AND)
obj.negate()
return obj
传Q对象,构造搜索条件
首先还是需要导入模块:
from django.db.models import Q
传入条件进行查询:
q1 = Q()
q1.connector = 'OR'
q1.children.append(('id', 1))
q1.children.append(('id', 2))
q1.children.append(('id', 3))
models.Tb1.objects.filter(q1)
合并条件进行查询:
con = Q()
q1 = Q()
q1.connector = 'OR'
q1.children.append(('id', 1))
q1.children.append(('id', 2))
q1.children.append(('id', 3))
q2 = Q()
q2.connector = 'OR'
q2.children.append(('status', '在线'))
con.add(q1, 'AND')
con.add(q2, 'AND')
models.Tb1.objects.filter(con)
<!-- .embody{ padding:10px 10px 10px; margin:0 -20px; border-bottom:solid 1px #ededed; } .embody_b{ margin:0 ; padding:10px 0; } .embody .embody_t,.embody .embody_c{ display: inline-block; margin-right:10px; } .embody_t{ font-size: 12px; color:#999; } .embody_c{ font-size: 12px; } .embody_c img,.embody_c em{ display: inline-block; vertical-align: middle; } .embody_c img{ width:30px; height:30px; } .embody_c em{ margin: 0 20px 0 10px; color:#333; font-style: normal; } -->
- Spring和SpringMVC父子的容器之道---[上篇]
- 快速完成(图片旋转,查看原图)
- Jsp中格式化时间戳的常用标签
- 反射+自定义注解---实现Excel数据列属性和JavaBean属性的自动映射
- 后台模板管理系统___左侧菜单数据的异步加载
- Shiro眼皮下玩ajax,玩出302 Found
- 对于JSONObject,我只是临时抱佛脚
- 总结切面编程AOP的注解式开发和XML式开发
- SpringMVC注解@RequestMapping之produces属性导致的406错误
- SpringBoot集成MyBatis的分页插件PageHelper(回头草)
- SpringBoot整合Mybatis之进门篇
- Tomcat和Java Virtual Machine的性能调优总结
- 一次浴火重生的MySQL优化(EXPLAIN命令详解)
- 简单聊聊不可或缺的Nginx反向代理服务器--实现负载均衡【上篇】
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- python爬虫--自动下载cosplay小姐姐图片(xpath使用自定义创建文件路径)
- springboot开发之修改员工
- LeetCode | 703.数据流中的第K大元素
- springboot开发之配置自定义的错误界面和错误信息
- springboot开发之删除员工
- LeetCode | 1.两数之和
- springboot开发之配置嵌入式Servlet容器两种方式
- jvaa之初始化块
- java之匿名内部类
- springboot配置之获取配置文件中属性的第二种方法(@Value)不同于@ConfigurationProperties
- mybatis动态sql之内置参数_parameter和_databaseId
- Redis | Redis 字符串相关命令
- java之抽象类
- springboot配置之yaml
- properties和yaml配置文件