多对多或一对多 Django

Posted

技术标签:

【中文标题】多对多或一对多 Django【英文标题】:Many to Many or One to Many Django 【发布时间】:2017-05-15 15:05:02 【问题描述】:

我在 Django 中有以下两个模型。一个基本上是基本 Django 用户类的扩展,另一个是公司模型。我想说一个用户可以属于一个或多个公司,一个公司也可以有一个或多个联系人=“用户”。这是一个正确的设置吗?我应该如何表现用户和公司之间的联系?

用户配置文件模型:

class Profile(models.Model):
    user = models.OneToOneField(User)
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

公司模式:

class Company(models.Model):
    name = models.CharField(max_length=120)
    account_name = models.CharField(max_length=10, default="")
    sales_rep = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_sales", default="")
    csr = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_csr", default="")

class CompanyContact(models.Model):
    name = models.CharField(max_length=40, default="")
    email = models.CharField(max_length=50, default="")
    user = models.ForeignKey(User)
    company = models.ForeignKey(Company)

【问题讨论】:

【参考方案1】:

首先,是否有理由扩展User 模型?默认模型已经包含 first_namelast_name 字段,因此您不需要仅针对该数据的其他模型。同样,您实际上并不需要CompanyContact,因为User 模型还包含emailname(同样,通过first_namelast_name)字段。

您可以将联系人添加为ManyToManyField。如果您想使用自定义Profile 模型而不是User,只需将User(在ManyToManyField 中)替换为Profile

class Company(models.Model):
    name = models.CharField(max_length=120)
    account_name = models.CharField(max_length=10, default="")
    sales_rep = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_sales", default="")
    csr = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_csr", default="")
    contacts = models.ManyToManyField(User) # or Profile

这允许每个公司有 许多 个联系人,每个用户可以成为 许多 个公司的联系人 - 因此是多对多。


现在,如果您想要额外的数据来描述多对多关系,you can have another model for that。例如,如果联系人仍处于活动状态或他们的角色是什么,您可能希望保留记录。因此,您可能有一个类似于以下内容的CompanyContact 模型:

class CompanyContact(models.Model):
    active = models.BooleanField(default=False)
    role = models.CharField(max_length=50, default="")
    user = models.ForeignKey(User) # or Profile
    company = models.ForeignKey(Company)

然后,声明ManyToManyField 关系以使用这个新模型:

class Company(models.Model):
    ...
    contacts = models.ManyToManyField(User, through="CompanyContact")
    # or contacts = models.ManyToManyField(Profile, through="CompanyContact")

【讨论】:

太棒了!我想将姓名和电子邮件添加到公司联系人,以防“联系人”没有个人资料。管理员可以为该公司输入他们自己的手动联系人,同时还可以将实际用户链接为公司联系人 此外,个人资料将包含更多信息,而不仅仅是名字和姓氏。将来它可能包含:主题、生日、访问规则。 @SamMunroe 在联系人中复制电子邮件/姓名可能有点笨拙。相反,我建议如下:保持UserCompanyCompanyContact 之间的多对多关系,然后在添加联系人时始终创建UserProfile 是独立的,包含其他信息,但不是联系人。

以上是关于多对多或一对多 Django的主要内容,如果未能解决你的问题,请参考以下文章

在 PostgreSQL 中存储一对多或多对多关系的最佳方式是啥?

思考具有两个外键的一对多或多对多关系的正确方法是啥?

数据库设计 - 多对多或一对多“交易”系统?

Django模型(继承、一对多、多对多)

django mysql 表的一对一 一对多 多对多

django ManyToManyField多对多关系