首页 > 解决方案 > Django OneToOneField 允许在线一个参考

问题描述

我正在尝试创建一对一的引用,并希望确保该引用不允许用于另一个模型或实例。

例如

假设我有一个地址模型、个人模型和公司模型

Person 有一个 OneToOneField 字段到 Address 公司也有一个 OneToOneField 字段到 Address

address=Address(data="some address")
company=Company(name="some company",address=address)
person=Person(name="my name",address=address)

楷模:

class Address(models.Model):
  data = models.CharField(max_length=255, blank=True, null=True)
class Company(models.Model):
  name = models.CharField(max_length=255, blank=True, null=True)
  address=models.OneToOneField(Address,on_delete=models.CASCADE)
class Person(models.Model):
  name = models.CharField(max_length=255, blank=True, null=True)
  address=models.OneToOneField(Address,on_delete=models.CASCADE)

我希望系统对此抛出错误,因为我将相同的地址设置为 2 个不同的模型。

如果我删除地址,这也会删除个人和公司。

通常你会用代码捕捉到这一点,而不会犯这样的愚蠢错误。但是系统可以捕捉到它,因为它是一对一的吗?

标签: pythondjangomodel

解决方案


在删除的情况下,您可以使用on_delete=models.PROTECT. 在另一种情况下,您可以添加unique=True一个人 id = 1 将有一个地址 id = 1,一个人 id = 2 不能再有一个地址 id = 1。但它只能解决一个模型:
address=models.ForeignKey(Address, unique=True, on_delete=models.PROTECT)

一种新方法是创建一个模型来引用公司和个人的地址,并能够禁止创建具有相同地址 id 的内容:

class AddressExample(models.Model):
    id_address = models.ForeignKey(Address, unique=True,on_delete=models.PROTECT)
    id_person = models.ForeignKey(Person, blank=True, null=True, unique=True, on_delete=models.PROTECT)
    id_company = models.ForeignKey(Person, blank=True, null=True, unique=True, on_delete=models.PROTECT)  

请注意,我使用blank=True, null=True了这样您就可以仅使用 Person 或 Company 创建实例,而无需同时使用两者创建实例。还有一个 Meta 可以使用主键组合。

class AddressExample(models.Model):
    id_address = models.ForeignKey(Address, unique=True,on_delete=models.PROTECT)
    id_person = models.ForeignKey(Person, blank=True, null=True, unique=True, on_delete=models.PROTECT)
    id_company = models.ForeignKey(Person, blank=True, null=True, unique=True, on_delete=models.PROTECT)

   class Meta:
       unique_togther = ('id_address', 'id_person', 'id_company')
       # Not sure if it will throw a error here because `id_person` and `id_company` can be blank 
       # or null. But the use of `unique together` is for cases where you want to guarantee 
       # the combination of the primary keys will be unique.

希望能帮助到你。


推荐阅读