5

Tôi nhận được một lỗi lạ khi cố gắng select_related qua nhiều mối quan hệ OneToOneField, ví dụ: trong trường hợp trường mục tiêu là một lớp con cháu. Tôi muốn một người nào đó giúp tôi hiểu những gì đang xảy ra (hoặc xác nhận rằng đây là một lỗi ở Django).Django select_related với các trường được chỉ định ngắt trên nhiều mối quan hệ một đến một

Minh họa:

# models.py 
from django.db import models 

class A(models.Model): 
    pass 

class B(A): 
    pass 

class C(B): 
    pass 

đơn giản đủ, đúng không? Bây giờ tôi mở vỏ Django bằng một cơ sở dữ liệu sạch:

>>> C().save() 
>>> A.objects.select_related('b__c') 
[] 

Chờ đợi, cái gì? Tại sao bộ truy vấn đó trống? Kiểm tra sanity nhanh:

>>> A.objects.select_related('b')[0].b.c 
<C: C object> 

Vậy tại sao cuộc gọi select_related không hoạt động? Vâng, hãy xem điều này:

>>> 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 
>>> 

Vì vậy, đây có phải là lỗi Django hay tôi không hiểu điều gì đó?

+1

Do sự im lặng về vấn đề này, tôi đã gửi một lỗi: https://code.djangoproject.com/ticket/16572 – rfrankel

+0

gặp vấn đề tương tự. hành vi kỳ lạ, có vẻ như một lỗi django thực sự. –

Trả lời

0

tôi thêm name = CharField đến A và chạy các bài kiểm tra sau trong vỏ:

>>> 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' 

Tôi biết nó không phải là một câu trả lời, và tôi không biết phải làm gì với nó. Nhưng về cơ bản tôi tìm thấy chữ thường không có nghĩa là bất cứ điều gì không có các trường trong các mô hình.

+0

Chữ thường là các trường được sử dụng để downcasting đối tượng thành một thể hiện của lớp con. Ví dụ, A.objects.get (id = 2) .b sẽ trả về đối tượng B với id = 2 nếu nó tồn tại, và đưa ra một ngoại lệ khác. Tương tự như vậy, A.objects.get (id = 3) .b.c sẽ trả về một đối tượng C (giả định nó tồn tại). Vé tôi đã gửi thực sự được xác nhận và chấp nhận, vì vậy tôi nghĩ đây là lỗi. – rfrankel

0

Got cùng một vấn đề, nhưng với một chút cấu trúc hoàn toàn khác mô hình:

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): 
.... 

Vì vậy, khi tôi viết

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

Tôi không thấy tất cả A - các đối tượng, chỉ những nơi C không phải là rỗng. Tuy nhiên, khi tôi viết

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

Django ORM trả về cho tôi tất cả đối tượng A, bao gồm cả các đối tượng trong đó C là rỗng.

Dường như một lỗi đối với tôi, select_related không hoạt động như một bộ lọc.

Các vấn đề liên quan