2011-02-15 7 views
7

Estimados personas que tratan de ayudar a los demás,ORM de Django forma de recorrer múltiples de muchos a muchos relación

Estoy tratando de encontrar la manera de llegar Django para hacer una unión para mí sin escribir SQL personalizado.

Digamos que tengo los siguientes modelos

class Parent(models.Model): 
    name = models.CharField() 
    children = models.ManyToManyField(Child, through="Parent_Child", related_name="parents") 

class Parent_Child(models.Model): 
    parent = models.ForeignKey(Parent, related_name='attached_children') 
    child = models.ForeignKey(Child, related_name='attached_parents') 

class Child(models.Model): 
    name = models.CharField() 
    toys = models.ManyToManyField(Toy, hrough="Child_Toy", related_name="toy_owners") 

class Child_Toy(models.Model): 
    child = models.ForeignKey(Child, related_name='attached_toys') 
    toy = models.ForeignKey(Toy, related_name='toy_owner') 

class Toy(models.Model): 
    name = models.CharField 

Un padre puede tener varios hijos. Un niño puede tener múltiples padres. Un niño puede ser dueño de múltiples juguetes. Los juguetes pueden ser propiedad de varios niños.

Quiero obtener una lista de todos los juguetes propiedad de los Hijos de un padre.

lo tanto, puedo hacer cosas como: parent.children.all() y child.toys.all()

lo que yo quiero hacer es algo así como parent.children.toys.all() Cuando trato de hacer esto me sale: AttributeError: 'ManyRelatedManager' object has no attribute 'toys'. Entiendo el error: parent.children devuelve varios registros. Esto es esperado. Lo que no puedo entender es cómo darle a Django la pista de que quiero que agregue una combinación adicional a su consulta.

¿Hay alguna manera de hacer esto para unirme a Django o tengo que ir a SQL personalizado para hacer esto?

Tenga en cuenta: Lo anterior solo pretende ilustrar mi problema, los modelos reales que estoy usando no son tan relevantes. Mi problema es realmente tratar de descubrir cómo unirme a través de múltiples relaciones M2M en Django sin tener que recurrir a SQL.

Agradezco su ayuda con anticipación. ¡Gracias!

+2

no quiero escribir una nueva respuesta, pero podría añadir un enlace a la documentación: http : //docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships para obtener información sobre django JOINs específicamente, será útil aprender cómo encadenar filter() afecta su consulta m2m –

Respuesta

7

Basta con escribir algo como:

Toy.objects.filter(toy_owners__parents=parent) 
+0

qué _Los propietarios y __parents significan? –

2

Si no almacenar información adicional en las tablas intermedias Parent_Child y Child_Toy que sólo puede dejarlos fuera - Django creará automáticamente por usted. Por lo que una configuración simplificada se vería así:

class Parent(models.Model): 
    name = models.CharField(max_length=80) 
    children = models.ManyToManyField('Child', related_name="parent") 

class Child(models.Model): 
    name = models.CharField(max_length=80) 
    toys = models.ManyToManyField('Toy', related_name="owner") 

class Toy(models.Model): 
    name = models.CharField(max_length=80) 

Puede consultar los juguetes para un padre específico mediante field lookups.

Toy.objects.filter(owner__parent__id=1) 

O:

Toy.objects.filter(owner__parent=parent) 

El resulting SQL se ve algo como esto:

SELECT "toy"."id", "toy"."name" FROM "toy" 
    INNER JOIN "child_toys" 
     ON ("toy"."id" = "child_toys"."toy_id") 
    INNER JOIN "child" 
     ON ("child_toys"."child_id" = "child"."id") 
    INNER JOIN "parent_children" 
     ON ("child"."id" = "parent_children"."child_id") 
    WHERE "parent_children"."parent_id" = 1 
Cuestiones relacionadas