繁体   English   中英

Django多重外键模型

[英]Django Multiple Foreign Key Model

这是我的代码,有没有更有效的编写方法? 我不喜欢它。

基本上,公司模型和供应商模型都应该具有多个联系人和多个电话号码。

class Contact(models.Model):
    company = models.ForeignKey(Company, related_name='contact',
        blank=True, null=True)
    supplier = models.ForeignKey(Supplier, related_name='contact',
        blank=True, null=True)
    name = models.CharFields(max_length=50, blank=True, null=True)
class Phone(models.Model):
    contact = models.ForeignKey(Contato, related_name='phone')
    number = models.CharFields(max_length=50, blank=True, null=True)

解决“ X型公司和Y型公司都有联系”问题的方法至少有四种:

  1. 两个表:公司和联系人。 公司有一个枚举的属性,其值为X和Y,并且每个联系人都有一个公司的外键。
  2. 三个表:一个用于X公司的表X,一个用于Y公司的表Y,以及用于联系人C的一个表,其中C具有指向X和Y的外键。外键可以为空。
  3. 四个表:X,Y,Cx和Cy,分别跟踪两种不同类型公司的两种不同联系人。 (因此,Cx具有X的外键,而Cy具有Y的外键)。
  4. 五个表:您从这三个表X,Y和C开始,但是没有添加指向C的可空指针,而是添加了两个多对多联接表XC和YC。

这些对基础数据有不同的要求。 您现在正在使用三表解决方案(X, Y, C) = (Company, Supplier, Contact) 如果要在公司和供应商之间共享某些联系,这很好,那么您有时需要问“谁是该公司与该供应商之间的联系人?”。 我维护着一个使用两表解决方案的数据库,当它最初被采用时,这是一个很好的解决方案(为什么不必重复所有关于地址和联系的逻辑?),但是今天看起来很笨拙(因为“公司”表包含的字段仅对X和Y分别有意义)。

对于我来说,如果迁移,最容易处理的是四表解决方案:将X型公司的联系人与Y型公司的联系人完全分开。 如果您从当前的方法开始,那么如果您在应用程序中遇到类似的麻烦,那么五表解决方案将是显而易见的概括。

至于跟踪电话号码,您有一些有限的选择:

  1. 在联系人表中存储一堆列,每个单独的电话号码一个。 这很快变得很丑陋,但这是快速简便的方法。 这称为“非规格化”数据。
  2. 将JSON存储在“联系人”列表中的文本字段中。 电话号码不太可能被搜索太多; 说“我有这个数字,它属于谁?”并不是很常见,因此您可以轻松地将其归一化。 这也使您可以执行{"mon thru thurs": 12025551234, "fri, sat": 12025554321} ,为数字存储简单的自定义注释。
  3. 像现在一样创建电话表。 这是执行此操作的最通用方法,如果您需要这些类型的注释,则可以在该表中添加另一个文本字段。

如果将此处的选项3与上面的选项3(四个表加一个显式电话表)混合使用,那么您可能希望拥有单独的电话表和单独的联系表; Px和Py分别具有指向Cx和Cy的外键。

对我而言, CompanySupplier模型可以相同。 既然大多数供应商都是对的公司? 如果它们与合并CompanySupplier模型基本相同,则如下所示:

class Company(models.Model):
    name = models.CharFields(max_length=50)
    is_supplier = models.BooleanField(default=False)  
    suppliers = models.ManyToManyField("self", 
        limit_choices_to={'is_supplier': True})


class Contact(models.Model):
    name = models.CharFields(max_length=50)    
    company = models.ForeignKey(Company)


class Phone(models.Model):
    number = models.CharFields(max_length=50)    
    contact = models.ForeignKey(Contact)

这是Chris Drosts的“两张桌子”解决方案。 如果您需要供应商特定的字段,而不是添加供应商模型并通过OneToOne将其链接到Company:

class Supplier(models.Model):
    ... # Some supplier specific fields.
    company = models.OneToOneField(Company)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM