Detailed Django-many intermediate table

A default intermediate table

  First, the model is this:

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

    def __str__(self):
        return self.name


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

    def __str__(self):
        return self.name

  In Group model by members fields to ManyToMany way to establish a relationship with the Person model.

  To look at the actual content within the database, Django creates three data tables, which is the application name app1. 

  Then add the following Person object in the database:   

  Group add the following objects: 

  Take a look at the middle of the table is what it looks like: 

  First, there is an id, which is the default Django added. And then the id column Person Group, which is the default, Django associated with the two tables of the way. To set the associated column, you can use to_field parameters.

  Visible in the middle of the table, not two data tables are stored together, but by mapping the id associated.

Second, custom intermediate table

  Generally, ordinary-many have been enough, without having to create their own third relational table. However, some cases may be more complicated, such as want to save a person time to join a group do? The reason you want to save it into the group?

  Django provides a throughparameter that specifies the intermediate model, into a similar set of time, the reason to invite other fields may be placed in the middle of the model. Examples are as follows:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)
    def __str__(self): 
        return self.name

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

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()        # 进组时间
    invite_reason = models.CharField(max_length=64)  # 邀请原因

  In the middle of the table, to write at least two foreign key fields, each point associated with two models. In the present embodiment, it is 'Person' and 'group'. Here, we additionally increased the 'date_joined' field, saving time for staff into the group, 'invite_reason' field holds the reason for the invitation into the group.

  Still below the actual look in the database: 

  Note middle of the table name has become "app2_membership" a. 

  Person and Group unchanged. 

  But the middle of the table a different story! It is perfectly preserved what we need.

Third, the intermediate table

  For the middle of the table above, the following are some examples of use:

>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
... date_joined=date(1962, 8, 16),
... invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all()
<QuerySet [<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()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>

  Ordinary-many not the same as using a custom-many middle of the table can not be created using the add (), create (), remove (), and set () method, delete relationships, see the following:

>>> # 无效
>>> beatles.members.add(john)
>>> # 无效
>>> beatles.members.create(name="George Harrison")
>>> # 无效
>>> beatles.members.set([john, paul, ringo, george])

  why? Because of the above methods can not provide the time to join, invite reason field content and other intermediate model needs. The only way is to only create many association by creating an instance of this type of intermediate models. However, clear () method is effective, it can clear all the many relationships.

>>> beatles.members.clear ()
 >>> # deleted intermediate object model 
>>> Membership.objects.all ()
 <QuerySet that []>

  Once you have established an association-many instances by the process of creating an intermediate model, it can immediately operate like a normal query as many-:

# Find all the groups have Paul this person (at the beginning of the name Paul) within the group 
>>> Group.objects.filter (members__name__startswith = ' Paul ' )
 <QuerySet [<Group: at The Beatles>]>

  You can use the properties of the intermediate model query:

>>> Person.objects.filter(
... group__name='The Beatles',
... membership__date_joined__gt=date(1961,1,1))
<QuerySet [<Person: Ringo Starr]>

  You can use the same model as the common intermediate model:

>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'
>>> ringos_membership = ringo.membership_set.get(group=beatles)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'

  This part requires a combination of the back of the model queries.

  For the middle of the table, it must be noted, by default, only the intermediate model comprising a foreign key relationship to the source model, the above example, i.e. only in Membership in each of a Group Person and foreign key relationships, no more . Otherwise, you must explicitly by ManyToManyField.through_fieldsparameters associated with the specified object. Reference to the following examples:

from django.db import models

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

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

class Membership(models.Model):
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    inviter = models.ForeignKey(
    Person,
    on_delete=models.CASCADE,
    related_name="membership_invites",
    )
    invite_reason = models.CharField(max_length=64)

Guess you like

Origin www.cnblogs.com/lavender1221/p/12499256.html