I am not very familiar with Django's signals and could use some help.
How do I modified the pk_set before the instance is saved? Do I have to return something to the signal caller (like the kwargs
)? Or do I save the instance
myself?
As a simplified example: I wanted to ensure the Category with pk=1
is included with all my Videos when they are saved. How would I do that with m2m_changed
?
class Video(models.Model):
category = models.ManyToManyField('Category')
def video_category_changed(sender, **kwargs):
action = kwargs.pop('action', None)
pk_set = kwargs.pop('pk_set', None)
instance = kwargs.pop('instance', None)
if action == "pre_add":
if 1 not in pk_set:
pk_set.update( [ 1 ] ) # adding this to the set
# do something else?
# profit?
m2m_changed.connect( video_category_changed, sender=Video.category.through )
Just updating the pk_set
is sufficient. You don't need to do any extra work. Once the video instance is saved, it will have a category with pk=1.
from django.db import models
from django.db.models.signals import m2m_changed
from django.dispatch import receiver
class Category(models.Model):
pass
class Video(models.Model):
category = models.ManyToManyField('Category')
@receiver(m2m_changed, sender=Video.category.through)
def video_category_changed(sender, **kwargs):
action = kwargs.pop('action', None)
pk_set = kwargs.pop('pk_set', None)
if action == "pre_add":
if 1 not in pk_set:
pk_set.update([1])
In the above method, the categories will be saved only after the video instance is saved. If you want to EXPLICITLY save them in the m2m_changed
instance, you can also do that as follows.
@receiver(m2m_changed, sender=Video.category.through)
def video_category_changed(sender, **kwargs):
instance = kwargs.pop('instance', None)
pk_set = kwargs.pop('pk_set', None)
action = kwargs.pop('action', None)
if action == "pre_add":
if 1 not in pk_set:
c = Category.objects.get(pk=1)
instance.category.add(c)
instance.save()