2010-07-30 89 views
39

從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

回答

32

最簡單的方法就是將樂隊傳遞給模板。模板能夠導航模型之間的關係,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

6

我不確定它是否只是解決方案,但將關係對象傳遞給模板當然有效。在你看來,得到查詢集成員的對象:

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