2013-07-23 82 views
2

我不明白为什么我们必须使用ManyToManyField来声明多对多关联。为此,我将创建另一个带有两个外键的表格,即句号! 下面是一个例子从DOC https://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany多对多协会

from django.db import models 

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

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

class Membership(models.Model): 
    person = models.ForeignKey(Person) 
    group = models.ForeignKey(Group) 
    extraField = models.DateField() 

我只想写:

from django.db import models 

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

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

class Membership(models.Model): 
    person = models.ForeignKey(Person) 
    group = models.ForeignKey(Group) 
    extraField = models.DateField() 

它是正确的吗?有什么不同?

+0

我让别人回答这个谁更有资格。很好的问题。 – jdero

+0

正确的方法是使用'ManyToManyField'来完成它,因为在你的情况下制作称为'Membership'的额外模型非常繁琐。 –

回答

2

定义关系的中间模型没有任何问题。通过这种方式,您可以在中间模型(“会员”)上存储额外信息,例如加入该群组的人员或会员资格仍然有效。但是,大多数情况下,您不需要额外的信息,只需要存储哪个人是哪个组的成员。在这些情况下,您可以使用简单的ManyToManyField。 Django的使得它很容易与这些领域的工作,所以你可以做group.members.add(user)group.members.delete(user),比较,为:

Membership.objects.create(user=user, group=group) 
Membership.objects.get(user=user, group=group).delete() 

免责声明:伪代码,可能不实际工作

您仍然可以使用ManyToManyField与中间模式,这使得大多数Django的多对多的便利,但也有一些限制:

不同于一般的多到很多领域,你不能使用添加,创建或转让(即甲壳虫。成员= [...])来建立关系。

为什么?您不能仅在Person和Group之间创建关系 - 您需要指定Membership模型所需关系的所有详细信息。简单的添加,创建和赋值调用不提供指定这些额外细节的方法。因此,它们在使用中间模型的多对多关系中被禁用。创建这种类型的关系的唯一方法是创建中间模型的实例。

出于类似的原因,remove()方法被禁用。但是,clear()方法可用于删除实例的所有多对多关系。

一旦通过创建中间模型的实例建立了多对多关系,就可以发出查询。与正常的多对多关系一样,您可以使用多对多关联模型的属性进行查询。

来源:docs.djangoproject.com

+0

好了,所以它只是一个快捷方式......如果我们想创建中间表(使用外键)......是否仍然需要使用ManyToManyField? – rom

+0

如果你有自己创建的中间模型,'ManyToManyField(through = ...)'是可选的。它仍然为您提供了大部分快捷方式,但无法创建新的关系。另见我的编辑。 – bouke

+0

我现在明白了,最好使用ManyToManyField来访问django快捷方式来操作模型。谢谢! – rom