jazzband/django-model-utils

'InheritanceQuerySet.instance_of' and 'count' do not mix

ambroisie opened this issue · 0 comments

Problem

When trying to use InheritanceQuerySet.instance_of to filter a queryset to only some sub-classes, and use queryset.count() to get the count, instead I get an OperationalError.

Environment

  • Django Model Utils version: 4.2.0
  • Django version: 4.0.3
  • Python version: 3.10

Code examples

from django.db import models
from model_utils.managers import InheritanceManager


class Parent(models.Model):
    objects = InheritanceManager()

    field = models.CharField(max_length=50)

class ChildA(Parent):
    field_chield_a = models.CharField(max_length=50)

class ChildB(Parent):
    field_chield_b = models.CharField(max_length=50)
>>> for _ in range(3):
...     ChildA()
...     ChildB()
>>> from django.db import connection
>>> Parent.objects.instance_of(ChildA)
<InheritanceQuerySet [<ChildA: ChildA object (1)>, <ChildA: ChildA object (2)>, <ChildA: ChildA object (3)>]>
>>>Parent.objects.instance_of(ChildA).count()
Traceback (most recent call last):
  File "<...>/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "<...>/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 477, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: no such column: playground_childa.parent_ptr_id
>>> from pprint import pprint
>>> pprint(connection.queries)
[{'sql': 'SELECT "playground_parent"."id", "playground_parent"."field", '
         '"playground_childa"."parent_ptr_id", '
         '"playground_childa"."field_chield_a" FROM "playground_parent" LEFT '
         'OUTER JOIN "playground_childa" ON ("playground_parent"."id" = '
         '"playground_childa"."parent_ptr_id") WHERE '
         '(("playground_childa"."parent_ptr_id" IS NOT NULL)) LIMIT 21',
  'time': '0.000'},
 {'sql': 'SELECT COUNT(*) AS "__count" FROM "playground_parent" WHERE '
         '(("playground_childa"."parent_ptr_id" IS NOT NULL))',
  'time': '0.000'}]

As you can see, the query is missing the LEFT OUTER JOIN directive when trying to use count.