2015-11-09 108 views
1

我使用Django 1.8.3與Rest Framework和json-api(https://github.com/django-json-api/django-rest-framework-json-api)。我有這個OneToOne關係:Django OneToOne反向關係DoesNotExists當爲空

class CalendarBlock(models.Model): 
     vehiclecheck = models.OneToOneField('vehiclecheck.VehicleCheck', 
             null=True, blank=True, 
             related_name='calendar_block' 
    ) 

    [...] 


class VehicleCheck(models.Model): 
     [...] 

現在問題是,關係可以是「空的」。其中一期工程,從CalendarBlock去Vehiclecheck的時候,而不是在相反的關係:

In [1]: from vehiclecheck.models import VehicleCheck 

In [2]: from dispo_calendar.models import CalendarBlock 

In [3]: CalendarBlock.objects.first().vehiclecheck 

In [4]: # no problem here 

In [5]: VehicleCheck.objects.first().calendar_block 
Out[5]: <CalendarBlock: CalendarBlock object> 

In [6]: VehicleCheck.objects.get(pk=398).calendar_block 
--------------------------------------------------------------------------- 
RelatedObjectDoesNotExist     Traceback (most recent call last) 
<ipython-input-6-65d3178686f5> in <module>() 
----> 1 VehicleCheck.objects.get(pk=398).calendar_block 

/home/sh/gitty/work/tcs_cardispo2_backend/.venv/lib/python3.5/site-packages/django/db/models/fields/related.py in __get__(self, instance, instance_type) 
    468     "%s has no %s." % (
    469      instance.__class__.__name__, 
--> 470      self.related.get_accessor_name() 
    471    ) 
    472   ) 

RelatedObjectDoesNotExist: VehicleCheck has no calendar_block. 

編輯:我的主要問題是,由於我使用rest_framework,我不能使用異常處理或類似因爲我不明確地調用訪問數據。

回答

1

CalendarBlock實例都會有vehiclecheck null或按照自己的定義不爲空,同樣不適用於VehicleCheck情況下,你得去檢查,首先這樣可以儘量避免的RelatedObjectDoesNotExist。你可以這樣做:

vehicle_check = VehicleCheck.objects.get(pk=398) 
if hasattr(vehicle_check, 'calendar_block'): 
    calendar_block = vehicle_check.calendar_block 
+0

我不能這樣做,因爲我使用序列化程序和ModelViewSet,所以數據被這些庫「自動」獲取。 – arsenbonbon

3

Django有關於OneToOne和ForeignKey相關字段的一些問題。具體假設:

class A(Model): 
    # assume these models exist 
    b = ForeignKey(B, null=True) 
    c = ForeignKey(C) 
    d = OneToOneField(D, null=True, related_name="a") 
    e = OneToOneField(E, related_name="a") 
  • 如果要檢索A()B或A()d,你就會得到無。
  • 如果您想檢索A()。c,則會引發C.DoesNotExist錯誤。
  • 如果您想檢索A().e,則會引發E.DoesNotExist錯誤。如果你想檢索B(),a_set.all()或C().a_set.all(),你會得到一個沒有元素的查詢集。
  • 如果您想檢索D().a或E().a,則會引發A.DoesNotExist錯誤。

我給你的例子與框架中的設計決定有關,而不是bug。另外,重要的事實並不是它們是新實例,而是它們有引用(或者沒有O2O分別引用它們)。摘要:

  • 檢索空=假(名爲參數默認值)FK領域將引發target.DoesNotExist如果該字段爲None(當然還有實例尚未保存,因爲沒有將不被允許對於這樣的領域)。對於您在clean(self)中驗證其字段的新創建的模型而言,這尤其適用,並且用戶可能沒有填充此字段並檢索它。 OneToOne也是如此。
  • 檢索OneToOne的反面,當直接邊有(將)值爲None將引發source.DoesNotExist錯誤。