Opened 4 years ago

Last modified 4 years ago

#16135 new Bug

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


Example model:

   class Parent(models.Model): 
        name = models.CharField(max_length='20',blank=True) 
    class Child(Parent): 

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

Change History (4)

comment:1 Changed 4 years ago by aaugustin

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

I'm accepting the bug for two reasons:

  • Parent.objects.filter(child__isnull=False) and Parent.objects.exclude(child__isnull=True) should always give the same results.
  • Model inheritance and OneToOneField should give the same results — at least that's what the docs say:

    The inheritance relationship introduces links between the child model and each of its parents (via an automatically-created OneToOneField).

It sounds like the wrong kind of join is used.

comment:2 Changed 4 years ago by desh

  • Owner changed from nobody to desh
  • Status changed from new to assigned
  • UI/UX unset

comment:3 Changed 4 years ago by desh

  • Cc nikolay@… 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 Changed 4 years ago by desh

  • Owner desh deleted
  • Status changed from assigned to new
Note: See TracTickets for help on using tickets.
Back to Top