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

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

问题描述:

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

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

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

对于这些情况,Django允许您指定将用于管理多对多关系的模型。然后您可以在中间模型上添加额外的字段。中间模型使用through参数与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) 

现在你已经设置了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

我的问题是,我该如何设置我的观点和模板来访问这些附加属性。假设我有一个乐队页面,我想显示乐队名称,遍历成员资格记录并显示姓名和date_joined。

我应该将带对象传递给模板吗?或者我以某种方式传递会员对象?

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

谢谢。

+1

我会考虑缩短从Django文档有点摘录。有可能回复的人可能已经对他们很熟悉了,这样就更容易找到真正的问题。 – cji 2010-07-30 04:57:37

最简单的方法就是将乐队传递给模板。模板能够导航模型之间的关系,Group上有成员和membership_set查询集管理器。因此,这里是我会怎么做:

观点:

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

完美的作品。我正在尝试通过group.membership.all进行迭代。我需要阅读_set。谢谢! – Alex 2010-07-30 14:18:31

+0

但是如果你需要更复杂的东西,比如排序,过滤等,标准的做法就是在视图中做,然后通过上下文传递它。 – CpILL 2015-09-29 14:22:17

+0

重要的一点是,通过表的小写字母的类名称使用“成员资格”。 – MagicLAMP 2016-03-10 12:16:37

我不确定它是否只是解决方案,但将关系对象传递给模板当然有效。在你看来,得到查询集成员的对象:

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()的任何其他查询。