Veillez à réaliser qu'il existe des différences entre OneToOneField(SomeModel)
et ForeignKey(SomeModel, unique=True)
. Comme indiqué dans le guide définitif de Django :
OneToOneField
Une relation un à un. Conceptuellement, ceci est similaire à un ForeignKey
avec unique=True
, mais le côté "inverse" de la relation renvoie directement un seul objet.
Contrairement à la OneToOneField
relation "inverse", une relation ForeignKey
"inverse" renvoie a QuerySet
.
Exemple
Par exemple, si nous avons les deux modèles suivants (code complet du modèle ci-dessous):
Car
modèle utilise OneToOneField(Engine)
Car2
modèle utilise ForeignKey(Engine2, unique=True)
De l'intérieur, python manage.py shell
exécutez ce qui suit:
OneToOneField
Exemple
>>> from testapp.models import Car, Engine
>>> c = Car.objects.get(name='Audi')
>>> e = Engine.objects.get(name='Diesel')
>>> e.car
<Car: Audi>
ForeignKey
avec l' unique=True
exemple
>>> from testapp.models import Car2, Engine2
>>> c2 = Car2.objects.get(name='Mazda')
>>> e2 = Engine2.objects.get(name='Wankel')
>>> e2.car2_set.all()
[<Car2: Mazda>]
Code modèle
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
fonctionne également?ForeignKey
avecunique=True
plutôt qu'unOneToOneField
? Je vois dans d'autres questions que Django prévient même queOneToOneField
les intérêts de chacun sont généralement les meilleurs. L'inverseQuerySet
n'aura jamais plus d'un élément, non?Une clé étrangère est pour un à plusieurs, donc un objet Car peut avoir plusieurs roues, chaque roue ayant une clé étrangère à la voiture à laquelle il appartient. Un OneToOneField serait comme un moteur, où un objet Car peut en avoir un et un seul.
la source
Le meilleur moyen et le plus efficace d'apprendre de nouvelles choses est de voir et d'étudier des exemples pratiques du monde réel. Supposons un instant que vous souhaitiez créer un blog dans django où les journalistes peuvent écrire et publier des articles de presse. Le propriétaire du journal en ligne souhaite autoriser chacun de ses reporters à publier autant d'articles qu'il le souhaite, mais ne souhaite pas que différents reporters travaillent sur le même article. Cela signifie que lorsque les lecteurs vont lire un article, ils ne voient qu'un seul auteur dans l'article.
Par exemple: Article de John, Article de Harry, Article de Rick. Vous ne pouvez pas avoir un article de Harry & Rick parce que le patron ne veut pas que deux ou plusieurs auteurs travaillent sur le même article.
Comment pouvons-nous résoudre ce «problème» avec l'aide de Django? La clé de la solution de ce problème est le django
ForeignKey
.Ce qui suit est le code complet qui peut être utilisé pour implémenter l'idée de notre patron.
Exécutez
python manage.py syncdb
pour exécuter le code SQL et créer les tables de votre application dans votre base de données. Ensuite, utilisezpython manage.py shell
pour ouvrir un shell python.Créez l'objet Reporter R1.
Créez l'objet Article A1.
Utilisez ensuite le code suivant pour obtenir le nom du reporter.
Créez maintenant l'objet Reporter R2 en exécutant le code python suivant.
Essayez maintenant d'ajouter R2 à l'objet Article A1.
Cela ne fonctionne pas et vous obtiendrez une AttributeError disant que l'objet 'Reporter' n'a pas d'attribut 'add'.
Comme vous pouvez le voir, un objet Article ne peut pas être lié à plusieurs objets Reporter.
Et R1? Pouvons-nous y attacher plusieurs objets Article?
Cet exemple pratique nous montre que django
ForeignKey
est utilisé pour définir des relations plusieurs-à-un.OneToOneField
est utilisé pour créer des relations un à un.Nous pouvons utiliser
reporter = models.OneToOneField(Reporter)
dans le fichier models.py ci-dessus mais cela ne sera pas utile dans notre exemple car un auteur ne pourra pas poster plus d'un article.Chaque fois que vous souhaitez publier un nouvel article, vous devrez créer un nouvel objet Reporter. C'est long, n'est-ce pas?
Je recommande fortement d'essayer l'exemple avec le
OneToOneField
et de réaliser la différence. Je suis presque sûr qu'après cet exemple, vous saurez complètement la différence entre djangoOneToOneField
et djangoForeignKey
.la source
OneToOneField (one-to-one) réalise, en orientation objet, la notion de composition, tandis que ForeignKey (one-to-many) concerne l'agrégation.
la source
Patient
etOrgan
.Patient
peut avoir plusieursOrgan
s, mais unOrgan
ne peut appartenir qu'à un seulPatient
. LorsquePatient
est supprimé, tous lesOrgan
s sont également supprimés. Ils ne peuvent pas exister sansPatient
.Il
OneToOneField
est également utile d'être utilisé comme clé primaire pour éviter la duplication des clés. On peut ne pas avoir de champ automatique implicite / explicitemais utilisez
OneToOneField
plutôt comme clé primaire (imaginez unUserProfile
modèle par exemple):la source
Lorsque vous accédez à OneToOneField, vous obtenez la valeur du champ que vous avez interrogé. Dans cet exemple, le champ «titre» d'un modèle de livre est un champ OneToOneField:
Lorsque vous accédez à une clé étrangère, vous obtenez l'objet de modèle associé, sur lequel vous pouvez ensuite effectuer d'autres requêtes. Dans cet exemple, le champ «éditeur» du même modèle de livre est une clé étrangère (en corrélation avec la définition du modèle de classe Publisher):
Avec les champs ForeignKey, les requêtes fonctionnent également dans l'autre sens, mais elles sont légèrement différentes en raison de la nature non symétrique de la relation.
Dans les coulisses, book_set est juste un QuerySet et peut être filtré et découpé comme n'importe quel autre QuerySet. Le nom d'attribut book_set est généré en ajoutant le nom du modèle en minuscule à _set.
la source
OneToOneField: si la deuxième table est liée à
table2 contiendra un seul enregistrement correspondant à la valeur pk de table1, c'est-à-dire que table2_col1 aura une valeur unique égale à pk de table
table2 peut contenir plusieurs enregistrements correspondant à la valeur pk de table1.
la source
ForeignKey vous permet de recevoir des sous-classes si c'est la définition d'une autre classe mais OneToOneFields ne peut pas le faire et il n'est pas attachable à plusieurs variables
la source