djang Extra fields on many-to-many relationships

django 官方文档介绍过,当有时你可能需要处理两个模型之间的关系与关联的数据。

需求如下:

For example, consider the case of an application tracking the musical groups which musicians belong to. There is a many-to-many relationship between a person and the groups of which they are a member, so you could use a ManyToManyField to represent this relationship. However, there is a lot of detail about the membership that you might want to collect, such as the date at which the person joined the group.

For these situations, Django allows you to specify the model that will be used to govern the many-to-many relationship. You can then put extra fields on the intermediate model. The intermediate model is associated with theManyToManyField using the through argument to point to the model that will act as an intermediary. For our musician example, the code would look something like this:

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)
你可以对进行如下操作:

>>> ringo = Person.objects.create(name="Ringo Starr") 在后台创建了一个名为"Ringo Starr"的Person对象
>>> paul = Person.objects.create(name="Paul McCartney") 在后台创建一个名为"Paul MxCartney"的Person对象
>>> beatles = Group.objects.create(name="The Beatles") 在后台创建一个名为"The Beatles"的beatles的对象
>>> m1 = Membership(person=ringo, group=beatles,
...     date_joined=date(1962, 8, 16),
...     invite_reason= "Needed a new drummer.") 在后台创建了一对具有关系的Merbership对象
>>> m1.save()
beatles与ringo之间具有多对多的关系,由一下beatles的拥有的成员可以看出,
>>> beatles.members.all() 
[<Person: Ringo Starr>]
>>> ringo.group_set.all()
[<Group: The Beatles>]
>>> m2 = Membership.objects.create(person=paul, group=beatles,
...     date_joined=date(1960, 8, 1),
...     invite_reason= "Wanted to form a band.")
>>> beatles.members.all()
[<Person: Ringo Starr>, <Person: Paul McCartney>]
但是以上通过中间模型创建的不能像正常的多对多的进行addcreate, or assignment (i.e., beatles.members = [...]) 去创建关系,一下操作是错误的:

# THIS WILL NOT WORK
>>> beatles.members.add(john)
# NEITHER WILL THIS
>>> beatles.members.create(name="George Harrison")
# AND NEITHER WILL THIS
>>> beatles.members = [john, paul, ringo, george]
 However, the clear() method can be used to remove all many-to-many relationships for an instance:但是你可以通过clear()来清除这样的关系:

# Beatles have broken up
>>> beatles.members.clear()
同样你能使用filter来刷选:

# Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(members__name__startswith='Paul') 过滤出members名字以Paul开头的对象出来
[<Group: The Beatles>]
# Find all the members of the Beatles that joined after 1 Jan 1961
>>> Person.objects.filter(
...     group__name='The Beatles',
...     membership__date_joined__gt=date(1961,1,1))
[<Person: Ringo Starr]
>>> Group.objects.filter(members__name__startswith='Paul',membership__date_joined=date(1962,8,16))这样的形式来进行过滤刷选。
这时你看懂这两种的关系了吗?通过members = models.ManyToManyField(Person,through='Membership')来给两者建立数据之间的关系。

你可能感兴趣的:(djang Extra fields on many-to-many relationships)