diff options
Diffstat (limited to 'django/db/models/query_utils.py')
| -rw-r--r-- | django/db/models/query_utils.py | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/django/db/models/query_utils.py b/django/db/models/query_utils.py index 746efce67f..9b5824f89f 100644 --- a/django/db/models/query_utils.py +++ b/django/db/models/query_utils.py @@ -8,12 +8,16 @@ circular import difficulties. import copy import functools import inspect +import logging from collections import namedtuple from django.core.exceptions import FieldError +from django.db import DEFAULT_DB_ALIAS, DatabaseError from django.db.models.constants import LOOKUP_SEP from django.utils import tree +logger = logging.getLogger("django.db.models") + # PathInfo is used when converting lookups (fk__somecol). The contents # describe the relation in Model terms (model Options and Fields for both # sides of the relation. The join_field is the field backing the relation. @@ -110,6 +114,31 @@ class Q(tree.Node): else: yield child + 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 Value + 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". + 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 deconstruct(self): path = "%s.%s" % (self.__class__.__module__, self.__class__.__name__) if path.startswith("django.db.models.query_utils"): |
