Opened 10 years ago

Closed 10 years ago

#23467 closed Bug (needsinfo)

Inconsistent behavior when filtering by inherited models when using a proxy model

Reported by: Luis A. Arce Owned by: nobody
Component: Database layer (models, ORM) Version: 1.6
Severity: Normal Keywords: inherit, proxy, model, queryset, filter
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Luis A. Arce)

Having the following scenario:

import django.db.models  as db_models

class ParentModel(db_models.Model):
    pass

class ChildModel(ParentModel):
    pass

class ParentProxyModel(ParentModel):
    pass

    class Meta:
        proxy=True

I can filter the ParentModel in terms of existing inheriting children, but not ParentProxyModel. An example:

Python 2.7.5 (default, Jun 25 2014, 10:19:55) 
[GCC 4.8.2 20131212 (Red Hat 4.8.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)

>>> a = ParentModel.objects.create()
>>> b = ChildModel.objects.create()

>>> ParentModel.objects.filter(childmodel=None)
[<ParentModel: ParentModel object>]

>>> ParentProxyModel.objects.filter(childmodel=None)

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/manager.py", line 163, in filter
    return self.get_queryset().filter(*args, **kwargs)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/query.py", line 590, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/query.py", line 608, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1198, in add_q
    clause = self._add_q(where_part, used_aliases)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1234, in _add_q
    current_negated=current_negated)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1100, in build_filter
    allow_explicit_fk=True)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1357, in setup_joins
    names, opts, allow_many, allow_explicit_fk)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1277, in names_to_path
    "Choices are: %s" % (name, ", ".join(available)))
FieldError: Cannot resolve keyword 'childmodel' into field. Choices are: id, parentmodel_ptr
>>> 

Change History (4)

comment:1 by Luis A. Arce, 10 years ago

Description: modified (diff)

comment:2 by Luis A. Arce, 10 years ago

Maybe the problem is easy to fix. There you have a couple of examples I was able to run after a small hack:

Python 2.7.5 (default, Jun 25 2014, 10:19:55) 
[GCC 4.8.2 20131212 (Red Hat 4.8.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)

>>> ParentModel.objects.filter(childmodel=None)
[<ParentModel: ParentModel object>]

>>> ParentProxyModel.objects.filter(childmodel=None)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/manager.py", line 163, in filter
    return self.get_queryset().filter(*args, **kwargs)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/query.py", line 590, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/query.py", line 608, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1198, in add_q
    clause = self._add_q(where_part, used_aliases)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1234, in _add_q
    current_negated=current_negated)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1100, in build_filter
    allow_explicit_fk=True)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1357, in setup_joins
    names, opts, allow_many, allow_explicit_fk)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1277, in names_to_path
    "Choices are: %s" % (name, ", ".join(available)))
FieldError: Cannot resolve keyword 'childmodel' into field. Choices are: id

>>> qs = ParentModel.objects.filter(childmodel=None)
>>> qs.model = ParentProxyModel
>>> qs
[<ParentProxyModel: ParentProxyModel object>]
>>> 
Python 2.7.5 (default, Jun 25 2014, 10:19:55) 
[GCC 4.8.2 20131212 (Red Hat 4.8.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)

>>> ParentModel.objects.annotate(childmodel_count=Count('childmodel')).values_list('childmodel')
[(None,), (2L,)]

>>> ParentProxyModel.objects.annotate(childmodel_count=Count('childmodel')).values_list('childmodel')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/manager.py", line 169, in annotate
    return self.get_queryset().annotate(*args, **kwargs)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/query.py", line 714, in annotate
    is_summary=False)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 985, in add_aggregate
    field_list, opts, self.get_initial_alias())
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1357, in setup_joins
    names, opts, allow_many, allow_explicit_fk)
  File "/home/ajaest/Code/pfc/src/.env/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1277, in names_to_path
    "Choices are: %s" % (name, ", ".join(available)))
FieldError: Cannot resolve keyword 'childmodel' into field. Choices are: id

>>> qs = ParentModel.objects.annotate(childmodel_count=Count('childmodel'))
>>> qs.model = ParentProxyModel
>>> qs.values_list('childmodel_count')
[(0,), (1,)]

>>> 

Both examples work even if the database was not hit (and therefore the cache not filled)

comment:3 by Shai Berger, 10 years ago

I don't see anything "inconsistent" here -- it simply seems that proxy models do not inherit the reverse one-to-one relations added by multi-table child models.

Can you verify if they inherit other reverse relations?

Also, can you check against 1.7? Django 1.6 has entered the "critical fixes only" phase of its life.

comment:4 by Tim Graham, 10 years ago

Resolution: needsinfo
Status: newclosed

@ajaest, please reopen if you can follow-up to Shai's reply.

Note: See TracTickets for help on using tickets.
Back to Top