class Q
from django.db.models.query_utils import Q
Encapsulate filters as objects that can then be combined logically (using `&` and `|`).
Ancestors (MRO)
Attribute | Value | Defined in |
---|---|---|
AND |
AND |
django.db.models.query_utils.Q |
OR |
OR |
django.db.models.query_utils.Q |
XOR |
XOR |
django.db.models.query_utils.Q |
conditional |
True |
django.db.models.query_utils.Q |
default |
AND |
django.db.models.query_utils.Q |
default |
DEFAULT |
django.utils.tree.Node |
def add(self, data, conn_type)
django.utils.tree.Node
Combine 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. Return a node which can be used in place of data regardless if the node other got squashed or not.
def add(self, data, conn_type):
"""
Combine 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.
Return a node which can be used in place of data regardless if the
node other got squashed or not.
"""
if self.connector != conn_type:
obj = self.copy()
self.connector = conn_type
self.children = [obj, data]
return data
elif (
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
def check(self, against, using='default')
django.db.models.query_utils.Q
Do a database query to check if the expressions of the Q instance matches against the expressions.
def check(self, against, using=DEFAULT_DB_ALIAS):
"""
Do a database query to check if the expressions of the Q instance
matches against the expressions.
"""
# Avoid circular imports.
from django.db.models import BooleanField, Value
from django.db.models.functions import Coalesce
from django.db.models.sql import Query
from django.db.models.sql.constants import SINGLE
query = Query(None)
for name, value in against.items():
if not hasattr(value, "resolve_expression"):
value = Value(value)
query.add_annotation(value, name, select=False)
query.add_annotation(Value(1), "_check")
# This will raise a FieldError if a field is missing in "against".
if connections[using].features.supports_comparing_boolean_expr:
query.add_q(Q(Coalesce(self, True, output_field=BooleanField())))
else:
query.add_q(self)
compiler = query.get_compiler(using=using)
try:
return compiler.execute_sql(SINGLE) is not None
except DatabaseError as e:
logger.warning("Got a database error calling check() on %r: %s", self, e)
return True
def copy(self)
django.utils.tree.Node
def __copy__(self):
obj = self.create(connector=self.connector, negated=self.negated)
obj.children = self.children # Don't [:] as .__init__() via .create() does.
return obj
def create(cls, children=None, connector=None, negated=False)
django.utils.tree.Node
Create a new instance using Node() instead of __init__() as some subclasses, e.g. django.db.models.query_utils.Q, may implement a custom __init__() with a signature that conflicts with the one defined in Node.__init__().
@classmethod
def create(cls, children=None, connector=None, negated=False):
"""
Create a new instance using Node() instead of __init__() as some
subclasses, e.g. django.db.models.query_utils.Q, may implement a custom
__init__() with a signature that conflicts with the one defined in
Node.__init__().
"""
obj = Node(children, connector or cls.default, negated)
obj.__class__ = cls
return obj
def deconstruct(self)
django.db.models.query_utils.Q
def deconstruct(self):
path = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
if path.startswith("django.db.models.query_utils"):
path = path.replace("django.db.models.query_utils", "django.db.models")
args = tuple(self.children)
kwargs = {}
if self.connector != self.default:
kwargs["_connector"] = self.connector
if self.negated:
kwargs["_negated"] = True
return path, args, kwargs
def flatten(self)
django.db.models.query_utils.Q
Recursively yield this Q object and all subexpressions, in depth-first order.
def flatten(self):
"""
Recursively yield this Q object and all subexpressions, in depth-first
order.
"""
yield self
for child in self.children:
if isinstance(child, tuple):
# Use the lookup.
child = child[1]
if hasattr(child, "flatten"):
yield from child.flatten()
else:
yield child
def identity(self)
django.db.models.query_utils.Q
def negate(self)
django.utils.tree.Node
Negate the sense of the root connector.
def negate(self):
"""Negate the sense of the root connector."""
self.negated = not self.negated
def referenced_base_fields(self)
django.db.models.query_utils.Q
Retrieve all base fields referenced directly or through F expressions excluding any fields referenced through joins.
def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False)
django.db.models.query_utils.Q
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,
check_filterable=False,
summarize=summarize,
)
query.promote_joins(joins)
return clause