Reputation: 2858
I am trying to compare django's Q objects which are composed in the exact same way.
But despite all children and relations between them being same, they aren't deemed equal.
from django.db.models import Q
$ q1 = Q(a=1) & Q(b=1) & Q(c=1)
$ q2 = Q(a=1) & Q(b=1) & Q(c=1)
$ q1 == q2
$ False
This is posing problems in my unit tests where I build up filters for my querysets using Q objects.
Why are the two Q objects not equal?
I am using Django 1.11.
Upvotes: 4
Views: 994
Reputation: 617
I built on xssChauhan's answer to handle the case where you have nested Q objects:
def compare_Qs(Q1, Q2):
if hasattr(Q1, 'children') and hasattr(Q2, 'children'):
if (Q1.__class__ == Q2.__class__) and ((Q1.connector, Q1.negated)
== (Q2.connector, Q2.negated)) and (len(Q1.children) ==
len(Q2.children)):
result = [compare_Qs(Q1.children[i], Q2.children[i]) for i in
range(len(Q1.children))]
return all(result)
return (Q1 == Q2)
Upvotes: 2
Reputation: 2858
Django <= 1.11.x does not implement __eq__
method for Q objects.
As can be seen here.
Django >= 2.0 implements __eq__
method for Q objects. Code.
So it is not possible to directly check the equality of two Q objects before Django 2.0.
But it is possible to write a simple function that checks the equality of Q objects. We can directly use the code from the repo.
def compare_q(q1 , q2):
return (
q1.__class__ == q2.__class__ and
(q1.connector, q1.negated) == (q2.connector, q2.negated) and
q1.children == q2.children
)
So, for older versions of Django we can do:
$ compare_q(q1 , q2)
$ True
Upvotes: 6