2010-07-30 18 views
39

Dalla documentazione Django ...Come accedere alle proprietà di una tabella "through" molti-a-molti da un modello django?

Quando hai solo che fare con semplici molti-a-molti, come la miscelazione e la congruenza pizze e condimenti, uno standard di ManyToManyField è tutto ciò che serve. Tuttavia, a volte potrebbe essere necessario associare i dati alla relazione tra due modelli.

Ad esempio, si consideri il caso di un'applicazione che tiene traccia dei gruppi musicali a cui appartengono i musicisti. Esiste una relazione molti-a-molti tra una persona e i gruppi di cui sono membri, quindi è possibile utilizzare ManyToManyField per rappresentare questa relazione. Tuttavia, ci sono molti dettagli sull'appartenenza che potresti voler raccogliere, come ad esempio la data in cui la persona si è unita al gruppo.

Per queste situazioni, Django consente di specificare il modello che verrà utilizzato per governare la relazione molti-a-molti. È quindi possibile inserire campi aggiuntivi sul modello intermedio. Il modello intermedio è associato a ManyToManyField utilizzando l'argomento through per indicare il modello che fungerà da intermediario. Per il nostro esempio musicista, il codice sarebbe simile a questa:

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) 

Ora che hai impostato il tuo ManyToManyField di utilizzare il modello di intermediazione (appartenenza, in questo caso), si è pronti a inizia a creare alcune relazioni molti-a-molti. A tale scopo, la creazione di istanze del modello intermedio:

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

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

La mia domanda è: come faccio a impostare la mia vista e il modello per accedere a questi attributi aggiuntivi. Diciamo che ho una pagina di banda e voglio visualizzare il nome della band, scorrere i record di appartenenza e visualizzare i nomi e date_joined.

Devo passare un oggetto banda al modello? O posso passare in qualche modo gli oggetti di appartenenza?

E come creo i loop for nel modello?

Grazie.

+1

vorrei prendere in considerazione accorciare estratti da documenti Django un po '. Le persone che probabilmente risponderanno probabilmente hanno già familiarità con loro e sarebbe più facile individuare la domanda in quel modo. – cji

risposta

32

Il modo più semplice è solo per passare la banda al modello. I modelli sono in grado di navigare le relazioni tra i modelli e sul gruppo sono presenti sia membri che gestori di set di chiavi membership_set.Quindi, ecco come lo farei:

vista:

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

modello:

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

Ciò funziona perfettamente. Stavo provando iterate attraverso group.membership.all. Ho bisogno di leggere su _set. Grazie! – Alex

+0

Ma se hai bisogno di qualcosa di più complesso, ad esempio ordinare, filtrare, ecc. La pratica standard è di farlo nella vista e poi passarla attraverso il contesto? – CpILL

+0

Un punto importante è che il nome della classe in lettere minuscole della tabella di passaggio viene utilizzato "membership" ,. – MagicLAMP

6

Non sono sicuro che sia solo una soluzione o meno, ma gli oggetti relazionali che passano al modello funzionano sicuramente. Secondo lei, ottenere QuerySet di oggetti Adesione:

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

e passarlo al modello, in cui è possibile scorrere su di esso con {% for %}

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

Si noti che questo non deve effettuare alcuna query aggiuntive a causa del select_related() .

Problemi correlati