ORM can produce invalid SQL when subclassing Query

Hi all,

We wrote some custom logic that extended the Query class. It worked fine in 3.2 but not for 4.1, and it started producing invalid SQL. We filed a ticket (#35836) but haven’t made any progress since Query is an undocumented API.

Our use case is an automatic site filter - objects belonging to different customer sites are automatically filtered to the current site, so each queryset doesn’t have to be explicitly filtered. We did this at the Query level rather than filtering the default manager’s get_queryset . This has the useful effect that our DRF views can define a queryset attribute on their class definition (where there isn’t a ‘current’ site) and the query will be filtered when it is actually executed (in a request context on a particular site)

How should we change our usage of Query to fix the bug? Below is the contents of the ticket.


We have observed a bug in the ORM where invalid SQL can be produced.

A reproduction can be seen here:

And specifically:

It is caused with the following steps:

  1. Subclassing django.db.models.sql.Query and using it in a Queryset mixin
  2. Creating a queryset with an exclude() expression which includes a subquery. EG Classroom.objects.exclude(student_set__id=student_A.id)
  3. Then before calling super().get_compiler from our subclassed Query:
  • Clone the query
  • Adding a simple expression via cloned_query.add_q eg cloned_query.add_q(Q(school_id=1))
  • Passing the cloned query into super().get_compiler
  1. Then evaluate the queryset, which produces invalid SQL and raises django.db.utils.OperationalError

Note the issue happens when get_compiler is invoked for the subquery, not on the main query itself.

This was working for us in Django 3.2, but not for Django 4.1

git bisect shows the breakage was introduced by this commit:
14c8504a37afad96ab93cf82f47b13bcc4d00621