jazzband / jazzband/django-model-utils
'InheritanceQuerySet.instance_of' and 'count' do not mix
- Dominant language
- Python
- Stars
- 2.8k
- Forks
- 374
- PR merge metrics
- No merged PRs in 30d
Description
## 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
```python
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)
```
```python
>>> for _ in range(3):
... ChildA()
... ChildB()
>>> from django.db import connection
>>> Parent.objects.instance_of(ChildA)
, , ]>
>>>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`.
Contributor guide
Research direction
Start by reproducing the reported case with InheritanceQuerySet.instance_of(ChildA).count() using the model definitions and Django, then inspect how instance_of builds the queryset and how count changes it. Confirm that the count query retains the join needed for the subclass condition and no longer raises the reported SQLite OperationalError.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100