Django select_related с указанными полями разрывается между несколькими отношениями один к одному
Я получаю странную ошибку, пытаясь выбрать select_related для нескольких отношений OneToOneField, например, в случае, когда целевое поле является подклассом внука. Я хотел бы, чтобы кто-то помог мне понять, что происходит (или подтвердить, что это ошибка в Django).
Иллюстрация:
# models.py
from django.db import models
class A(models.Model):
pass
class B(A):
pass
class C(B):
pass
Достаточно просто, верно? Теперь я открываю оболочку Django с чистой базой данных:
>>> C().save()
>>> A.objects.select_related('b__c')
[]
Чего ждать? Почему этот набор запросов пуст? Быстрая проверка работоспособности:
>>> A.objects.select_related('b')[0].b.c
<C: C object>
Так почему же не работает вызов select_related? Ну, смотрите это:
>>> A.objects.select_related('b__c').__iter__().next()
...
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/opt/webapps/asdf/lib/python2.6/site-packages/django/db/models/query.py", line 107, in _result_iter
self._fill_cache()
File "/opt/webapps/asdf/lib/python2.6/site-packages/django/db/models/query.py", line 772, in _fill_cache
self._result_cache.append(self._iter.next())
File "/opt/webapps/asdf/lib/python2.6/site-packages/django/db/models/query.py", line 273, in iterator
for row in compiler.results_iter():
File "/opt/webapps/asdf/lib/python2.6/site-packages/django/db/models/sql/compiler.py", line 680, in results_iter
for rows in self.execute_sql(MULTI):
File "/opt/webapps/asdf/lib/python2.6/site-packages/django/db/models/sql/compiler.py", line 725, in execute_sql
sql, params = self.as_sql()
File "/opt/webapps/asdf/lib/python2.6/site-packages/django/db/models/sql/compiler.py", line 58, in as_sql
self.pre_sql_setup()
File "/opt/webapps/asdf/lib/python2.6/site-packages/django/db/models/sql/compiler.py", line 29, in pre_sql_setup
self.fill_related_selections()
File "/opt/webapps/asdf/lib/python2.6/site-packages/django/db/models/sql/compiler.py", line 661, in fill_related_selections
used, next, restricted, new_nullable)
File "/opt/webapps/asdf/lib/python2.6/site-packages/django/db/models/sql/compiler.py", line 617, in fill_related_selections
chain = opts.get_base_chain(f.rel.to)
File "/opt/webapps/asdf/lib/python2.6/site-packages/django/db/models/options.py", line 452, in get_base_chain
% model._meta.module_name,)
TypeError: 'b' is not an ancestor of this model
>>>
Итак, это ошибка в Django или я чего-то не понимаю?
2 ответа
У меня та же проблема, но с совершенно другой структурой модели:
class A(models.Model):
b = models.ForeignKey(B)
....
class B(models.Model):
....
class C(models.Model):
b = models.OneToOneField(B)
d = models.OneToOneField(D)
....
class D(models.Model):
....
Итак, когда я пишу
A.objects.select_related('b__c__d').all()
Я не вижу все A -объекты, только те, где C не нуль. Тем не менее, когда я пишу
A.objects.select_related('b__c').all()
Django ORM возвращает мне все объекты A, включая те, где C равно нулю.
Для меня это похоже на ошибку, select_related не должен работать как фильтр.
Я добавил name=CharField в A и запустил следующие тесты в оболочке:
>>> a = A(name='a_object')
>>> a.save()
>>> b = B(name='b_object')
>>> b.save()
>>> c = C(name='c_object')
>>> c.save()
>>> A.objects.all()
[<A: A object>, <A: A object>, <A: A object>]
>>> B.objects.all()
[<B: B object>, <B: B object>]
>>> C.objects.all()
[<C: C object>]
>>> A.objects.select_related('b__c')
[]
>>> A.objects.select_related('b__c').__iter__().next()
Traceback ....
...
TypeError: 'b' is not an ancestor of this model
>>> d = A.objects.select_related('B__C')
>>> for item in d:
... print item.name
...
a_object
b_object
c_object
>>> test = A.objects.select_related('B__C').__iter__().next()
>>> test.name
u'a_object'
Я знаю, что это не ответ, и я не знаю, что с этим делать. Но в основном я обнаружил, что строчные буквы ничего не значат без полей в моделях.