Opened 13 years ago
Closed 9 years ago
#16135 closed Bug (fixed)
Model 'Child' is inherited from 'Parent', expecting to get only Child results with Parent.objects.filter(child__isnull=False), but does not work.
Reported by: | Robin | Owned by: | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.3 |
Severity: | Normal | Keywords: | |
Cc: | nikolay@… | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Example model:
class Parent(models.Model): name = models.CharField(max_length='20',blank=True) class Child(Parent): pass
I want to get the result of Child.objects.all() but I do not want to
use Child.
I want to use Parent instead, which I tried to do with:
Parent.objects.filter(child__isnull=False) # not work, but should
Which doesn't work and gives the result of Product.objects.all() instead.
However If I do the following, it works:
Parent.objects.exclude(child__isnull=True) # work
If I insist on using:
Parent.objects.filter(child__isnull=False) # will work if do below
Then it will work if I use the OneToOneField for Child.
class Child(models.Model): parent = models.OneToOneField(Parent)
I expect the query to also work with Model Inheritance as well.
Also discussed in http://groups.google.com/group/django-users/browse_thread/thread/9e20b70811f386a8
Change History (5)
comment:1 by , 13 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 13 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
UI/UX: | unset |
comment:3 by , 13 years ago
Cc: | added |
---|
The problem is in trim_joins()
method of the Query
class. This method just trims inner join because the condition is "pk of Child is not null", "pk of Child" is actually a foreign key to parent so trimmer reduces join chain and we finally gets "pk of Parent is not null".
We can avoid it by skipping trimming for the isnull lookup. We also can avoid it by not trimming at all. I think that this problem need better recognition and thinkwork, as it is not only about model inheritance. This behaviour is also reproducible if one has ForeignKey(SomeModel, primary_key=True)
.
comment:4 by , 13 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
comment:5 by , 9 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Fixed by #15316 / 2e56066a5b93b528fbce37285bac591b44bc6ed7 which is in Django 1.4+.
The test I used to bisect is:
Parent.objects.create() self.assertEqual(Parent.objects.filter(child__isnull=False).count(), 0) self.assertEqual(Parent.objects.filter(child__isnull=True).count(), 1)
I'm accepting the bug for two reasons:
Parent.objects.filter(child__isnull=False)
andParent.objects.exclude(child__isnull=True)
should always give the same results.OneToOneField
should give the same results — at least that's what the docs say:https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance
It sounds like the wrong kind of join is used.