Compare Q objects in a way that works with sets.

Review Request #14899 — Created March 12, 2026 and submitted

Information

django-assert-queries
main

Reviewers

Django 5.0 introduced a new Q.__eq__ implementation which converts the
entire tree to a nested tuple before comparing. The purpose of this was
to fix an issue with dict_keys objects that are used in the migrations
framework, and nothing to do with actual Q objects the way we use them.

Unfortunately, this breaks comparison of Q objects which contain sets
(for example, name__in={'a', 'b'}), because the set ordering is not
stable and it's no longer comparing the actual sets, but tuples created
from the set contents.

This change makes it so we compare Q objects using the parent class
(Node)'s __eq__ implementation, which will compare each item in the
tree one by one, comparing sets against sets instead of converting to
tuples.

  • Ran unit tests.
  • Ran full Review Board test suite.
  • Ran affected Power Pack tests.
Summary ID
Compare Q objects in a way that works with sets.
Django 5.0 introduced a new `Q.__eq__` implementation which converts the entire tree to a nested tuple before comparing. The purpose of this was to fix an issue with `dict_keys` objects that are used in the migrations framework, and nothing to do with actual Q objects the way we use them. Unfortunately, this breaks comparison of Q objects which contain sets (for example, `name__in={'a', 'b'}`), because the set ordering is not stable and it's no longer comparing the actual sets, but tuples created from the set contents. This change makes it so we compare Q objects using the parent class (`Node`)'s `__eq__` implementation, which will compare each item in the tree one by one, comparing sets against sets instead of converting to tuples. Testing Done: - Ran unit tests. - Ran full Review Board test suite. - Ran affected Power Pack tests.
xtsszmwsqtnmslrxyyqpsuvlvyoyzvzy
chipx86
  1. Ship It!
  2. 
      
david
Review request changed
Status:
Completed