Django ForeignKey, das keine referenzielle Integrität erfordert?

8

Ich möchte ein ForeignKey -Feld in einem Django-Modell einrichten, das manchmal auf eine andere Tabelle zeigt. Aber ich möchte, dass es in Ordnung ist, eine ID in dieses Feld einzufügen, die sich auf einen Eintrag in der anderen Tabelle bezieht, der möglicherweise nicht dort ist. Wenn also die Zeile in der anderen Tabelle vorhanden ist, möchte ich alle Vorteile der ForeignKey-Beziehung nutzen. Aber wenn nicht, würde ich das als eine Nummer behandeln lassen.

Ist das möglich? Ist das was generische Beziehungen sind?

    
Leopd 24.08.2010, 16:54
quelle

5 Antworten

6

Diese Frage wurde vor langer Zeit gestellt, aber für Neulinge gibt es jetzt eine eingebaute Möglichkeit, dies zu handhaben, indem Sie db_constraint = False auf ForeignKey setzen:

Ссылка

%Vor%

oder wenn Sie NULL-Werte haben möchten und nicht referentielle Integrität erzwingen wollen:

%Vor%

Wir verwenden dies in Fällen, in denen wir nicht garantieren können, dass die Beziehungen in der richtigen Reihenfolge erstellt werden.

BEARBEITEN: Link aktualisieren

    
brandon 27.02.2014, 22:47
quelle
3

Ich bin neu in Django, also tue ich es jetzt nicht, wenn es das bietet, was Sie wollen, out-of-the-box. Ich dachte an so etwas:

%Vor%

Ich weiß nicht, ob Sie die contrib-Admin-App verwenden. Mit PositiveIntegerField anstelle von ForeignKey würde das Feld mit einem Textfeld auf der Admin-Site gerendert werden.

    
matheus.emm 24.08.2010 18:07
quelle
3

Das ist wahrscheinlich so einfach, wie einen ForeignKey zu deklarieren und die Spalte zu erstellen, ohne sie als FOREIGN KEY zu deklarieren. Auf diese Weise erhalten Sie o.obj_id, o.obj wird funktionieren, wenn das Objekt existiert, und - ich denke - eine Ausnahme auslösen, wenn Sie versuchen, ein Objekt zu laden, das nicht wirklich existiert (wahrscheinlich DoesNotExist ) .

Ich glaube jedoch nicht, dass Sie syncdb für sich tun können. Ich fand syncdb so einschränkend, dass es nutzlos ist, also umgehe ich es komplett und erstelle das Schema mit meinem eigenen Code. Sie können syncdb verwenden, um die Datenbank zu erstellen, und dann die Tabelle direkt ändern, z. ALTER TABLE tablename DROP CONSTRAINT fk_constraint_name .

Sie verlieren natürlich auch ON DELETE CASCADE und alle referenziellen Integritätsprüfungen.

    
Glenn Maynard 30.09.2010 09:42
quelle
3

Um die Lösung von @Glenn Maynard über South zu erstellen, erzeuge eine leere Südmigration:

python manage.py schemamigration myapp name_of_migration --empty

Bearbeiten Sie die Migrationsdatei und führen Sie sie dann aus:

%Vor%

Quellenartikel

    
Sooie 26.04.2013 21:56
quelle
1

(Hinweis: Es könnte hilfreich sein, wenn Sie erklären, warum Sie dies möchten. Es könnte einen besseren Weg geben, sich dem zugrunde liegenden Problem zu nähern.)

  

Ist das möglich?

Nicht nur mit ForeignKey, weil Sie die Spaltenwerte mit zwei verschiedenen Bedeutungen überladen, ohne eine zuverlässige Unterscheidung zu finden. (Was würde beispielsweise passieren, wenn ein neuer Eintrag in der Zieltabelle mit einem Primärschlüssel erstellt wird, der mit alten Einträgen in der Referenztabelle übereinstimmt? Was würde mit diesen alten Referenzeinträgen geschehen, wenn der neue Zieleintrag gelöscht wird?)

Die übliche Ad-hoc-Lösung für dieses Problem besteht darin, neben dem Fremdschlüssel eine "type" - oder "tag" -Spalte zu definieren, um die verschiedenen Bedeutungen zu unterscheiden (siehe unten).

  

Ist das was generische Beziehungen sind?

Ja, teilweise.

GenericForeignKey ist nur ein Django-Hilfsprogramm für das obige Muster; es paart einen Fremdschlüssel mit einem Typ-Tag, das angibt, auf welche Tabelle / Modell es verweist (mit dem zugeordneten ContentType des Modells; siehe contenttypes )

Beispiel:

%Vor%

Damit können Sie other wie einen ForeignKey verwenden, um auf Instanzen Ihres anderen Modells zu verweisen. (Im Hintergrund erhält und setzt GenericForeignKey other_type und other_id für Sie.)

Um eine Zahl darzustellen, die keine Referenz ist, würden Sie other_type auf None setzen und einfach other_id direkt verwenden. In diesem Fall gibt der Zugriff auf other immer None zurück, anstatt DoesNotExist zu erhöhen (oder ein unbeabsichtigtes Objekt aufgrund einer ID-Kollision zurückzugeben).

    
Pi Delport 01.10.2010 19:58
quelle