Je pense qu'il n'y a pas de moyen facile de le faire. Comme l'indique le Django doc, vous ne pouvez pas associer un élément à une relation tant qu'elle n'a pas été enregistrée. Exemple de la doc:
>>> a1 = Article(headline='...')
>>> a1.publications.add(p1)
Traceback (most recent call last):
...
ValueError: 'Article' instance needs to have a primary key value before a many-to-many relationship can be used.
# should save Article first
>>> a1.save()
# the below statement never know it's just following a creation or not
>>> a1.publications.add(p1)
Il est logiquement impossible pour un enregistrement de relation de savoir s'il est ajouté à « un élément vient de créer » ou « un élément qui existe déjà depuis un certain temps », sans information externe.
Quelques solutions de contournement Je suis arrivé avec:
Solution 1. ajouter un DateTimeField dans MyModel
pour indiquer le temps de création. Le gestionnaire m2m_changed utilise l'heure de création pour vérifier quand l'élément est créé. Cela fonctionne pratiquement dans certains cas, mais ne peut garantir l'exactitude
Solution 2. ajouter un attribut 'created' dans MyModel
, soit dans un gestionnaire post_save ou dans d'autres codes. Exemple:
@receiver(post_save, sender=Pizza)
def pizza_listener(sender, instance, created, **kwargs):
instance.created = created
@receiver(m2m_changed, sender=Pizza.toppings.through)
def topping_listener(sender, instance, action, **kwargs):
if action != 'post_add':
# as example, only handle post_add action here
return
if getattr(instance, 'created', False):
print 'toppings added to freshly created Pizza'
else:
print 'toppings added to modified Pizza'
instance.created = False
Démo:
p1 = Pizza.objects.create(name='Pizza1')
p1.toppings.add(Topping.objects.create())
>>> toppings added to freshly created Pizza
p1.toppings.add(Topping.objects.create())
>>> toppings added to modified Pizza
p2 = Pizza.objects.create(name='Pizza2')
p2.name = 'Pizza2-1'
p2.save()
p2.toppings.add(Topping.objects.create())
>>> toppings added to modified Pizza
Mais soyez prudent en utilisant cette solution. Depuis l'attribut « créé » a été attribué à l'instance Python, pas enregistré dans le DB, les choses peuvent mal tourner comme:
p3 = Pizza.objects.create(name='Pizza3')
p3_1 = Pizza.objects.get(name='Pizza3')
p3_1.toppings.add(Topping.objects.create())
>>> toppings added to modified Pizza
p3.toppings.add(Topping.objects.create())
>>> toppings added to freshly created Pizza
C'est tout au sujet de la réponse. Ensuite, vous a attrapé ici! Je suis zhang-z du groupe github django-notifications :)
Hé mec, c'est à peu près ce que j'ai dû faire, donc je l'ai marqué correctement. J'ajouterai une réponse séparée à ce que j'ai réellement fait. –