2014-10-18 12 views
9

Also ich bin neu in Django, und will das Szenario beschreiben: es gibt eine Reihe von Persons, und es gibt eine Reihe von Items, und eine Person geht Items zum anderen Person .Django: Modell verfügt über zwei ManyToMany Beziehungen durch Zwischenmodell

Ich habe folgendes Modell:

class Item(models.Model): 
    title = models.CharField(max_length=1024, blank=False) 

    def __unicode__(self): 
     return self.title 

class Person(models.Model): 
    name = models.CharField(max_length=127, blank=False) 
    out_item = models.ManyToManyField(
     Item, 
     through='Event', 
     through_fields=('from_user', 'item'), 
     related_name='giver' 
    ) 
    in_item = models.ManyToManyField(
     Item, 
     through='Event', 
     through_fields=('to_user', 'item'), 
     related_name='receiver' 
    ) 

    def __unicode__(self): 
     return self.name 

class Event(models.Model): 
    item = models.ForeignKey(Item) 
    from_user = models.ForeignKey(Person, related_name='event_as_giver') 
    to_user = models.ForeignKey(Person, related_name='event_as_receiver') 

Aber makemigrations sagt mir app.Person: (models.E003) The model has two many-to-many relations through the intermediate model 'app.Event'.

Ich frage mich, was ich falsch gemacht habe? Oder was ist ein sauberer Weg, um das Szenario zu erreichen? Vielleicht kann ich Event in GiveEvent und ReceiveEvent trennen? Aber das macht intuitiv weniger Sinn, da es tatsächlich nur ein einziges Ereignis gibt, wenn ein Item übergeben wird.

+0

Es scheint, dass das neue Django-System-Check-Framework zwei Viele-zu-Viele-Felder im selben Modell nicht akzeptiert, die das gleiche "Through" -Modell verwenden. Deshalb schlägt dies fehl, wie die Fehlermeldung suggeriert. Das ist das erwartete Verhalten für Ihren Fall. Aber was ich frage ist, warum ist es so implementiert und verbietet es .. Gute Frage .. –

Antwort

5

Was Sie beschreiben, klingt vernünftig genug. Es kann einen technischen Grund geben, warum das nicht erlaubt ist; Ein semantischer Grund ist, dass jede ManyToManyField die Erstellung einer neuen Tabelle impliziert, und es kann nicht zwei Tabellen mit demselben Namen geben (d. h. durch die gleiche Klasse repräsentiert).

Ein alternativer Ansatz (kürzer und DRY) wäre dies:

class Person(models.Model): 
    name = models.CharField(max_length=127, blank=False) 
    to_users = models.ManyToManyField(
     'self', 
     symmetrical=False, 
     related_name='from_users', 
     through='Event', 
     through_fields=('from_user', 'to_user'), 
    ) 

class Event(models.Model): 
    item = models.ForeignKey(Item, related_name='events') 
    from_user = models.ForeignKey(Person, related_name='events_as_giver') 
    to_user = models.ForeignKey(Person, related_name='events_as_receiver') 

Die Tabellenstruktur ist die gleiche, aber die Deskriptoren sind unterschiedlich. Zugriff auf verwandte Menschen ist ein wenig einfacher, aber Zugriff auf verwandte Elemente ist ein bisschen schwieriger (zum Beispiel statt person.out_items.all() würden Sie sagen Item.objects.filter(events__from_user=person).distinct()).

+0

Die Zeile 'Item.Objects.Filter (events__from_user = Person) .Distinct()' funktioniert nicht ..... Person nicht definiert –

Verwandte Themen