代码之家  ›  专栏  ›  技术社区  ›  Alex

如何从django模板访问多对多“through”表的属性?

  •  42
  • Alex  · 技术社区  · 16 年前

    从Django文档中。。。

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

    例如,考虑应用程序跟踪音乐家所属的音乐组的情况。一个人和他们所属的组之间存在多对多关系,因此可以使用ManyToManyField来表示这种关系。但是,您可能需要收集很多有关成员身份的详细信息,例如此人加入组的日期。

    对于这些情况,Django允许您指定将用于管理多对多关系的模型。然后可以在中间模型上添加额外的字段。中间模型与ManyToManyField相关联,使用through参数指向将充当中间层的模型。以音乐家为例,代码如下所示:

    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)
    

    既然您已经设置了ManyToManyField以使用中介模型(在本例中是成员),那么就可以开始创建一些多对多关系了。可以通过创建中间模型的实例来执行此操作:

    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()
    [<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>]
    

    资料来源: http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany

    我的问题是,如何设置视图和模板以访问这些附加属性。假设我有一个乐队页面,我想显示乐队名称,遍历成员记录,显示乐队名称和加入日期。

    如何在模板中创建for循环?

    谢谢。

    2 回复  |  直到 6 年前
        1
  •  40
  •   Rory Hart    16 年前

    最简单的方法就是把带子传给模板。模板能够导航模型之间的关系,并且在组上有成员和成员集查询集管理器。所以我会这样做:

    def group_details(request, group_id):
        group = get_object_or_404(Group, pk=group_id)
        return render_to_response('group_details.html',
                                  {'group': group})
    

    模板:

    <h2>{{ group.name }}</h2>
    {% for membership in group.membership_set.all %}
        <h3>{{ membership.person }}</h3>
        {{ membership.date_joined }}
    {% endfor %}
    
        2
  •  6
  •   cji    16 年前

    rel = Membership.objects.filter( group = your_group ).select_related()
    

    并将其传递给模板,在模板中可以使用 {% for %}

    {% for r in rel %}
         {{ r.person.name }} joined group {{ r.group.name }} on {{ r.date_joined }}<br />
    {% endfor %}
    

    请注意,这不应执行任何其他查询,因为 select_related() .

        3
  •  0
  •   Quique    6 年前

    罗里哈特的回答基本上是正确的。它允许您使用中间( through )多人关系中的表。

    但是,模板中的循环应该使用 select_related

    <h2>{{ group.name }}</h2>
    {% for membership in group.membership_set.select_related %}
        <h3>{{ membership.person.name }}</h3>
        {{ membership.date_joined }}
    {% endfor %}