diff options
| author | Gagaro <gagaro42@gmail.com> | 2022-01-31 16:04:13 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-05-04 08:47:52 +0200 |
| commit | 5d91dc8ee3ff7e2230cfacf41005f61b8efbf057 (patch) | |
| tree | dcf497a064eba43eaa6163b772f4f7873b5bfc42 /django/db/models/query_utils.py | |
| parent | 1109e669905d2011561e843f0ab7c2c02fb63c4d (diff) | |
Refs #30581 -- Added Q.check() hook.
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"): |
