Django检查相关对象是否存在错误:RelatedObjectDoesNotExist

Pro*_*eus 60 python django

has_related_object我的模型中有一个方法需要检查相关对象是否存在

class Business(base):
      name =  models.CharField(max_length=100, blank=True, null=True)

  def has_related_object(self):
        return (self.customers is not None) and (self.car is not None)


class Customer(base):
      name =  models.CharField(max_length=100, blank=True, null=True)
      person = models.OneToOneField('Business', related_name="customer")
Run Code Online (Sandbox Code Playgroud)

但我得到错误:

Business.has_related_object()

RelatedObjectDoesNotExist:业务没有客户.

mrt*_*rts 124

使用hasattr(self, 'customers')以避免异常支票在Django文档建议:

def has_related_object(self):
    return hasattr(self, 'customers') and self.car is not None
Run Code Online (Sandbox Code Playgroud)

  • 除了在这种情况下请求许可同样容易,并且将所有内容都包含在 try 中:except 子句往往会掩盖不相关的错误,使问题更难调试。 (8认同)
  • 一般来说在python中它是EAFP.https://docs.python.org/3/glossary.html#term-eafp (4认同)

sch*_*ngt 57

这是因为ORM必须转到数据库检查是否customer存在.由于它不存在,它引发了一个例外.

您必须将方法更改为以下内容:

def has_related_object(self):
    has_customer = False
    try:
        has_customer = (self.customers is not None)
    except Customer.DoesNotExist:
        pass
    return has_customer and (self.car is not None)
Run Code Online (Sandbox Code Playgroud)

我不知道情况self.car所以我会留给你调整它,如果它需要它.

附注:如果您在具有ForeignKeyField或OneToOneField的模型上执行此操作,则可以执行以下操作以避免数据库查询.

def has_business(self):
    return self.business_id is not None
Run Code Online (Sandbox Code Playgroud)

  • @AntoinePinsard,在这种情况下使用列名会更快,因为Django不会尝试在基础查询中进行联接。Django鼓励这些做法以进行必要的优化。https://docs.djangoproject.com/zh-CN/2.1/topics/db/optimization/#use-foreign-key-values-direct (3认同)
  • 请注意,根据文档(https://docs.djangoproject.com/en/1.9/ref/models/fields/#database-representation),“[...]你的代码不应该处理数据库列名称,除非您编写自定义 SQL。您将始终处理模型对象的字段名称。”。 (2认同)
  • 如果您尝试查询一个对象的关系之一,为什么 Django 不直接返回“None”?抛出异常似乎太过分了。 (2认同)
  • 这样做可能是为了涵盖具有可为空字段的情况。当允许为 null 时,它返回 None。如果不是,则会引发异常。 (2认同)

Meh*_*are 10

尽管这是一个老问题,但我认为这对于希望处理此类异常的人很有帮助,特别是当您想要检查 OneToOne 关系时。

我的解决方案是使用ObjectDoesNotExistfrom django.core.exceptions

from django.core.exceptions import ObjectDoesNotExist

class Business(base):
      name =  models.CharField(max_length=100, blank=True, null=True)

    def has_related_object(self):
        try:
            self.customers
            self.car
            return True
        except ObjectDoesNotExist:
            return False


class Customer(base):
      name =  models.CharField(max_length=100, blank=True, null=True)
      person = models.OneToOneField('Business', related_name="customer")

Run Code Online (Sandbox Code Playgroud)