Achten Sie darauf, dass es einige Unterschiede zwischen OneToOneField(SomeModel)
und gibt ForeignKey(SomeModel, unique=True)
. Wie im endgültigen Leitfaden für Django angegeben :
OneToOneField
Eine Eins-zu-Eins-Beziehung. Konzeptionell ähnelt dies einem ForeignKey
with unique=True
, aber die "umgekehrte" Seite der Beziehung gibt direkt ein einzelnes Objekt zurück.
Im Gegensatz zur OneToOneField
"umgekehrten" Beziehung gibt eine ForeignKey
"umgekehrte" Beziehung a zurück QuerySet
.
Beispiel
Zum Beispiel, wenn wir die folgenden zwei Modelle haben (vollständiger Modellcode unten):
Car
Modell verwendet OneToOneField(Engine)
Car2
Modell verwendet ForeignKey(Engine2, unique=True)
python manage.py shell
Führen Sie von innen Folgendes aus:
OneToOneField
Beispiel
>>> from testapp.models import Car, Engine
>>> c = Car.objects.get(name='Audi')
>>> e = Engine.objects.get(name='Diesel')
>>> e.car
<Car: Audi>
ForeignKey
mit unique=True
Beispiel
>>> from testapp.models import Car2, Engine2
>>> c2 = Car2.objects.get(name='Mazda')
>>> e2 = Engine2.objects.get(name='Wankel')
>>> e2.car2_set.all()
[<Car2: Mazda>]
Modellnummer
from django.db import models
class Engine(models.Model):
name = models.CharField(max_length=25)
def __unicode__(self):
return self.name
class Car(models.Model):
name = models.CharField(max_length=25)
engine = models.OneToOneField(Engine)
def __unicode__(self):
return self.name
class Engine2(models.Model):
name = models.CharField(max_length=25)
def __unicode__(self):
return self.name
class Car2(models.Model):
name = models.CharField(max_length=25)
engine = models.ForeignKey(Engine2, unique=True, on_delete=models.CASCADE)
def __unicode__(self):
return self.name
e.car
funktioniert , wenn der Fremdschlüssel eindeutig und nicht null ist ?ForeignKey
mitunique=True
anstatt eines verwenden wollenOneToOneField
? Ich sehe in anderen Fragen, dass Django sogar warnt, dassOneToOneField
die Interessen eines normalerweise am besten dienen. Das GegenteilQuerySet
wird niemals mehr als ein Element haben, oder?Ein ForeignKey ist für eins zu viele, daher kann ein Autoobjekt viele Räder haben, wobei jedes Rad einen ForeignKey für das Auto hat, zu dem es gehört. Ein OneToOneField wäre wie ein Motor, bei dem ein Autoobjekt nur einen haben kann.
quelle
Der beste und effektivste Weg, neue Dinge zu lernen, besteht darin, praktische Beispiele aus der Praxis zu sehen und zu studieren. Angenommen, Sie möchten für einen Moment ein Blog in Django erstellen, in dem Reporter Nachrichtenartikel schreiben und veröffentlichen können. Der Inhaber der Online-Zeitung möchte jedem seiner Reporter erlauben, so viele Artikel zu veröffentlichen, wie er möchte, möchte jedoch nicht, dass verschiedene Reporter an demselben Artikel arbeiten. Dies bedeutet, dass Leser, die einen Artikel lesen, nur einen Autor im Artikel sehen.
Zum Beispiel: Artikel von John, Artikel von Harry, Artikel von Rick. Sie können keinen Artikel von Harry & Rick haben, da der Chef nicht möchte, dass zwei oder mehr Autoren an demselben Artikel arbeiten.
Wie können wir dieses "Problem" mit Hilfe von Django lösen? Der Schlüssel zur Lösung dieses Problems ist der Django
ForeignKey
.Das Folgende ist der vollständige Code, mit dem die Idee unseres Chefs umgesetzt werden kann.
Führen Sie
python manage.py syncdb
diese Option aus, um den SQL-Code auszuführen und die Tabellen für Ihre App in Ihrer Datenbank zu erstellen. Verwenden Sie dannpython manage.py shell
, um eine Python-Shell zu öffnen.Erstellen Sie das Reporter-Objekt R1.
Erstellen Sie das Artikelobjekt A1.
Verwenden Sie dann den folgenden Code, um den Namen des Reporters abzurufen.
Erstellen Sie nun das Reporter-Objekt R2, indem Sie den folgenden Python-Code ausführen.
Versuchen Sie nun, R2 zum Artikelobjekt A1 hinzuzufügen.
Es funktioniert nicht und Sie erhalten einen AttributeError, der besagt, dass das Objekt 'Reporter' kein Attribut 'add' hat.
Wie Sie sehen, kann ein Artikelobjekt nicht mit mehr als einem Reporterobjekt verknüpft werden.
Was ist mit R1? Können wir mehr als ein Artikelobjekt daran anhängen?
Dieses praktische Beispiel zeigt uns, dass Django
ForeignKey
verwendet wird, um viele-zu-eins-Beziehungen zu definieren.OneToOneField
wird verwendet, um Eins-zu-Eins-Beziehungen zu erstellen.Wir können
reporter = models.OneToOneField(Reporter)
die obige Datei models.py verwenden, sie ist jedoch in unserem Beispiel nicht hilfreich, da ein Autor nicht mehr als einen Artikel veröffentlichen kann.Jedes Mal, wenn Sie einen neuen Artikel veröffentlichen möchten, müssen Sie ein neues Reporter-Objekt erstellen. Das ist zeitaufwändig, nicht wahr?
Ich empfehle dringend, das Beispiel mit dem zu versuchen
OneToOneField
und den Unterschied zu erkennen. Ich bin mir ziemlich sicher, dass Sie nach diesem Beispiel den Unterschied zwischen DjangoOneToOneField
und Django vollständig kennenForeignKey
.quelle
OneToOneField (Eins-zu-Eins) verwirklicht in der Objektorientierung den Begriff der Komposition, während ForeignKey (Eins-zu-Viele) sich auf Agregation bezieht.
quelle
Patient
undOrgan
.Patient
kann vieleOrgan
s haben, aber eineOrgan
kann nur zu einem gehörenPatient
. WennPatient
gelöscht wird, werden auch alleOrgan
s gelöscht. Sie können nicht ohne existierenPatient
.Es
OneToOneField
ist auch nützlich, als Primärschlüssel verwendet zu werden, um das Duplizieren von Schlüsseln zu vermeiden. Man kann kein implizites / explizites Autofeld habenVerwenden Sie
OneToOneField
stattdessen den Primärschlüssel (stellen Sie sich beispielsweise einUserProfile
Modell vor):quelle
Wenn Sie auf ein OneToOneField zugreifen, erhalten Sie den Wert des abgefragten Feldes. In diesem Beispiel ist das Titelfeld eines Buchmodells ein OneToOneField:
Wenn Sie auf einen ForeignKey zugreifen, erhalten Sie das zugehörige Modellobjekt, für das Sie weitere Abfragen durchführen können. In diesem Beispiel ist das Feld "Publisher" des gleichen Buchmodells ein ForeignKey (korreliert mit der Definition des Publisher-Klassenmodells):
Bei ForeignKey-Feldern funktionieren Abfragen auch umgekehrt, unterscheiden sich jedoch aufgrund der nicht symmetrischen Natur der Beziehung geringfügig.
Hinter den Kulissen ist book_set nur ein QuerySet und kann wie jedes andere QuerySet gefiltert und in Scheiben geschnitten werden. Der Attributname book_set wird generiert, indem der Modellname in Kleinbuchstaben an _set angehängt wird.
quelle
OneToOneField: Wenn die zweite Tabelle mit verwandt ist
Tabelle2 enthält nur einen Datensatz, der dem pk-Wert von Tabelle1 entspricht, dh table2_col1 hat einen eindeutigen Wert, der pk der Tabelle entspricht
Tabelle2 kann mehr als einen Datensatz enthalten, der dem pk-Wert von Tabelle1 entspricht.
quelle
Mit ForeignKey können Sie Unterklassen empfangen, wenn es sich um eine Definition einer anderen Klasse handelt. OneToOneFields kann dies jedoch nicht und kann nicht an mehrere Variablen angehängt werden
quelle