【问题标题】:Check if a OneToOne relation exists in Django检查 Django 中是否存在 OneToOne 关系
【发布时间】:2014-11-14 16:49:05
【问题描述】:

现在我使用的是 django 1.6

我有两个模型与OneToOneField 相关。

class A(models.Model):
    pass

class B(models.Model):
    ref_a = models.OneToOneField(related_name='ref_b', null=True)

首先看我指出问题的代码:

a1 = A.objects.create()
a2 = A.objects.create()
b1 = B.objects.create()
b2 = B.objects.create(ref_a=a2)

# then I call:
print(a1.ref_b)  # DoesNotExist Exception raised
print(a2.ref_b)  # returns b2
print(b1.ref_a)  # returns None
print(b2.ref_a)  # returns a2

现在的问题是,如果我要检查一个A 对象,判断它是否存在引用它的B 对象。我该怎么办?

我尝试的有效方法只是尝试捕获异常,但是还有其他更漂亮的方法吗?


我的努力:

1 - 下面的代码有效,但是太丑了!

b = None
try:
    b = a.ref_b
except:
    pass

2 - 我也尝试检查 a 中的属性,但不起作用:

b = a.ref_b if hasattr(a, 'ref_b') else None

朋友们,你们也遇到同样的问题吗?请指点一下,谢谢!

【问题讨论】:

  • 我认为这对你有用,请记住至少在 2 后更改你的班级名称。 b = hasattr(a_class_object, 'b class') 和 a.ref_b 或无。我正在使用相同的产品并为我工作。
  • @Yogesh 我不太明白,能否请您发布更详细的解决方案?
  • hasattr 在 Django 1.8.17 和 Python 2 上似乎可以正常工作。

标签: python django model one-to-one


【解决方案1】:

因此,您至少有两种检查方法。 首先是创建try/catch块来获取属性,其次是使用hasattr

class A(models.Model):
   def get_B(self):
       try:
          return self.b
       except:
          return None

class B(models.Model):
   ref_a = models.OneToOneField(related_name='ref_b', null=True)

请尽量避免裸露的except: 子句。它可以隐藏一些problems

第二种方式是:

class A(models.Model):
    def get_B(self):
       if(hasattr(self, 'b')):
           return self.b
       return None

class B(models.Model):
    ref_a = models.OneToOneField(related_name='ref_b', null=True)

在这两种情况下,您都可以毫无例外地使用它:

a1 = A.objects.create()
a2 = A.objects.create()
b1 = B.objects.create()
b2 = B.objects.create(ref_a=a2)

# then I call:
print(a1.get_b)  # No exception raised
print(a2.get_b)  # returns b2
print(b1.a)  # returns None
print(b2.a)  # returns a2

没有其他办法,因为抛出异常是 Django One to One relationships 的默认行为。

这是从官方文档中处理它的示例。

>>> from django.core.exceptions import ObjectDoesNotExist
>>> try:
>>>     p2.restaurant
>>> except ObjectDoesNotExist:
>>>     print("There is no restaurant here.")
There is no restaurant here.

【讨论】:

  • 很好的答案!谢谢!
【解决方案2】:

各个模型类提供了一个更具体的例外,称为 DoesNotExist,它扩展了 ObjectDoesNotExist。我的偏好是这样写:

b = None
try:
    b = a.ref_b
except B.DoesNotExist:
    pass

【讨论】:

  • 为什么不把b = None 放在except 子句中? (保存一行)
【解决方案3】:

hasattr 与 Django1.11 配合得很好! 您可以使用getattr 来获得更短的版本:

getattr(self, 'field', default)

你的情况

b = getattr(a, 'ref_b', None)

https://docs.python.org/3.6/library/functions.html#getattr

【讨论】:

    猜你喜欢
    • 2020-05-14
    • 1970-01-01
    • 2020-06-21
    • 2015-01-29
    • 2014-08-24
    • 2014-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多