【问题标题】:Is Django many to many really necessary?Django many to many 真的有必要吗?
【发布时间】:2020-10-13 15:06:53
【问题描述】:

去年我一直在学习使用 Django,而 Python 不是我的母语编程语言。通常,当我想创建多对多关系时,我会创建 3 个表,其中一个包含另外两个表的两个外键。出于这个原因,我发现 Django 多对多字段非常不自然。这个多对多字段是否会在数据库中创建第三个表来存储关系?如果是这种情况,那么使用多对多字段将阻止类结构直接表示表结构。

我想知道是否有理由我应该使用这个多对多字段,或者我可以使用 3 个类来表示多对多关系吗?

谢谢

标记

【问题讨论】:

    标签: python-3.x django


    【解决方案1】:

    我将创建 3 个表,其中一个包含另外两个表的两个外键。出于这个原因,我觉得 Django 多对多字段非常不自然。

    正是 Django 在幕后所做的。如果您检查数据库,您将看到junction table [wiki]。 Django 只是在后台执行此操作。它只是将其呈现作为一个字段到前台。正如您在database Representation of the ManyToManyField 中看到的:

    在幕后,Django 创建了一个中间连接表来表示多对多关系。默认情况下,此表名是使用多对多字段的名称和包含它的模型的表名生成的。由于某些数据库不支持超过一定长度的表名,这些表名将被自动截断并使用唯一性哈希,例如author_books_9cdf。您可以使用db_table 选项手动提供连接表的名称。

    您甚至可以通过在两者之间显式定义模型并在through=… parameter [Django-doc] 中指定这一点,向此联结表添加额外字段。例如:

    class Category(models.Model):
        name = models.CharField(
            max_length=128,
            unique=True
        )
    
    class Item(models.Model):
        name = models.CharField(
            max_length=128,
            unique=True
        )
        categories = models.ManyToManyField(
            Category,
            through='ItemCategory'
            related_name='items'
        )
    
    class ItemCategory(models.Model):
        category = models.ForeignKey(Category, on_delete=models.CASCADE)
        item = models.ForeignKey(Item, on_delete=models.CASCADE)
        validated = models.BooleanField(default=False)

    ManyToManyField 因此更多的是一个概念,使表示和查询更方便。

    【讨论】:

    • 感谢您的重播 - 它有助于我的理解。在您的示例中,如果您删除了说明 categories = models.ManyToManyField( .... ) 的代码段,那么该代码是否仍代表多对多关系?这使得多对多字段感觉有点超出要求。我想公平地说,如果你在只需要 2 个类的情况下使用 3 个类,这同样适用,但由于类结构不再直接代表表结构,因此肯定会失去清晰度。跨度>
    • @MarkyMark1000:是的,如果没有ManyToManyField,它仍然代表多对多关系。但随后查询Itemcategories 可能会更麻烦。 ManyToManyField 因此在其之上添加了一个“概念层”,以便于使用 myitem.categories.all() 进行查询。
    • 啊,好吧,这很有趣,所以你说如果我不包含 ManyToManyField,我以后可能会发现很难在 Django 中查询。知道这真的很有用。只是出于兴趣,我还可以在使用相同“ItemCategory”类的类别表中添加一个“Items”字段吗?这个想法是这样我也可以使用我的 category.items.all()
    • 谢谢,这真的很有用。
    • 对于任何感兴趣的人,我发现当我尝试添加 items manytomany 字段时,迁移失败,因为 Item 类还不存在。我猜 ManyToMany 字段是单向的,您需要仔细选择哪个类首先出现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多