2010-07-30 3 views
39

Aus der Dokumentation Django ...Wie kann ich von einer Django-Vorlage auf die Eigenschaften einer Viele-zu-Viele-Tabelle zugreifen?

Wenn Sie sind mit einfachen many-to-many-Beziehungen wie Mischen und Anpassen von Pizza und Toppings tun hat, ist ein Standard-ManyToManyField alles, was Sie brauchen. Manchmal müssen Sie Daten jedoch möglicherweise der Beziehung zwischen zwei Modellen zuordnen.

Betrachten Sie zum Beispiel den Fall einer Anwendung, die die Musikgruppen verfolgt, zu denen Musiker gehören. Zwischen einer Person und den Gruppen, denen sie angehören, besteht eine Viele-zu-Viele-Beziehung. Sie können also ein ManyToManyField verwenden, um diese Beziehung darzustellen. Es gibt jedoch viele Details über die Mitgliedschaft, die Sie sammeln möchten, z. B. das Datum, zu dem die Person der Gruppe beigetreten ist.

In diesen Situationen können Sie in Django das Modell angeben, das zur Steuerung der Viele-zu-Viele-Beziehung verwendet wird. Sie können dann zusätzliche Felder auf das Zwischenmodell setzen. Das Zwischenmodell ist mit dem ManyToManyField verknüpft, wobei das Argument through verwendet wird, um auf das Modell zu verweisen, das als Vermittler fungiert. Für unsere Musiker Beispiel würde der Code wie folgt aussehen:

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) 

Jetzt, wo Sie Ihre ManyToManyField eingerichtet haben Ihr Vermittler-Modell (Mitgliedschaft, in diesem Fall) zu verwenden, sind Sie bereit zu fange an, einige Viele-zu-Viele-Beziehungen zu erstellen. Sie tun dies, indem Instanzen des Zwischenmodells:

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>] 

Quelle: http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany

Meine Frage ist, wie ich diese zusätzlichen Attribute meiner Sicht und Vorlage für den Zugriff auf sie einrichten. Angenommen, ich habe eine Bandseite, und ich möchte den Bandnamen anzeigen, die Mitgliedschaftsdatensätze durchlaufen und Namen und date_joined anzeigen.

Sollte ich ein Band-Objekt an die Vorlage übergeben? Oder übergebe ich die Membership-Objekte irgendwie?

Und wie würde ich die for-Schleifen in der Vorlage erstellen?

Danke.

+1

halte ich würde Auszüge aus django docs ein wenig zu verkürzen. Leute, die wahrscheinlich antworten werden, sind wahrscheinlich bereits mit ihnen vertraut und es wäre leichter, die tatsächliche Frage auf diese Weise zu erkennen. – cji

Antwort

32

Der einfachste Weg ist, das Band an die Vorlage zu übergeben. Vorlagen sind in der Lage, die Beziehungen zwischen Modellen zu steuern, und es gibt sowohl Mitglieder- als auch Membership_set-Queryset-Manager in der Gruppe.Also hier ist, wie ich es tun würde:

Ansicht:

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

Vorlage:

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

Das funktioniert perfekt. Ich habe versucht, iterate durch group.membership.all. Ich muss über _set nachlesen. Vielen Dank! – Alex

+0

Aber wenn Sie etwas komplizierteres benötigen, d. H. Ordnen, Filtern usw. Standard ist, es in der Ansicht zu tun und dann über den Kontext weiterzugeben? – CpILL

+0

Ein wichtiger Punkt ist, dass der Klassenname in Kleinbuchstaben der durchgehenden Tabelle "Mitgliedschaft" verwendet wird. – MagicLAMP

6

Ich bin mir nicht sicher, ob es nur Lösung oder nicht ist, aber die Übergabe von Relation-Objekten an die Vorlage funktioniert sicherlich. Ihrer Ansicht nach erhalten QuerySet die Mitgliedschaft Objekte:

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

und es Vorlage übergeben, wo Sie über ihn mit {% for %}

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

Hinweis iterieren können, dass dies keine zusätzliche Abfragen wegen select_related() durchführen sollte .