【问题标题】:Best approach to use Many to Many in Django + SQL在 Django + SQL 中使用多对多的最佳方法
【发布时间】:2021-03-01 01:51:51
【问题描述】:

我正在制作一个网络应用程序,我希望在模型中使用多对多字段。我之前没有考虑太多,只是在模型中使用了多对多字段,但现在我在想这些多对多字段实际上如何存储在数据库中,在模型中使用多对多字段时最好的方法是什么。

方法一:

class Company(models.Model):
    name = models.CharField(max_length = 190,blank = False,null = False)
    about = models.CharField(max_length = 260,blank = False,null = True)
    website = models.URLField(blank = False)
    address  = models.OneToOneField(Address,related_name="org_address",on_delete=models.SET_NULL,null=True)
    admin = models.ManyToManyField(User,related_name="org_admin",blank = False)
    created_on = models.DateTimeField(default = timezone.now)
    updated_on = models.DateTimeField(default = timezone.now)

或 方法二:

class Company(models.Model):
    name = models.CharField(max_length = 190,blank = False,null = False)
    about = models.CharField(max_length = 260,blank = False,null = True)
    website = models.URLField(blank = False)
    address  = models.OneToOneField(Address,related_name="org_address",on_delete=models.SET_NULL,null=True)
    created_on = models.DateTimeField(default = timezone.now)
    updated_on = models.DateTimeField(default = timezone.now)

class CompanyAdmin(models.Model):
    admin = models.ManyToManyField(User,related_name="org_admin",blank = False)
    company = models.ForeignKey(Company,related_name="company",on_delete=models.CASCADE)

这两种方法是否以相同的方式处理多对多字段?

我使用 MySQL 作为数据库

更新 “为了使它们等效,第二种方法应该具有 ForiegnKey 字段,而不是 多对多” 还要避免多个公司管理员条目字段公司应该是一对一的。

解决方案

不要创建连接表,因为 Django ORM 会自行处理。

【问题讨论】:

  • 不,通过使用CompanyAdmin 您创建了一个额外的表,所以现在多对多关系使用两个中间表。它还导致您可以在多个 CompanyAdmins 中添加相同的User,从而将其多次链接到相同 Company
  • 为了使第二个示例等效,CompanyAdmin 中的 admin 必须是 ForeignKey(而不是 ManyToManyField) - 但 Django 的 ORM 的优点之一是你不需要不必自己创建这个中间“连接表”,所以我认为这样做没有任何好处。
  • 好的,假设在第二种方法中使用一对一字段而不是外键。方法1不会也自动创建一个不同的表来处理多对多字段吗?
  • @RobinZigmond 谢谢,这就是我的想法。现在这清除了它。
  • @Dushyant Deshwal:即使你创建了一个OneToOneField,它也会导致构建一个额外的表,这将导致查询时额外的JOIN,以及更多的磁盘使用。所以添加这样的额外模型不是一个好主意。

标签: python mysql django model


【解决方案1】:

但现在我在想这些多对多实际上是如何存储在数据库中的。

Django 将构建一个具有两个ForeignKeys 的模型,一个用于Company,一个用于User 模型。因此,该模型对应于CompanyUser 模型之间的junction table [wiki]

因此,ManyToManyField 不会映射到 ManyToManyField 更多的是一个概念,可以让人们编写更简单的查询,并提供更方便的界面。

这两种方法是否以相同的方式处理多对多字段?

。使用后者,您将制作 两张 额外表格,一张用于CompanyAdmin 模型,一张用于CompanyAdminUser 之间的ManyToManyField。例如,这也会导致更多的JOINs 来获取User 是管理员的公司,并且这里可以为相同的@ 构造多个 CompanyAdmins 987654342@,从而多次链接同一个User

您可以在联结表中定义自定义属性,方法是使用 through=… parameter [Django-doc] 显式指定联结模型:

from django.conf import settings

class Company(models.Model):
    admin = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='org_admin',
        through='CompanyAdmin'
    )
    created_on = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)

class CompanyAdmin(models.Model):
    admin = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE
    )
    company = models.ForeignKey(
        Company,
        on_delete=models.CASCADE
    )

注意:通常使用settings.AUTH_USER_MODEL [Django-doc] 引用用户模型比直接使用User model [Django-doc] 更好。更多信息可以查看referencing the User model section of the documentation


注意:Django 的DateTimeField [Django-doc] 有一个auto_now_add=… parameter [Django-doc] 使用时间戳。这将自动分配当前日期时间 创建对象时,将其标记为不可编辑(editable=False),例如 默认情况下它不会出现在ModelForms 中。

【讨论】:

    猜你喜欢
    • 2019-06-13
    • 1970-01-01
    • 2012-04-25
    • 1970-01-01
    • 2016-08-08
    • 2011-03-10
    • 2016-08-03
    • 2011-01-09
    • 2016-05-17
    相关资源
    最近更新 更多