Django select_与多个一对一关系中指定的中断字段相关

Django select_与多个一对一关系中指定的中断字段相关,django,django-queryset,django-orm,django-select-related,django-inheritance,Django,Django Queryset,Django Orm,Django Select Related,Django Inheritance,我在尝试选择多个OneToOneField关系上的_related时遇到了一个奇怪的错误,例如,在目标字段是孙子子类的情况下。我希望有人能帮助我理解发生了什么(或者确认这是Django中的一个bug) 说明: # models.py from django.db import models class A(models.Model): pass class B(A): pass class C(B): pass 很简单,对吧?现在,我用一个干净的数据库打开Djan

我在尝试选择多个OneToOneField关系上的_related时遇到了一个奇怪的错误,例如,在目标字段是孙子子类的情况下。我希望有人能帮助我理解发生了什么(或者确认这是Django中的一个bug)

说明:

# models.py
from django.db import models

class A(models.Model):
    pass

class B(A):
    pass

class C(B):
    pass
很简单,对吧?现在,我用一个干净的数据库打开Django shell:

>>> C().save()
>>> A.objects.select_related('b__c')
[]
等等,什么?为什么queryset是空的?快速健康检查:

>>> A.objects.select_related('b')[0].b.c
<C: C object>
>A.objects。选择与之相关的('b')[0]。b.c
那么,为什么与select_相关的调用不起作用呢?好,看这个:

>>> 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
>>> 
>>>A.objects.选择相关('b_uuuc')。\uu iter\uuu().下一步()
... 
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/opt/webapps/asdf/lib/python2.6/site packages/django/db/models/query.py”,第107行,在结果文件中
self._fill_cache()
文件“/opt/webapps/asdf/lib/python2.6/site packages/django/db/models/query.py”,第772行,在缓存中
self.\u result\u cache.append(self.\u iter.next())
迭代器中的文件“/opt/webapps/asdf/lib/python2.6/site packages/django/db/models/query.py”,第273行
对于编译器.results\u iter()中的行:
文件“/opt/webapps/asdf/lib/python2.6/site packages/django/db/models/sql/compiler.py”,第680行,结果文件
对于self.execute_sql(多)中的行:
文件“/opt/webapps/asdf/lib/python2.6/site packages/django/db/models/sql/compiler.py”,第725行,在execute_sql中
sql,params=self.as_sql()
as_sql中的文件“/opt/webapps/asdf/lib/python2.6/site packages/django/db/models/sql/compiler.py”,第58行
self.pre_sql_setup()
文件“/opt/webapps/asdf/lib/python2.6/site packages/django/db/models/sql/compiler.py”,第29行,在预sql设置中
self.fill_相关_选择()
文件“/opt/webapps/asdf/lib/python2.6/site packages/django/db/models/sql/compiler.py”,第661行,填写相关选项
已使用、下一个、受限、新(可为空)
文件“/opt/webapps/asdf/lib/python2.6/site packages/django/db/models/sql/compiler.py”,第617行,填写相关选项
链=选择获取基本链(f.rel.to)
文件“/opt/webapps/asdf/lib/python2.6/site packages/django/db/models/options.py”,第452行,在get_base_链中
%模型。\元模块\名称,)
TypeError:“b”不是此模型的祖先
>>> 

那么,这是一个Django bug,还是我不了解什么?

我在a中添加了name=CharField,并在shell中运行了以下测试:

>>> 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'
>a=a(name='a_object')
>>>a.保存()
>>>b=b(name='b_object')
>>>b.保存()
>>>c=c(name='c_object')
>>>c.保存()
>>>A.objects.all()
[, ]
>>>B.objects.all()
[, ]
>>>C.objects.all()
[]
>>>A.对象。选择与对象相关的('b\u\c')
[]
>>>A.objects.选择与之相关的('b\u c')。\u iter\u().next()
回溯。。。。
...
TypeError:“b”不是此模型的祖先
>>>d=A.objects。选择与之相关的('B\u\C')
>>>d项:
...     打印项目名称
... 
物体
b_对象
c_对象
>>>test=A.objects。选择相关('B_uuuuuc')。\uuuuu iter\uuuuuu()。下一步()
>>>test.name
u'a_object'

我知道这不是答案,我也不知道该怎么理解。但基本上,我发现小写字母似乎并不表示模型中没有字段的任何内容。

也有同样的问题,但模型结构有很大不同:

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返回所有A对象,包括C为null的对象


对我来说似乎是一个bug,select_related不应该用作过滤器。

鉴于对此保持沉默,我提出了一个bug:陷入了完全相同的问题。奇怪的行为,看起来确实像django bug。小写字母是用于将对象向下转换为子类实例的字段。例如,A.objects.get(id=2).b将返回id=2的b对象(如果存在),否则将引发异常。同样,A.objects.get(id=3).b.c将返回一个c对象(假设它存在)。我提交的票实际上已经确认并接受了,所以我认为这是一个错误。