filter 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q对象

调用Q

from django.db.models import Q

Q 对象可以使用c&(AND)|(OR)操作符组合起来。

当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。

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

等同于SQL语句

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

如果一个查询函数有多个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 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询:

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

查询函数可以混合使用Q对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。例如

Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who') #下列是不合法的查询条件
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
 

Q对象实例化使用:

        # 获取搜索条件
condition_dict = json.loads(request.GET.get('condition'))
'''
{'sn__contains': ['1', '2', '3', '1'], 'hostname__contains': ['c1', 'c2', 'c3']}
''' from django.db.models import Q
#产生第一个Q对象
con = Q()
for k,v in condition_dict.items():
#产生第二个Q对象
temp = Q()
temp.connector = 'OR' # Connection types AND = 'AND' OR = 'OR' default = AND for item in v:
temp.children.append((k,item)) #children是Q父类Node的属性,默认是个列表 con.add(temp,'AND') # add 是父类Node的方法, print(con)
'''
(AND: (OR: ('sn__contains', '1'), ('sn__contains', '1')), ('hostname__contains', 'c3'))
'''
models.Server.objects.filter(con)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Created by Mona on 2017/10/24 import copy from django.utils.encoding import force_str, force_text class Node(object):
"""
A single internal node in the tree graph. A Node should be viewed as a
connection (the root) with the children being either leaf nodes or other
Node instances.
"""
# Standard connector type. Clients usually won't use this at all and
# subclasses will usually override the value.
default = 'DEFAULT' def __init__(self, children=None, connector=None, negated=False):
"""
Constructs a new Node. If no connector is given, the default will be
used.
"""
self.children = children[:] if children else []
self.connector = connector or self.default
self.negated = negated # We need this because of django.db.models.query_utils.Q. Q. __init__() is
# problematic, but it is a natural Node subclass in all other respects.
@classmethod
def _new_instance(cls, children=None, connector=None, negated=False):
"""
This is called to create a new instance of this class when we need new
Nodes (or subclasses) in the internal code in this class. Normally, it
just shadows __init__(). However, subclasses with an __init__ signature
that is not an extension of Node.__init__ might need to implement this
method to allow a Node to create a new instance of them (if they have
any extra setting up to do).
"""
obj = Node(children, connector, negated)
obj.__class__ = cls
return obj def __str__(self):
template = '(NOT (%s: %s))' if self.negated else '(%s: %s)'
return force_str(template % (self.connector, ', '.join(force_text(c) for c in self.children))) def __repr__(self):
return str("<%s: %s>") % (self.__class__.__name__, self) def __deepcopy__(self, memodict):
"""
Utility method used by copy.deepcopy().
"""
obj = Node(connector=self.connector, negated=self.negated)
obj.__class__ = self.__class__
obj.children = copy.deepcopy(self.children, memodict)
return obj def __len__(self):
"""
The size of a node if the number of children it has.
"""
return len(self.children) def __bool__(self):
"""
For truth value testing.
"""
return bool(self.children) def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self) def __contains__(self, other):
"""
Returns True is 'other' is a direct child of this instance.
"""
return other in self.children def add(self, data, conn_type, squash=True):
"""
Combines this tree and the data represented by data using the
connector conn_type. The combine is done by squashing the node other
away if possible. This tree (self) will never be pushed to a child node of the
combined tree, nor will the connector or negated properties change. The function returns a node which can be used in place of data
regardless if the node other got squashed or not. If `squash` is False the data is prepared and added as a child to
this tree without further logic.
"""
if data in self.children:
return data
if not squash:
self.children.append(data)
return data
if self.connector == conn_type:
# We can reuse self.children to append or squash the node other.
if (isinstance(data, Node) and not data.negated and
(data.connector == conn_type or len(data) == 1)):
# We can squash the other node's children directly into this
# node. We are just doing (AB)(CD) == (ABCD) here, with the
# addition that if the length of the other node is 1 the
# connector doesn't matter. However, for the len(self) == 1
# case we don't want to do the squashing, as it would alter
# self.connector.
self.children.extend(data.children)
return self
else:
# We could use perhaps additional logic here to see if some
# children could be used for pushdown here.
self.children.append(data)
return data
else:
obj = self._new_instance(self.children, self.connector,
self.negated)
self.connector = conn_type
self.children = [obj, data]
return data def negate(self):
"""
Negate the sense of the root connector.
"""
self.negated = not self.negated class Q(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) + list(kwargs.items())) def _combine(self, other, conn):
if not isinstance(other, Q):
raise TypeError(other)
obj = type(self)()
obj.connector = conn
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 def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
# We must promote any new joins to left outer joins so that when Q is
# used as an expression, rows aren't filtered due to joins.
clause, joins = query._add_q(self, reuse, allow_joins=allow_joins, split_subq=False)
query.promote_joins(joins)
return clause

Q源码参考

django---ORM之Q查询的更多相关文章

  1. Python自动化之django orm之Q对象

    Python自动化之django orm之Q对象 什么是Q对象? Encapsulates filters as objects that can then be combined logically ...

  2. 请教如何用 peewee 实现类似 django ORM 的这种查询效果。

    本人新入坑的小白,如有不对的地方请包涵~~~! 在 django 中代码如下:模型定义: class Friends(models.Model): first_id = models.IntegerF ...

  3. django F与Q查询 事务 only与defer

    F与Q 查询 class Product(models.Model): name = models.CharField(max_length=32) #都是类实例化出来的对象 price = mode ...

  4. Django ORM多表查询练习

    ORM多表查询 创建表结构: from django.db import models # 创建表结构 # Create your models here. class Class_grade(mod ...

  5. DJANGO的ORM的Q查询作多字段外键的模糊查询样码

    工作中用到的,存照一下. from django.db.models import Q if self.kwargs.has_key('search_pk'): search_pk = self.kw ...

  6. django ORM 连表查询2

    set() 更新model对象的关联对象 book_obj=models.Book.objects.first() book_obj.authors.set([2,3]) 把book_obj这个对象重 ...

  7. Django ORM中的查询,删除,更新操作

    ORM查询操作 修改views.py文件 from django.shortcuts import render, HttpResponse from app01 import models from ...

  8. Django ORM多表查询

    基于双下划线查询 根据存的时候,字段的数据格式衍生的查询方法 1.年龄大于35岁 res = models.AuthorDetails.objects.filter(age__lt=80) print ...

  9. django ORM 连表查询

    db_index=True  如果设置该字段就可以设置索引 auto_now_add  代表设置创建时候的时间 auto_now   每次更新数据记录时会更新该字段 to_field 设置要关联表的字 ...

  10. Django ORM单表查询必会13条

    必知必会13条 操作下面的操作之前,我们实现创建好了数据表,这里主要演示下面的操作,不再细讲创建准备过程 <1> all(): 查询所有结果 <2> filter(**kwar ...

随机推荐

  1. HDU 5326(2015多校3)-Work(dfs)

    题目地址:pid=5326">HDU 5326 题意:给一张有向图n个点.n - 1(....输入n-1)条边. A指向B代表A管理B.然后能够间接管理,比方A管理B,B管理C.则A管 ...

  2. EntityFramework :数据库创建

    控制数据库的位置 默认情况下,数据库是创建在localhost\SQLEXPRESS服务器上,并且默认的数据库名为命名空间+context类名,例如我们前面的BreakAway.BreakAwayCo ...

  3. SQL Server Profiler的简单使用(监控mssql)

    SQL Server Profiler可以检测在数据上执行的语句,特别是有的项目不直接使用sql语句,直接使用ORM框架的系统处理数据库的项目,在调试sql语句时,给了很大的帮助. 之前写了使用SQL ...

  4. java的list转map

    companyList = companyManager.listByCompanyId(companyIds);departList = departManager.findByTree(depar ...

  5. sql的case when then else end 的语法实现列转行

    SELECT * FROM test5 ; RESOURCES DATETIME CNT ID1 0 2018-01-22 4 12 0 2018-01-24 10 23 0 2018-01-25 2 ...

  6. 《JAVA多线程编程核心技术》 笔记:第四章、Lock的使用

    一.使用ReentrantLock类1.1 ReentrantLock的使用:1.2 ReentrantLock的不足:1.3 正确使用Condition实现等待/通知1.4 使用多个Conditio ...

  7. Scala 常用语法

    Clojure首先是FP, 但是由于基于JVM, 所以不得已需要做出一些妥协, 包含一些OO的编程方式 Scala首先是OO, Java语法过于冗余, 一种比较平庸的语言, Scala首先做的是简化, ...

  8. 用jq实现鼠标移入按钮背景渐变其他的背景效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. echarts系列之动态修改柱状图颜色

    echarts根据某一变量动态修改柱状图颜色 1.option中参数配置项series { "name":"Android", "type" ...

  10. yield的表达式形式、面向过程编程(grep -rl 'root' /etc)

    一.yield的表达形式 def foo(): print('starting') while True: x=yield None#return 2 print('value :',x) g=foo ...