我应该使用单独的表而不是 Django 中的多对多字段吗

afs*_*hin 6 django django-models

我需要为提交列表分配一个或多个类别,我最初使用带有两个外键的表来完成此操作,直到我意识到 Django 具有多对多字段,但是按照文档我无法复制我对原始表所做的。

我的问题是:使用多对多字段而不是手动创建关系表有好处吗?如果更好,是否有关于使用 Django 提交和检索多对多字段的示例?

Jam*_*ury 8

来自关于多对多关系的 Django 文档:

当您只处理简单的多对多关系(例如混合和匹配比萨饼和配料)时,标准的 ManyToManyField 就是您所需要的。但是,有时您可能需要将数据与两个模型之间的关系相关联。

简而言之:如果您有一个简单的关系,多对多字段会更好(为您创建和管理额外的表)。如果您需要多个额外的详细信息,请使用外键创建您自己的模型。所以这真的取决于情况。

更新 :-要求的示例:

从文档:

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __unicode__(self):
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person)
    group = models.ForeignKey(Group)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)
Run Code Online (Sandbox Code Playgroud)

您可以通过此示例看到,除了多对多关系之外,还保留了成员资格详细信息 (date_joinedinvite_reason)。

但是,在文档中的一个简化示例中:

class Topping(models.Model):
    ingredient = models.CharField(max_length=128)

class Pizza(models.Model):
    name = models.CharField(max_length=128)
    toppings = models.ManyToManyField(Topping)
Run Code Online (Sandbox Code Playgroud)

似乎不需要任何额外的数据,因此也不需要额外的模型。

更新 2 :-

如何删除关系的示例。

在我给你的第一个例子中,你有这个额外的模型,Membership你只需像普通模型一样删除关系及其细节。

for membership in Membership.objects.filter(person__pk=1)
    membership.delete()
Run Code Online (Sandbox Code Playgroud)

中提琴!非常简单。

对于第二个示例,您需要使用(或全部删除).remove() .clear()

apple = Toppings.objects.get(pk=4)
super_pizza = Pizza.objects.get(pk=12)

super_pizza.toppings.remove(apple)
super_pizza.save()
Run Code Online (Sandbox Code Playgroud)

而且那个也完成了!