Beaucoup à beaucoup
ManyToMany (to, through), avec les paramètres obligatoires to et optionnel through, prend à la fois les classes de modèle objectif et relationnel.
Les colonnes et types Sqlalchemy sont automatiquement extraits du modèle cible.
- Colonne Sqlalchemy: Classe de la colonne de clé primaire du modèle cible
- Type (pour pydantic): type du modèle cible
Définir le modèle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | |
Créer des données d'échantillon:
1 2 3 | |
Relation inverse
Le champ de clé étrangère enregistre automatiquement le verso de la relation.
Par défaut, il s'agit du nom du modèle enfant (source)+ s, comme dans le post du fragment de code suivant:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
Une relation inverse expose une API pour gérer les objets associés depuis le parent.
Les noms associés
Par défaut, les noms associés sont générés de la même manière que les relations de clé étrangère (classe.name.lower()+'s'), mais vous pouvez également remplacer ce nom en fournissant un argument de nom associé, comme suit:
1 2 3 | |
!!!avertit que lorsque vous fournissez plusieurs relations au même modèle, sinon vous ne pourrez plus générer automatiquement le nom related_name. dans ce cas, vous devez donc fournir le nom related_name pour tous les champs sauf un (qui peut être par défaut et généré) ou pour tous les champs associés.
Sauter les relations inverses
Si vous êtes sûr de ne pas vouloir une relation inverse, vous pouvez utiliser le drapeau skip_reverse=True de ManyToMany.
Si vous définissez l'attribut skip_reverse en interne, le champ est toujours enregistré à l'autre bout de la relation, vous pouvez donc:
- Filtrer par champ de modèle pertinent dans le modèle inverse
- order_by Champ de modèle pertinent dans le modèle inverse
Mais vous ne pouvez:
- Utiliser related_name pour accéder aux champs pertinents à partir du modèle inverse
- Même si vous sélectionnez une relation du côté opposé du modèle, le modèle retourné ne sera pas rempli dans l'instance inverse (les connexions ne seront pas bloquées, vous pouvez donc toujours filtrer et trier les relations).
- La relation n'est pas remplie dans modèle_dump() et json(). Lorsque* est rempli à partir d'un dictionnaire ou d'un fichier json (également via fastapi), vous ne pouvez pas passer les objets liés imbriqués. il sera ignoré ou une erreur sera générée en fonction des paramètres supplémentaires dans la configuration pydantique.
Exemples:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
par Model
Alternativement, si vous souhaitez ajouter des champs supplémentaires, vous pouvez créer et passer explicitement une classe de modèle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
!!!Attention, même si vous ne le fournissez pas via un modèle, il est automatiquement créé pour vous et doit tout de même être inclus dans l'exemple de migration alembic.
!!!Note: Si vous souhaitez personnaliser le nom du modèle Through ou le nom de la table de base de données pour ce modèle, vous devez fournir le modèle Through.
Si vous ne fournissez pas le champ « Passer », le système le générera pour vous.
La convention de nommage par défaut est:
- Pour un nom de classe, il s'agit d'une union de deux noms de classe (parent + autre), donc dans l'exemple ci-dessus, ce serait PostCategory.
- Pour les noms de table, c'est similaire, mais avec un trait inférieur et s à la fin du nom minuscule de la classe, ce qui serait posts_categorys dans l'exemple ci-dessus.
Personnalisation par nom de relation
Par défaut, le nom du modèle associé est par défaut en minuscules via le nom de la relation de modèle.
Dans un exemple comme celui-ci:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Pour personnaliser les noms des champs/relations dans le modèle Through, vous pouvez maintenant utiliser les nouveaux paramètres de ManyToMany:
- through_relation_name -nom du champ menant au modèle dans lequel ManyToMany est déclaré
- through_reverse_relation_name -Nom du champ menant au modèle auquel ManyToMany mène
Exemples:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
!!!Remarque Notez que la déclaration explicite de relations dans le modèle Through est interdite, donc même si vous fournissez votre propre modèle Through personnalisé, vous ne pouvez pas changer le nom et vous devez utiliser les mêmes arguments through_relation_name et through_reverse_relation_name.
A travers les champs
Les champs de passage sont automatiquement ajoutés au verso de la relation.
Les champs exposés sont nommés en minuscules par le nom de la classe.
Le champ exposé ne charge explicitement aucune relation, car la relation est déjà remplie dans le champ ManyToMany, elle n'est donc utile que si d'autres champs sont fournis sur le modèle Through.
Dans un exemple de configuration de modèle, cela ressemblerait à ceci:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
Le champ through peut être utilisé comme champ de modèle normal dans la plupart des opérations QuerySet.
Notez que les champs de passage ne sont attachés qu'à l'extrémité pertinente de la requête, donc:
1 2 3 4 5 6 7 8 9 10 | |
Le champ Via peut être utilisé pour filtrer les données.
1 2 3 4 5 | |
!!!tip Notez que même si l'instance réelle n'est pas remplie dans le modèle source, vous pouvez accéder à travers le modèle des deux côtés dans les requêtes, les instructions order by, etc. Donc la requête suivante a exactement le même effet (notez l'accès par catégorie)
1 2 3 4 5 6 7 | |
Les requêtes peuvent être utilisées de manière séquentielle via le modèle
1 2 3 4 5 | |
Vous pouvez également utiliser fields et except_fields pour sélectionner un sous-ensemble de colonnes de la manière habituelle QuerySet.
1 2 3 4 5 | |
Attention: comme through fields invalide explicitement tous les champs relationnels, car les relations sont remplies dans le champ ManyToMany, les méthodes standard du modèle telles que save() et update() ne doivent pas être utilisées tant que les champs n'ont pas été rechargés à partir de la base de données.
Si vous souhaitez modifier le champ de passage sur place, n'oubliez pas de le recharger à partir de la base de données…Sinon, vous définissez la relation sur « Aucun », ce qui rend le champ inutile!
1 2 3 4 | |
Notez que le rechargement du modèle recharge effectivement les relations en tant que modèles pk_only (définissant uniquement la clé primaire), de sorte qu 'elles ne sont pas complètement remplies, mais suffisantes pour préserver les relations lorsqu' elles sont mises à jour.
!!!avertit que si vous utilisez ie fastapi, les modèles associés chargés par la partie champ peuvent provoquer une erreur de validation pydantique (ce qui est la principale raison pour laquelle ils ne sont pas remplis par défaut). vous devez donc soit exclure les champs associés de la réponse, soit charger complètement les modèles associés. dans l'exemple ci-dessus, cela signifie:python await post2.categories[0].postcategory.post.load() await post2.categories[0].postcategory.category.load() ou, vous pouvez utiliser load_all():python await post2.categories[0].postcategory.load_all()
La méthode de mise à jour préférée est via la méthode queryset proxy update().
1 2 | |
La loi relationnelle
Ajouter à
Ajouter (projet: modèle,**kwargs)
Permet d'ajouter des modèles à une relation plusieurs-à-plusieurs.
1 2 3 4 | |
!!!Dans tous les cas non None, la valeur de clé primaire du modèle associé doit exister dans la base de données.
1 | |
Si vous déclarez un modèle à l'aide d'un modèle Through avec des champs supplémentaires, vous pouvez les remplir lors de l'ajout de sous-modèles à la relation.
Pour ce faire, passez un argument de mot-clé avec le nom et la valeur du champ à l'appel add().
Notez que cela ne s'applique qu 'aux relations plusieurs-à-plusieurs.
1 2 3 4 | |
Éliminer
Les modèles pertinents sont supprimés un par un.
Supprime également les relations dans la base de données.
1 | |
Clear à
Un seul appel supprime tous les modèles associés.
Supprime également les relations dans la base de données.
En attendant news.posts.clear()
Query Set Agent pour
La relation inverse expose l'API QuerysetProxy, qui vous permet d'interroger les modèles pertinents comme vous le feriez pour une requête normale.
Pour savoir quelles méthodes QuerySet sont disponibles, lisez Querysetproxy ci-dessous.