为了账号安全,请及时绑定邮箱和手机立即绑定

我如何限制或选择一个或另一个外键?

我如何限制或选择一个或另一个外键?

qq_花开花谢_0 2023-07-05 15:30:09
问题是概念性的(数据库关系),因此语言不是这里的重点,但我正在使用 Python 和 Django。我有 3 个模型/桌子:公司顾客地址例如。class Company(models.Model):    name = models.CharField(max_lenght=100) #exampleclass Customer(models.Model):    name = models.CharField(max_lenght=100) #exampleclass Adress(models.Model):    country = models.CharField(max_lenght=100) #example    state = models.CharField(max_lenght=100) #example        # here I want the address owner    # I could put something like this:    company = models.ForeignKey(Company, on_delete=models.PROTECT)    customer = models.ForeignKey(Customer, on_delete=models.PROTECT)我希望该地址属于客户或公司,但不能同时属于两者。我知道我可以简单地创建 2 个地址类,例如 CustomerAddress、CompanyAddress,每个类都有其正确的外键:class Company(models.Model):    name = models.CharField(max_lenght=100) #exampleclass Customer(models.Model):    name = models.CharField(max_lenght=100) #exampleclass CompanyAdress(models.Model):    country = models.CharField(max_lenght=100) #example    state = models.CharField(max_lenght=100) #example    company = models.ForeignKey(Company, on_delete=models.PROTECT)class CustomerAdress(models.Model):    country = models.CharField(max_lenght=100) #example    state = models.CharField(max_lenght=100) #example    customer = models.ForeignKey(Company, on_delete=models.PROTECT)但我不想这么做,原因有两个:重复的代码以及在 Django 管理面板中我将有两个单独的地址列表的事实,这没有多大意义,因为所有地址在结构上都是相同的。我可以修复创建基类、继承基类等的重复代码,但我在管理面板中仍然会有 2 个列表。将来我可能会遇到同样的概念性问题,但会更加复杂,例如,某些事物有 300 个类,而 1 个类应该只有 300 个类中的一个具有外键。我应该怎么办?
查看完整描述

2 回答

?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

您可以尝试将外键设置为 null=True 并根据需要通过视图控制数据库中的输入:

class Address(models.Model):
    country = models.CharField(max_lenght=100) 
    state = models.CharField(max_lenght=100)
    company = models.ForeignKey(Company, on_delete=models.PROTECT, null=True)
    customer = models.ForeignKey(Customer, on_delete=models.PROTECT, null=True)


查看完整回答
反对 回复 2023-07-05
?
千万里不及你

TA贡献1784条经验 获得超9个赞

下面是一个DB模型。


-- Address ADR exists.
--
address {ADR}
     PK {ADR}

Party是个人或组织的通用术语;判别器TYP用于区分两者。

-- Party PTY, of party-type TYP, resides at address ADR.
--
party {PTY, TYP, ADR}
   PK {PTY}
   SK {PTY, TYP}

CHECK TYP in {'P', 'O'}

FK {ADR} REFERENCES address {ADR}
-- Person, a party PTY of party-type TYP = 'P', exists.
--
person {PTY, TYP}
    PK {PTY}

CHECK TYP = 'P'

FK {PTY, TYP} REFERENCES party {PTY, TYP}
-- Organization, a party PTY of party-type TYP = 'O', exists.
--
organization {PTY, TYP}
          PK {PTY}

CHECK TYP = 'O'

FK {PTY, TYP} REFERENCES party {PTY, TYP}

笔记:

All attributes (columns) NOT NULL


PK = Primary Key
AK = Alternate Key   (Unique)
SK = Proper Superkey (Unique)
FK = Foreign Key

关于亚型的一句话。实现子类型约束的正确方法是使用断言(CREATE ASSERTION),但它在主要数据库中仍然不可用。我正在使用FKs它,并且与所有其他替代方法一样,它并不完美。人们争论很多,关于SO和SE-DBA,哪个更好。我鼓励您也检查其他方法。


查看完整回答
反对 回复 2023-07-05
  • 2 回答
  • 0 关注
  • 75 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信