Hier ist mein Modell:
class GroupedModels(models.Model):
other_model_one = models.ForeignKey('app.other_model')
other_model_two = models.ForeignKey('app.other_model')
Im Wesentlichen möchte ich, dass other_model
diese Tabelle eindeutig ist. Das heißt, wenn es einen Datensatz gibt, in dem sich other_model_one
id befindet 123
, sollte ich nicht zulassen, dass ein anderer Datensatz mit other_model_two
id as erstellt wird 123
. Ich kann es wohl überschreiben, clean
aber ich habe mich gefragt, ob in Django etwas eingebaut ist.
Ich verwende Version 2.2.5 mit PSQL.
Bearbeiten: Dies ist keine eindeutige Situation zusammen. Wenn ich einen Datensatz mit other_model_one_id=1
und anderen hinzufüge other_model_two_id=2
, sollte ich keinen weiteren Datensatz mit other_model_one_id=2
und anderen hinzufügen könnenother_model_two_id=1
python
django
django-models
Pittfall
quelle
quelle
Antworten:
Ich erkläre hier verschiedene Optionen, vielleicht kann eine davon oder eine Kombination für Sie nützlich sein.
Überschreiben
save
Ihre Einschränkung ist eine Geschäftsregel. Sie können die
save
Methode überschreiben , um die Datenkonsistenz zu gewährleisten:Design ändern
Ich habe eine Probe leicht verständlich gemacht. Nehmen wir dieses Szenario an:
Jetzt möchten Sie vermeiden, dass eine Mannschaft ein Spiel mit sich selbst spielt. Auch Team A kann nur einmal mit Team B spielen (fast Ihre Regeln). Sie können Ihre Modelle wie folgt umgestalten:
ManyToManyField.symmetrical
Dies sieht aus wie ein symmetrisches Problem, das Django für Sie erledigen kann. Anstatt ein
GroupedModels
Modell zu erstellen , erstellen Sie einfach ein ManyToManyField-Feld mit sich selbst aufOtherModel
:Dies ist, was Django für diese Szenarien eingebaut hat.
quelle
match_id
auf unike Einschränkung aufgenommen habe, um Teams zu erlauben, unbegrenzte Spiele zu spielen. Entfernen Sie einfach dieses Feld, um die Wiedergabe wieder einzuschränken.Es ist keine sehr befriedigende Antwort, aber leider gibt es keine Möglichkeit, das, was Sie beschreiben, mit einer einfachen integrierten Funktion zu tun.
Was Sie beschrieben haben,
clean
würde funktionieren, aber Sie müssen vorsichtig sein, um es manuell aufzurufen, da es meiner Meinung nach nur bei Verwendung von ModelForm automatisch aufgerufen wird. Möglicherweise können Sie eine komplexe Datenbankeinschränkung erstellen , die jedoch außerhalb von Django liegt, und Sie müssten Datenbankausnahmen behandeln (was in Django während einer Transaktion schwierig sein kann).Vielleicht gibt es einen besseren Weg, um die Daten zu strukturieren?
quelle
Es gibt bereits eine großartige Antwort von Dani Herrera , aber ich möchte darauf näher eingehen .
Wie in der zweiten Option erläutert, besteht die vom OP geforderte Lösung darin, das Design zu ändern und zwei eindeutige Einschränkungen paarweise zu implementieren. Die Analogie zu den Basketballspielen verdeutlicht das Problem auf sehr praktische Weise.
Anstelle eines Basketballspiels verwende ich ein Beispiel für Fußballspiele. Ein Fußballspiel (das ich es nenne
Event
) wird von zwei Teams gespielt (in meinen Modellen ist es ein TeamCompetitor
). Dies ist eine Viele-zu-Viele-Beziehung (m:n
), dien
in diesem speziellen Fall auf zwei begrenzt ist. Das Prinzip ist für eine unbegrenzte Anzahl geeignet.So sehen unsere Modelle aus:
Ein Ereignis könnte sein:
Jetzt müssen wir das Problem aus der Frage lösen. Django erstellt automatisch eine Zwischentabelle zwischen den Modellen mit einer Viele-zu-Viele-Beziehung. Wir können jedoch ein benutzerdefiniertes Modell verwenden und weitere Felder hinzufügen. Ich nenne das Modell
Participant
:Das
ManyToManyField
hat eine Optionthrough
, mit der wir das Zwischenmodell angeben können. Lassen Sie uns das im Modell ändernEvent
:Die eindeutigen Einschränkungen begrenzen jetzt automatisch die Anzahl der Teilnehmer pro Veranstaltung auf zwei (da es nur zwei Rollen gibt: Heim und Besucher ).
In einem bestimmten Ereignis (Fußballspiel) kann es nur eine Heimmannschaft und nur eine Besucherteams geben. Ein Verein (
Competitor
) kann entweder als Heimmannschaft oder als Besucherteam auftreten.Wie verwalten wir jetzt all diese Dinge im Admin? So was:
Wir haben das
Participant
als Inline in das hinzugefügtEventAdmin
. Wenn wir neue erstellenEvent
, können wir die Heimmannschaft und die Besucherteams auswählen. Die Optionmax_num
begrenzt die Anzahl der Einträge auf 2, daher können nicht mehr als 2 Teams pro Event hinzugefügt werden.Dies kann für andere Anwendungsfälle überarbeitet werden. Nehmen wir an, unsere Veranstaltungen sind Schwimmwettkämpfe und statt Heim und Besucher haben wir die Bahnen 1 bis 8. Wir überarbeiten nur Folgendes
Participant
:Mit dieser Modifikation können wir dieses Ereignis haben:
Titel: FINA 2019, 50m Backstroke Herrenfinale,
Teilnehmer:
// und so weiter Spur 5 bis Spur 8 (Quelle: Wikipedia
Ein Schwimmer kann nur einmal in einem Lauf auftreten, und eine Bahn kann nur einmal in einem Lauf besetzt werden.
Ich habe den Code an GitHub gesendet: https://github.com/cezar77/competition .
Alle Credits gehen wieder an dani herrera. Ich hoffe, diese Antwort bietet den Lesern einen Mehrwert.
quelle