2011-02-15 12 views
7

Drodzy ludzie starają się pomóc innym,Django ORM sposób przeżywa wielu wiele do wielu relacji

Próbuję dowiedzieć się, jak uzyskać Django zrobić sprzężenie dla mnie bez pisania niestandardowego SQL.

Powiedzmy mam następujące modele

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 

Rodzic może mieć wiele dzieci. Dziecko może mieć wielu rodziców. Dziecko może posiadać wiele zabawek. Zabawki mogą być własnością wielu dzieci.

Chcę uzyskać listę wszystkich zabawek należących do Dzieci Rodzica.

więc mogę robić takie rzeczy jak: parent.children.all() i child.toys.all()

co chcę zrobić, to coś jak parent.children.toys.all() Kiedy próbuję to zrobić uzyskać: AttributeError: 'ManyRelatedManager' object has no attribute 'toys'. Rozumiem błąd - parent.children zwraca wiele rekordów. To jest oczekiwane. To, czego nie mogę zrozumieć, to dać Django wskazówkę, że chcę dodać dodatkowe sprzężenie do jego zapytania.

Czy jest sposób, w jaki mogę to zrobić, dołączyć do Django, czy też muszę przejść do niestandardowego kodu SQL, aby to zrobić?

Uwaga: powyższe ma jedynie na celu zilustrowanie mojego problemu, rzeczywiste modele, których używam, nie są istotne. Mój problem jest naprawdę próbuje dowiedzieć się, jak dołączyć przez wiele relacji M2M w Django bez konieczności uciekania się do SQL.

Doceniam Twoją pomoc z góry. Dzięki!

+2

nie chcę, aby napisać nową odpowiedź, ale chciałbym dodać link do docs: http : //docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships dla informacji na temat DANGO JOINs szczególnie pomocne będzie dowiedzieć się, w jaki sposób analiza łańcucha() wpływa na zapytanie m2m: –

Odpowiedz

7

Wystarczy napisać coś takiego:

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

_odpowiedzi i rodzice –

2

Jeśli nie przechowywać dodatkowe informacje w tabelach pośrednich Parent_Child i Child_Toy można po prostu zostawić je - Django stworzy je automatycznie. Tak uproszczona konfiguracja może wyglądać następująco:

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) 

Można zapytać zabawki dla danego rodzica za pomocą field lookups.

Toy.objects.filter(owner__parent__id=1) 

Lub:

Toy.objects.filter(owner__parent=parent) 

resulting SQL wygląda mniej więcej tak:

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