Opened 8 years ago

Closed 8 years ago

Last modified 5 years ago

#10955 closed (fixed)

`select_related()` doesn't work with proxy models.

Reported by: Tai Lee Owned by: Jacob
Component: Database layer (models, ORM) Version: master
Severity: Keywords: proxy model select_related
Cc: Armin Ronacher Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

I get a traceback if I call get() on a queryset for a proxy model which is using select_related(), or simply no objects if I try to access the queryset itself.

# models

class Country(models.Model):
	name = models.CharField(max_length=50, unique=True)

class State(models.Model):
	name = models.CharField(max_length=50)
	country = models.ForeignKey(Country)

	def __unicode__(self):
		return self.name

class StateProxy(State):
	class Meta:
		proxy = True

# interactive shell

>>> country = Country.objects.create(name='Australia')
>>> state = State.objects.create(name='New South Wales', country=country)

>>> State.objects.select_related()
[<State: New South Wales>]

>>> StateProxy.objects.select_related()
[]

# should have got [<State: New South Wales>]

>>> StateProxy.objects.get(name='New South Wales')
<StateProxy: New South Wales>

>>> StateProxy.objects.select_related().get(name='New South Wales')
Traceback (most recent call last):
  File "<console>", line 1, in ?
  File "/path/to/django/db/models/manager.py", line 120, in get
    return self.get_query_set().get(*args, **kwargs)
  File "/path/to/django/db/models/query.py", line 269, in get
    num = len(clone)
  File "/path/to/django/db/models/query.py", line 68, in __len__
    self._result_cache = list(self.iterator())
  File "/path/to/django/db/models/query.py", line 207, in iterator
    for row in self.query.results_iter():
  File "/path/to/django/db/models/sql/query.py", line 276, in results_iter
    for rows in self.execute_sql(MULTI):
  File "/path/to/django/db/models/sql/query.py", line 2301, in execute_sql
    sql, params = self.as_sql()
  File "/path/to/django/db/models/sql/query.py", line 384, in as_sql
    self.pre_sql_setup()
  File "/path/to/django/db/models/sql/query.py", line 571, in pre_sql_setup
    self.fill_related_selections()
  File "/path/to/django/db/models/sql/query.py", line 1361, in fill_related_selections
    lhs_col = int_opts.parents[int_model].column
AttributeError: 'NoneType' object has no attribute 'column'

# should have got <StateProxy: New South Wales>

Attachments (3)

10955-proxy_select_related-r10643.diff (1.5 KB) - added by Tai Lee 8 years ago.
10955_proxy_select_related_r10697.diff (9.6 KB) - added by Clément Nodet 8 years ago.
initial patch, fixes select_related + filter on proxy, and type issue on subproxy
10955_proxy_select_related_no_manager_fix_r10697.diff (8.2 KB) - added by Clément Nodet 8 years ago.
patch without manager fix (covered by #10953)

Download all attachments as: .zip

Change History (12)

Changed 8 years ago by Tai Lee

Changed 8 years ago by Clément Nodet

initial patch, fixes select_related + filter on proxy, and type issue on subproxy

comment:1 Changed 8 years ago by Clément Nodet

Has patch: set

There was a possible bug on subproxy (proxy of proxy) manager creation, giving the following results on the API tests:

>>> MyPersonProxy.objects.all() 
[<MyPerson: Bazza del Frob>, <MyPerson: Foo McBar>, <MyPerson: homer>]

bypassed that by forcing manager inheritance (of abstract and concrete managers) from the model base (before skipping proxy for populating fields), but not sure this is the needed behaviour here.

Patch mostly adresses proxy skipping when joining fields (traversing multiple levels of nested proxies) and ancestors chain when populating select fields on proxy models. Added also some regression tests on proxy + model inheritance, subproxy select_related().filter(...), and ForeignKey( proxy / subproxy )

comment:2 Changed 8 years ago by Alex Gaynor

I have a patch on another issue (I forget the number) that solves the manager issue.

Changed 8 years ago by Clément Nodet

patch without manager fix (covered by #10953)

comment:3 Changed 8 years ago by Clément Nodet

@Alex:

I suppose #10953 , attached a new patch with no modifications in django.models.base.ModelBase

comment:4 Changed 8 years ago by Armin Ronacher

Owner: changed from nobody to Armin Ronacher

comment:5 Changed 8 years ago by Armin Ronacher

The patch for this and #10953 is attached to my github repo: http://github.com/mitsuhiko/django/tree/ticket-10953

comment:6 Changed 8 years ago by Jacob

Owner: changed from Armin Ronacher to Jacob
Status: newassigned

comment:7 Changed 8 years ago by Armin Ronacher

Cc: Armin Ronacher added

comment:8 Changed 8 years ago by Jacob

Resolution: fixed
Status: assignedclosed

(In [10738]) Fixed #10953, #10955: proxies of proxies now work correctly, though I still don't quite understand why you'd want to do such a thing. Thanks, Armin Ronacher.

comment:6 Changed 5 years ago by Jacob

milestone: 1.1

Milestone 1.1 deleted

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