python - tutorial - the django project
¿Cómo puedo acceder a las propiedades de una tabla "a través" de muchos a muchos desde una plantilla django? (2)
De la documentación de Django ...
Cuando solo se trata de relaciones simples de varios a muchos, como mezclar y combinar pizzas y ingredientes, un estándar de ManyToManyField es todo lo que necesita. Sin embargo, a veces puede necesitar asociar datos con la relación entre dos modelos.
Por ejemplo, considere el caso de una aplicación que rastrea los grupos musicales a los que pertenecen los músicos. Existe una relación de muchos a muchos entre una persona y los grupos de los que son miembros, por lo que podría usar ManyToManyField para representar esta relación. Sin embargo, hay muchos detalles sobre la membresía que podría querer recopilar, como la fecha en que la persona se unió al grupo.
Para estas situaciones, Django le permite especificar el modelo que se utilizará para gobernar la relación de muchos a muchos. A continuación, puede poner campos adicionales en el modelo intermedio. El modelo intermedio está asociado con ManyToManyField utilizando el argumento through para apuntar al modelo que actuará como intermediario. Para nuestro ejemplo de músico, el código sería algo como esto:
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)
Ahora que ha configurado ManyToManyField para usar su modelo de intermediario (Membresía, en este caso), está listo para comenzar a crear relaciones de muchos a muchos. Para ello, crea instancias del modelo 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>]
fuente: http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany
Mi pregunta es, ¿cómo configuro mi vista y plantilla para acceder a estos atributos adicionales? Supongamos que tengo una página de banda y deseo mostrar el nombre de la banda, repetir los registros de membresía y mostrar los nombres y la fecha_unidada.
¿Debo pasar un objeto de banda a la plantilla? ¿O paso los objetos de membresía de alguna manera?
¿Y cómo crearía los bucles for en la plantilla?
Gracias.
La forma más fácil es simplemente pasar la banda a la plantilla. Las plantillas son capaces de navegar por las relaciones entre los modelos y hay tanto miembros como administradores de conjunto de consultas de membership_set en el Grupo. Así que aquí es cómo lo haría:
ver:
def group_details(request, group_id):
group = get_object_or_404(Group, pk=group_id)
return render_to_response(''group_details.html'',
{''group'': group})
modelo:
<h2>{{ group.name }}</h2>
{% for membership in group.membership_set.all %}
<h3>{{ membership.person }}</h3>
{{ membership.date_joined }}
{% endfor %}
No estoy seguro de si es solo una solución o no, pero pasar objetos de relación a la plantilla ciertamente funciona. En su opinión, obtenga QuerySet de los objetos de Membresía:
rel = Membership.objects.filter( group = your_group ).select_related()
y pasarlo a la plantilla, donde puedes iterar sobre él con {% for %}
{% for r in rel %}
{{ r.person.name }} joined group {{ r.group.name }} on {{ r.date_joined }}<br />
{% endfor %}
Tenga en cuenta que esto no debería realizar ninguna consulta adicional debido a select_related()
.