Django OneToOne反向关系当空

时间:2015-11-09 13:46:32

标签: python django

我使用Django 1.8.3和Rest Framework以及json-api(https://github.com/django-json-api/django-rest-framework-json-api)。我有这个OneToOne关系:

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,我无法使用异常处理等,因为我没有明确地调用访问数据

2 个答案:

答案 0 :(得分:6)

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错误。

我给你的例子与框架中的设计决策有关,而不是错误。此外,重要的事实并不是它们是新实例,而是它们具有引用(或者没有O2O分别引用它们)。总结:

  • 检索null = False(命名参数的默认值)如果字段为None,则FK字段将引发target.DoesNotExist(当然实例尚未保存,因为此类字段不允许使用None)。这对于您在clean(self)中验证其字段的新创建的模型尤其如此,并且用户可能没有填充此类字段,您可以检索它。这同样适用于OneToOne。
  • 检索OneToOne的反面,当直接边(将有)值为None时,将引发source.DoesNotExist错误。

答案 1 :(得分:1)

根据您的定义,每个CalendarBlock实例都会vehiclecheck为null或不为null,同样不适用于VehicleCheck个实例,您将需要检查首先,这样你就可以避免RelatedObjectDoesNotExist。你可以这样做:

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