Référence des objets liés¶
-
class
RelatedManager¶ Un gestionnaire de liaison (« related manager ») est un gestionnaire utilisé dans un contexte de champ lié un-à-plusieurs ou plusieurs-à-plusieurs. Cela se produit dans deux cas :
Le « côté opposé » d’une relation
ForeignKey. C’est-à-dire :from django.db import models class Blog(models.Model): # ... pass class Entry(models.Model): blog = models.ForeignKey(Blog, on_delete=models.CASCADE, null=True)
Dans l’exemple ci-dessus, les méthodes ci-dessous seront disponibles pour le gestionnaire
blog.entry_set.Les deux côtés d’une relation
ManyToManyField:class Topping(models.Model): # ... pass class Pizza(models.Model): toppings = models.ManyToManyField(Topping)
Dans cet exemple, les méthodes ci-dessous seront disponibles à la fois pour
topping.pizza_setet pourpizza.toppings.
-
add(*objs, bulk=True, through_defaults=None)¶ Ajoute les objets modèles indiqués à l’ensemble des objets liés.
Exemple :
>>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) >>> b.entry_set.add(e) # Associates Entry e with Blog b.
Dans l’exemple ci-dessus, dans le cas d’une relation
ForeignKey,QuerySet.update()est utilisée pour effectuer la mise à jour. Ceci nécessite que les objets soient déjà enregistrés.Vous pouvez utiliser le paramètre
bulk=Falsepour que la mise à jour soit effectuée plutôt par le gestionnaire de la relation en appelante.save().Cependant, l’emploi de
add()avec une relation plusieurs-à-plusieurs n’appelle aucune méthodesave()(le paramètrebulkn’existe pas), mais crée plutôt les relations en utilisantQuerySet.bulk_create(). Si vous avez besoin de faire exécuter une certaine logique personnalisée lors de la création d’une relation, faites-le dans une fonction à l’écoute du signalm2m_changed, qui va déclencher les actionspre_addetpost_add.L’utilisation de
add()sur une relation qui existe déjà ne va pas dupliquer la relation, mais cela va tout de même déclencher les signaux.Pour les relations plusieurs-à-plusieurs,
add()accepte dans le paramètre*objssoit des instances de modèles, soit des valeurs de champs, en principe des clés primaires.Utilisez le paramètre
through_defaultspour définir les valeurs des nouvelles instances du modèle intermédiaire, si nécessaire. Vous pouvez utiliser des valeurs exécutables dans le dictionnairethrough_defaults, elles seront évaluées une fois avant la création d’instances intermédiaires.Changed in Django 3.1:Les valeurs
through_defaultspeuvent dorénavant être des objets exécutables.
-
create(through_defaults=None, **kwargs)¶ Crée un nouvel objet, l’enregistre et le place dans l’ensemble des objets liés. Renvoie l’objet nouvellement créé :
>>> b = Blog.objects.get(id=1) >>> e = b.entry_set.create( ... headline='Hello', ... body_text='Hi', ... pub_date=datetime.date(2005, 1, 1) ... ) # No need to call e.save() at this point -- it's already been saved.
C’est équivalent à (mais plus simple) :
>>> b = Blog.objects.get(id=1) >>> e = Entry( ... blog=b, ... headline='Hello', ... body_text='Hi', ... pub_date=datetime.date(2005, 1, 1) ... ) >>> e.save(force_insert=True)
Notez qu’il n’y a pas besoin de fournir le paramètre nommé du modèle qui définit la relation. Dans l’exemple ci-dessus, nous ne transmettons pas le paramètre
blogàcreate(). Django réalise lui-même que le champblogdu nouvel objetEntrydoit recevoir la valeurb.Utilisez le paramètre
through_defaultspour définir les valeurs des nouvelles instances du modèle intermédiaire, si nécessaire. Vous pouvez utiliser des valeurs exécutables dans le dictionnairethrough_defaults.Changed in Django 3.1:Les valeurs
through_defaultspeuvent dorénavant être des objets exécutables.
-
remove(*objs, bulk=True)¶ Enlève les objets modèles indiqués de l’ensemble des objets liés :
>>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) >>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.
Comme avec
add(), on appellee.save()dans l’exemple ci-dessus pour effectuer la mise à jour. Cependant, l’emploi deremove()avec une relation plusieurs-à-plusieurs supprime les relations avecQuerySet.delete(), ce qui signifie qu’aucune méthodesave()n’est appelée. Si vous avez besoin de faire exécuter du code personnalisé lors de la suppression d’une relation, faites-le dans une fonction à l’écoute du signalm2m_changed.Pour les relations plusieurs-à-plusieurs,
remove()accepte dans le paramètre*objssoit des instances de modèles, soit des valeurs de champs, en principe des clés primaires.Pour les objets
ForeignKey, cette méthode existe seulement quandnull=True. Si le champ lié ne peut pas recevoir la valeurNone(NULL), alors un objet ne peut pas être enlevé d’une relation sans être ajouté à une autre. Dans l’exemple ci-dessus, enleveredeb.entry_set()est l’équivalent de la définitione.blog = None, et comme la cléForeignKeyblogn’a pas l’optionnull=True, ce n’est pas valide.Pour les objets
ForeignKey, cette méthode accepte un paramètrebulkpour contrôler comment effectuer l’opération. AvecTrue(valeur par défaut), c’estQuerySet.update()qui est utilisé. Avecbulk=False, c’est plutôt la méthodesave()de chaque instance de modèle individuelle qui est appelée. Cela déclenche les signauxpre_saveetpost_saveau détriment d’une perte de performance.Pour les relations plusieurs-à-plusieurs, le paramètre nommé
bulkn’existe pas.
-
clear(bulk=True)¶ Enlève tous les objets de l’ensemble des objets liés :
>>> b = Blog.objects.get(id=1) >>> b.entry_set.clear()
Notez que cela ne supprime pas les objets liés, il ne fait que les dissocier.
Tout comme
remove(),clear()n’est disponible pour un champForeignKeyque lorsquenull=Trueet il accepte également le paramètre nommébulk.Pour les relations plusieurs-à-plusieurs, le paramètre nommé
bulkn’existe pas.
-
set(objs, bulk=True, clear=False, through_defaults=None)¶ Remplace l’ensemble des objets liés :
>>> new_list = [obj1, obj2, obj3] >>> e.related_set.set(new_list)
Cette méthode accepte un paramètre
clearpour contrôler le fonctionnement de l’opération. SiFalse(par défaut), les éléments manquants dans le nouvel ensemble sont supprimés avecremove()et seuls les nouveaux sont ajoutés. Siclear=True, la méthodeclear()est appelée à la place et l’ensemble est ajouté en une seule fois.Pour les objets
ForeignKey, le paramètrebulkest transmis àadd()et àremove().Pour les relations plusieurs-à-plusieurs, le paramètre nommé
bulkn’existe pas.Notez que dans la mesure où
set()est une opération composée, elle est sujette aux situations de concurrence. Par exemple, de nouveaux objets pourraient être ajoutés à la base de données entre l’appelclear()et l’appeladd().Pour les relations plusieurs-à-plusieurs,
set()accepte dans le paramètreobjssoit une liste d’instances de modèles, soit une liste de valeurs de champs, en principe des clés primaires.Utilisez le paramètre
through_defaultspour définir les valeurs des nouvelles instances du modèle intermédiaire, si nécessaire. Vous pouvez utiliser des valeurs exécutables dans le dictionnairethrough_defaults, elles seront évaluées une fois avant la création d’instances intermédiaires.Changed in Django 3.1:Les valeurs
through_defaultspeuvent dorénavant être des objets exécutables.
Note
Notez que
add(),create(),remove(),clear()etset()appliquent tous immédiatement les modifications de base de données pour tous les types de champs de relation. En d’autres termes, il n’est pas nécessaire d’appelersave()ni d’un côté de la relation, ni de l’autre.Si vous utilisez
prefetch_related(), les méthodesadd(),remove(),clear()etset()effacent le cache de préchargement.