Reputation: 13145
I have the following signal:
@receiver(m2m_changed, sender=User.cars.through)
def car_added_to_user(sender, instance, action, **kwargs):
if action in ("post_add",):
cache.delete(f"user-{instance.pk}")
I can trigger it as expected when doing:
User.cars.add(car)
but if I also want to delete the user from the cache in this case, what do I do?
Car.user_set.add(user)
as in this case the instance is a Car object and not a User object.
Upvotes: 1
Views: 23
Reputation: 477533
Such signals already work bi-directional. So regardless how you add the element.
In fact this is one of the caveats of the m2m_changed
signal signal [Django-doc]: that the sender
and the instance
can be a User
and Car
, but also a Car
and User
, so making it more complicated to write the signal.
@receiver(m2m_changed, sender=User.cars.through)
def car_added_to_user(sender, instance, action, **kwargs):
if action == 'post_add':
if issubclass(sender, User):
# did through my_user.cars.add(my_car)
cache.delete(f"user-{instance.pk}")
# my_user is the instance
elif issubclass(sender, Car):
# did through my_car.user_set.add(my_user)
# my_car is the instance
pass
The kwargs
will have two additional parameters that are interesting here:
reverse
: which is True
if you did the add/remove/change by using the related manager, so in this case my_car.user_set.add(my_user)
; andpk_set
: which is a set of the primary keys added/removed, so in case of my_user.cars.add(my_car)
, a set with one element: the primary key of my_car
, and in case of my_car.user_set.add(my_user)
, a set with one element: the primary key of my_user
.Note: Signals are often not a robust mechanism. I wrote an article [Django-antipatterns] that discusses certain problems when using signals. Therefore you should use them only as a last resort.
Upvotes: 0