Utilisez une clé étrangère pour une relation un-à-plusieurs
Jusqu'à présent, nous avons travaillé avec un seul modèle à la fois. Nous créons des objets Band, et nous créons des objets Listing, mais nous ne travaillons qu'avec l'un d'entre eux à la fois. Il est temps de les réunir !
Pensez aux entités du monde réel que nos modèles représentent. Les différentes listes d’articles que nous avons : posters, vêtements, etc., ils sont tous liés à un groupe. Un utilisateur peut arriver sur le site et être intéressé par la liste des articles d'un groupe spécifique qui l'intéresse. Ce serait formidable si nous pouvions permettre à l'utilisateur d'afficher une page avec les annonces uniquement liées à ce groupe.
Pour ce faire, nous devons créer une relation entre le modèle Band
et le modèle Listing
.
L'une des relations les plus courantes entre deux modèles est la relation « one-to-many » (un-à-plusieurs).
Par exemple, nous pourrions dire qu'un Band
peut avoir de nombreux Listing
apparentés, mais chaque Listing
ne peut avoir qu'un seul Band
apparenté.
Ainsi, nous pourrions avoir un T-shirt, une affiche et un billet de concert tous liés au groupe « De La Soul ». Le groupe est lié à 3 annonces, mais chacune de ces annonces n’est liée qu’à un seul groupe. Un article ne peut pas être lié à la fois à « De La Soul » et à « Foo Fighters » en même temps.
Voyons comment créer une relation « one-to-many » entre les modèles Band
et Listing
.
Examinons quelques données sur nos deux tables dans la base de données (certains champs/colonnes ont été omis).
Band
id | name |
1 | De La Soul |
2 | Foo Fighters |
3 | Cut Copy |
Listing
id | title |
1 | T-shirt Cut Copy |
2 | Affiche tournée De La Soul |
3 | Affiche du single des Foo Fighters |
Si chacune de nos annonces, en un sens, « appartient » à l'un des groupes, nous pouvons ajouter une colonne à la table des annonces et y indiquer à quel groupe cette annonce appartient, ou plutôt, nous indiquons l'identifiant du groupe auquel elle appartient, comme ceci :
Listing
id | title | band_id |
1 | T-shirt Cut Copy | 3 |
2 | Affiche tournée De La Soul | 1 |
3 | Affiche du single des Foo Fighters | 2 |
Cette nouvelle colonne que nous avons ajoutée, band_id
, est connue comme une clé étrangère, car elle contient l'identifiant (ou la « clé ») d'une autre table.
Cela suggère que nous devons ajouter un nouveau champ au modèle Listing, pour agir comme un lien vers le modèle Band
, et il y a un type spécial de champ pour cela, appelé ForeignKey
.
Ajoutons maintenant une clé étrangère au modèle Listing
.
class Listing(models.Model):
...
band = models.ForeignKey(Band, null=True, on_delete=models.SET_NULL)
Nous nommons le champ band
. Cela signifie que nous pouvons obtenir le groupe de n'importe quelle annonce en appelant listing.band
, ce qui sera très pratique plus tard.
Nous passons également trois arguments à ForeignKey
:
le modèle auquel on veut se rattacher :
Band
;null=True
: parce que nous voulons permettre la création d’annonces même si elles ne sont pas directement liées à un groupe ;on_delete=models.SET_NULL
: c'est ici que nous décidons de la stratégie à suivre lorsque les objetsBand
sont supprimés. Il existe de multiples options pour cela, comme par exemple :définir le champ
band
comme nul en utilisantmodels.SET_NULL
,définir le champ
band
à sa valeur par défaut en utilisantmodels.SET_DEFAULT
,supprimer l'objet
Listing
en utilisantmodels.CASCADE
,et d'autres paramètres plus complexes que vous pouvez trouver décrits dans la documentation de Django.
Nous ne voulons pas supprimer l'objet Listing
si un Band
est supprimé, nous utiliserons donc SET_NULL
.
Ensuite, nous devons nous assurer que les modifications de notre modèle sont reflétées dans la base de données. Générons donc une migration avec python manage.py makemigrations
et exécutons ensuite cette migration avec python manage.py migrate
.
Manipulez les clés étrangères dans l'administration de Django
Démarrez le serveur de développement et regardez la vue Create pour l'objet Listing
.
Nous avons maintenant une liste déroulante dans laquelle nous pouvons choisir un groupe auquel associer cette liste. La valeur de la liste déroulante est donnée par la représentation en chaîne de l'objet Band
.
Définissons le champ band
de cette liste à De La Soul
. Voyons ensuite ce qu'il en est dans la vue en liste.
Est-il possible de voir les groupes liés pour chacune de ces annonces également ?
Faisons cela en ajoutant le champ band
au ListingAdmin
dans admin.py.
class ListingAdmin(admin.ModelAdmin):
list_display = ('title', 'band') # ajouter ‘band' ici
Regardons à nouveau.
Joli ! Ce que nous voyons dans la colonne Band
est dicté par la représentation en chaîne de l'objet Band
, que nous avons configuré plus tôt avec la méthode __str__
.
Rafraîchissez vos nouvelles compétences en suivant les étapes du screencast.
En résumé
Nous pouvons créer des relations one-to-many en utilisant le champ
ForeignKey
.Nous contrôlons la stratégie de ce qui se passe lorsqu'un modèle lié est supprimé, en utilisant l'argument
on_delete
.Les relations one-to-many peuvent être gérées dans l'administration de Django.
Maintenant que vous pouvez relier différents modèles à l'aide de clés étrangères, il est temps d'examiner comment faire marche arrière et fusionner des migrations.