2017-05-22 5 views
1

Ich möchte paarweise Beziehungen zwischen allen Mitgliedern eines Satzes modellieren.Django ungerichtet unique-together

class Match(models.Model): 

    foo_a = models.ForeignKey(Foo, related_name='foo_a') 
    foo_b = models.ForeignKey(Foo, related_name='foo_b') 

    relation_value = models.IntegerField(default=0) 

    class Meta: 
     unique_together = ('ingredient_a', 'ingredient_b') 

Wenn ich ein Paar A-B hinzufügen, es hindert mich erfolgreich aus der Addition wieder A-B, aber nicht daran hindert mich nicht aus dem B-A hinzufügen.

Ich versuchte folgendes, aber ohne Erfolg.

unique_together = (('ingredient_a', 'ingredient_b'), ('ingredient_b', 'ingredient_a')) 

Edit: muss ich die relationship_value für jedes Paar von Elementen

Antwort

1

ich das speichern Methode der habe außer Kraft gesetzt Objekt, um jedes Mal 2 Paare zu speichern. Wenn der Benutzer ein Paar A-B hinzufügen möchte, wird automatisch ein Datensatz B-A mit den gleichen Parametern hinzugefügt.

Hinweis: Diese Lösung wirkt sich auf die Abfragegeschwindigkeit aus. Für mein Projekt ist das kein Problem, aber es muss berücksichtigt werden.

def save(self, *args, **kwargs): 
    if not Match.objects.filter(foo_a=self.foo_a, foo_b=self.foo_b).exists(): 
     super(Match, self).save(*args, **kwargs) 
    if not Match.objects.filter(foo_a=self.foo_b, foo_b=self.foo_a).exists(): 
     Match.objects.create(foo_a=self.foo_b, foo_b=self.foo_a, bar=self.bar) 

EDIT: aktualisieren und entfernen Methoden müssen natürlich auch außer Kraft gesetzt werden.

1

eindeutig sein Wenn Sie ein Modell wie definieren, was Sie definiert, es ist nicht nur eine ForeignKey, sein genannt ManyToMany Beziehung.

In den django-Dokumenten ist explizit definiert, dass die eindeutige zusammengesetzte Einschränkung für eine ManyToMany-Beziehung nicht enthalten sein darf.

Aus den Dokumenten,

A ManyToManyField nicht in unique_together aufgenommen werden können. (Es ist nicht klar, was das überhaupt bedeuten würde!) Wenn Sie die Eindeutigkeit eines ManyToManyField überprüfen müssen, versuchen Sie es mit einem Signal oder einem expliziten Through-Modell.

EDIT

Nach viel suchen und einige Versuch und Irrtum und schließlich ich glaube, ich habe eine Lösung für Ihr Szenario gefunden. Ja, wie Sie sagten, ist das gegenwärtige Schema nicht so trivial wie wir alle denken. In diesem Zusammenhang ist die Beziehung Viele zu viele nicht die Diskussion, die wir weiterleiten müssen. Die Lösung ist, (oder was ich denke, die Lösung ist) sauber Modell Methode:

class Match(models.Model): 
    foo_a = models.ForeignKey(Foo, related_name='foo_a') 
    foo_b = models.ForeignKey(Foo, related_name='foo_b') 

    def clean(self): 
     a_to_b = Foo.objects.filter(foo_a = self.foo_a, foo_b = self.foo_b) 
     b_to_a = Foo.objects.filter(foo_a = self.foo_b, foo_b = self.foo_a) 

     if a_to_b.exists() or b_to_a.exists(): 
      raise ValidationError({'Exception':'Error_Message')}) 

Für weitere Informationen über Modell saubere Methode, beziehen sich die docs here...

+0

Ich möchte, dass der relationship_value für alle zwei gegebenen Elemente eindeutig ist. Das bedeutet, dass Sie die ManyToMany-Beziehung auf jeweils nur 1 Element beschränken müssen, was meines Wissens nicht trivial ist. –

+0

Ihre Bearbeitung verhindert Inkonsistenzen. Danke für die Eingabe. Ich löste es, indem ich redundante Paare A-B, B-A schuf. Die Tabelle wird nicht für Produktionsabfragen verwendet, sondern nur, um eine Konfusionsmatrix für die zukünftige Verwendung zu erstellen, sodass die Leistung kein Problem darstellt. Ich frage mich immer noch, welcher der beiden Ansätze wäre besser, wenn Leistung berücksichtigt werden müsste. Ihr Ansatz hat den Vorteil, dass Sie die Methoden zum Aktualisieren und Entfernen nicht überschreiben müssen. –

+0

Froh, ich könnte eine Hilfe sein ... – zaidfazil

Verwandte Themen