summaryrefslogtreecommitdiff
path: root/django/db/models/query_utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'django/db/models/query_utils.py')
-rw-r--r--django/db/models/query_utils.py23
1 files changed, 23 insertions, 0 deletions
diff --git a/django/db/models/query_utils.py b/django/db/models/query_utils.py
index 78148f76b0..fcda30b3a7 100644
--- a/django/db/models/query_utils.py
+++ b/django/db/models/query_utils.py
@@ -14,6 +14,8 @@ from django.core.exceptions import FieldError
from django.db import DEFAULT_DB_ALIAS, DatabaseError, connections
from django.db.models.constants import LOOKUP_SEP
from django.utils import tree
+from django.utils.functional import cached_property
+from django.utils.hashable import make_hashable
logger = logging.getLogger("django.db.models")
@@ -151,6 +153,27 @@ class Q(tree.Node):
kwargs["_negated"] = True
return path, args, kwargs
+ @cached_property
+ def identity(self):
+ path, args, kwargs = self.deconstruct()
+ identity = [path, *kwargs.items()]
+ for child in args:
+ if isinstance(child, tuple):
+ arg, value = child
+ value = make_hashable(value)
+ identity.append((arg, value))
+ else:
+ identity.append(child)
+ return tuple(identity)
+
+ def __eq__(self, other):
+ if not isinstance(other, Q):
+ return NotImplemented
+ return other.identity == self.identity
+
+ def __hash__(self):
+ return hash(self.identity)
+
class DeferredAttribute:
"""