简体   繁体   English

在 Django + SQL 中使用多对多的最佳方法

[英]Best approach to use Many to Many in Django + SQL

I am making a web app and i wish to use many to many fields in models.I haven't given much thought before and have simply used many to many field in models but now i am thinking how actually these many to many are stored in database and what would be the best approach when using Many to Many Fields in Models.我正在制作一个网络应用程序,我希望在模型中使用多对多字段。我之前没有考虑太多,只是在模型中使用了多对多字段,但现在我在想这些多对多实际上是如何存储的数据库以及在模型中使用多对多字段时的最佳方法是什么。

Approach 1:方法一:

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)

OR Approach 2:或 方法 2:

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)

Do both methods handle many to many fields in the same way ?这两种方法是否以相同的方式处理多对多字段?

I am using MySQL as Database我使用 MySQL 作为数据库

Update "To make them Equivalent, Second Approach should have field as ForiegnKey and not many to many " also to avoid multiple company admin entries Field company should be one to one.更新“为了使它们等效,第二种方法应该将字段作为ForiegnKey而不是多对多”也为了避免多个公司管理员条目字段公司应该是一对一的。

Solution解决方案

Do not create join tables as Django ORM Handles this itself.不要创建连接表,因为 Django ORM 会自行处理。

but now I am thinking how actually these many to many are stored in database.但现在我在想这些多对多实际上是如何存储在数据库中的。

Django will construct a model that has two ForeignKey s, one to the Company and one to the User model. Django 将构建一个具有两个ForeignKey的模型,一个是Company模型,一个是User模型。 This model thus corresponds to the junction table [wiki] between the Company and User model.因此,该模型对应于CompanyUser模型之间的连接表[wiki]

A ManyToManyField thus does not map on a column .因此, ManyToManyField不会映射到列上 The ManyToManyField is more a concept that enables one to write simpler queries, and provides a more convenient interface. ManyToManyField更像是一个概念,它使人们能够编写更简单的查询,并提供更方便的界面。

Do both methods handle many to many fields in the same way ?这两种方法是否以相同的方式处理多对多字段?

No .没有 With the latter you will make two extra tables, one for the CompanyAdmin model, and one for the ManyToManyField between CompanyAdmin and User .对于后者,您将创建两个额外的表,一个用于CompanyAdmin模型,另一个用于CompanyAdminUser之间的ManyToManyField It would also result in more JOIN s to fetch the companies for which a User is an admin for example, and it would here be possible to construct multiple CompanyAdmin s for the same Company , and thus linking the same User multiple times.例如,这也会导致更多JOIN来获取User作为管理员的公司,并且在这里可以为同一个Company构造多个CompanyAdmin ,从而多次链接同一个User

You can define however custom attributes in the junction table, by specifying the junction model explicitly with the through=… parameter [Django-doc] :但是,您可以通过使用through=…参数 [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
    )

Note : It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly.注意:通常最好使用settings.AUTH_USER_MODEL [Django-doc]来引用用户模型,而不是直接使用User模型 [Django-doc] For more information you can see the referencing the User model section of the documentation .有关更多信息,您可以查看文档引用User模型部分


Note : Django's DateTimeField [Django-doc] has a auto_now_add=… parameter [Django-doc] to work with timestamps.注意:Django 的DateTimeField [Django-doc]有一个auto_now_add=…参数 [Django-doc]来处理时间戳。 This will automatically assign the current datetime when creating the object, and mark it as non-editable ( editable=False ), such that it does not appear in ModelForm s by default.这将在创建对象时自动分配当前日期时间,并将其标记为不可编辑( editable=False ),这样默认情况下它不会出现在ModelForm

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

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