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 Reporter(models.Model):
# ...
pass
class Article(models.Model):
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
Dans l’exemple ci-dessus, les méthodes ci-dessous seront disponibles pour le gestionnaire reporter.article_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_set
et pour pizza.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=False
pour que la mise à jour soit effectuée plutôt par le gestionnaire de la relation en appelant e.save()
.
Cependant, l’emploi de add()
avec une relation plusieurs-à-plusieurs n’appelle aucune méthode save()
(le paramètre bulk
n’existe pas), mais crée plutôt les relations en utilisant QuerySet.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 signal m2m_changed
, qui va déclencher les actions pre_add
et post_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.
add()
accepte également comme paramètre le champ vers lequel pointe la relation. L’exemple ci-dessus peut être réécrit comme b.entry_set.add(234)
.
Utilise le paramètre through_defaults
pour définir les valeurs des nouvelles instances du modèle intermédiaire, si nécessaire.
Le paramètre through_defaults
a été ajouté.
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 beaucoup 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 champ blog
du nouvel objet Entry
doit recevoir la valeur b
.
Utilise le paramètre through_defaults
pour définir les valeurs de la nouvelle instance du modèle intermédiaire, si nécessaire.
Le paramètre through_defaults
a été ajouté.
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 appelle e.save()
dans l’exemple ci-dessus pour effectuer la mise à jour. Cependant, l’emploi de remove()
avec une relation plusieurs-à-plusieurs supprime les relations avec QuerySet.delete()
, ce qui signifie qu’aucune méthode save()
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 signal m2m_changed
.
Comme pour add()
, remove()
accepte également comme paramètre le champ vers lequel pointe la relation. L’exemple ci-dessus peut être réécrit comme b.entry_set.remove(234)
.
Pour les objets ForeignKey
, cette méthode existe seulement quand null=True
. Si le champ lié ne peut pas recevoir la valeur None
(NULL
), alors un objet ne peut pas être enlevé d’une relation sans être ajouté à une autre. Dans l’exemple ci-dessus, enlever e
de b.entry_set()
est l’équivalent de la définition e.blog = None
, et comme la clé ForeignKey
blog
n’a pas l’option null=True
, ce n’est pas valide.
Pour les objets ForeignKey
, cette méthode accepte un paramètre bulk
pour contrôler comment effectuer l’opération. Avec True
(valeur par défaut), c’est QuerySet.update()
qui est utilisé. Avec bulk=False
, c’est plutôt la méthode save()
de chaque instance de modèle individuelle qui est appelée. Cela déclenche les signaux pre_save
et post_save
au détriment d’une perte de performance.
Pour les relations plusieurs-à-plusieurs, le paramètre nommé bulk
n’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 champ ForeignKey
que lorsque null=True
et il accepte également le paramètre nommé bulk
.
Pour les relations plusieurs-à-plusieurs, le paramètre nommé bulk
n’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 clear
pour contrôler le fonctionnement de l’opération. Si False
(par défaut), les éléments manquants dans le nouvel ensemble sont supprimés avec remove()
et seuls les nouveaux sont ajoutés. Si clear=True
, la méthode clear()
est appelée à la place et l’ensemble est ajouté en une seule fois.
Pour les objets ForeignKey
, le paramètre bulk
est transmis à add()
et à remove()
.
Pour les relations plusieurs-à-plusieurs, le paramètre nommé bulk
n’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’appel clear()
et l’appel add()
.
Comme pour add()
, set()
accepte également comme paramètre le champ vers lequel pointe la relation. L’exemple ci-dessus peut être réécrit comme e.related_set.set([obj1.pk, obj2.pk, obj3.pk])
.
Utilise le paramètre through_defaults
pour définir les valeurs des nouvelles instances du modèle intermédiaire, si nécessaire.
Le paramètre through_defaults
a été ajouté.
Note
Notez que add()
, create()
, remove()
, clear()
et set()
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’appeler save()
ni d’un côté de la relation, ni de l’autre.
Si vous utilisez prefetch_related()
, les méthodes add()
, remove()
, clear()
et set()
effacent le cache de préchargement.
_meta
des modèles
Hors ligne (Django 2.2) :
HTML |
PDF |
ePub
Offert par Read the Docs.
© 2005-2024 Django Software Foundation and individual contributors. Django is a registered trademark of the Django Software Foundation.