检查 Django 中是不是存在 OneToOne 关系

Posted

技术标签:

【中文标题】检查 Django 中是不是存在 OneToOne 关系【英文标题】: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 上似乎可以正常工作。 【参考方案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

【讨论】:

以上是关于检查 Django 中是不是存在 OneToOne 关系的主要内容,如果未能解决你的问题,请参考以下文章

Django:为啥要为 UserProfile 创建 OneToOne 而不是子类化 auth.User?

如何检查Django中是不是存在模板?

检查列表 django 模板中是不是存在

检查以检查 Django 中是不是存在数据库表?

Django:如何检查自定义小部件定义中是不是存在字段错误?

检查图像是不是存在于 Django 模板中