Django Q object

Complex queries with Q objects¶

The keyword argument queries in methods such as filter()  are "ANDed" together. If you need to perform more complex queries (such as OR  statements), you can use theobject .

The Q  object  ( django.db.models.Q ) object is used to encapsulate a set of keyword arguments. These keyword arguments are the ones mentioned in "Field Queries" above.

For example, the following Q  object encapsulates a LIKE  query:

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

Q  objects can be combined using the &  and |  operators. When an operator is used on two Q  objects, it produces a new Q  object.

For example, the following statement produces a Q  object representing  the "OR" of two "question__startswith" queries:

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

It is equivalent to the following SQL  WHERE  clause:

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

You can combine &  and |   operators and use parentheses for grouping to write arbitrarily complex Q  objects. Also, Q  objects can be negated using the ~  operator, which allows combining normal and negated ( NOT ) queries:

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

Each query function that accepts keyword arguments (eg filter() , exclude() , get() ) can be passed one or more Q  objects as positional (unnamed) arguments. If a query function has multiple Q  object parameters, the logical relationship of these parameters is "AND". E.g:

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

... which roughly translates to this SQL:

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

Query functions can mix Q objects and keyword arguments. All arguments (keyword arguments or Q  objects) supplied to the query function are "ANDed" together. However, if a Q  object is present, it must precede all keyword arguments. E.g:

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

... is a valid query, equivalent to the previous example; however:

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

... is not legal.

see also

The OR query example in Django unit tests demonstrates several  uses of Q.

In the source code of Django's Q object implementation:

 

 

[python]  view plain copy  
 
  1. # in /django/db/models/query_utils.py  
  2.   
  3. class Q(tree.Node):  
  4.     """ 
  5.     Encapsulates filters as objects that can then be combined logically (using 
  6.     & and |). 
  7.     """  
  8.     # Connection types  
  9.     AND = 'AND'  
  10.     OR = 'OR'  
  11.     default = AND  
  12.   
  13.     def __init__(self, *args, **kwargs):  
  14.         super(Q, self).__init__(children=list(args) + kwargs.items())  
  15.   
  16.     def _combine(self, other, conn):  
  17.         if not isinstance(other, Q):  
  18.             raise TypeError(other)  
  19.         obj = type(self)()  
  20.         obj.add(self, conn)  
  21.         obj.add(other, conn)  
  22.         return obj  
  23.   
  24.     def __or__(self, other):  
  25.         return self._combine(other, self.OR)  
  26.   
  27.     def __and__(self, other):  
  28.         return self._combine(other, self.AND)  
  29.   
  30.     def __invert__(self):  
  31.         obj = type(self)()  
  32.         obj.add(self, self.AND)  
  33.         obj.negate()  
  34.         return obj  
 

 

Pass the Q object and construct the search condition

 

First you still need to import the module:

from django.db.models import Q

Pass in conditions to query:

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)

Combine conditions to query:

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)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325183043&siteId=291194637
Recommended