5

複数の OneToOneField リレーションシップで select_related を実行しようとすると、奇妙なエラーが発生します。たとえば、ターゲット フィールドが孫のサブクラスである場合です。何が起こっているのかを理解するのを手伝ってくれる人が欲しいです (または、これが 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 のバグですか、それとも私は何かを理解していませんか?

4

2 に答える 2

0

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'

私はそれが答えではないことを知っています、そして私はそれをどうすればいいのか分かりません。しかし、基本的に、小文字はモデルにフィールドがないことを意味しないように思われることがわかりました。

于 2011-08-10T19:20:49.883 に答える
0

同じ問題が発生しましたが、モデル構造がかなり異なります。

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がnullでないオブジェクトのみが表示されます。しかし、私が書くとき

A.objects.select_related('b__c').all()

Django ORMは、Cがnullのオブジェクトを含むすべてのAオブジェクトを返します。

私にはバグのように思えますが、select_relatedはフィルターとして機能しないはずです。

于 2011-08-27T18:33:58.257 に答える