最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

django - m2m_changed instance when in reverse - Stack Overflow

programmeradmin1浏览0评论

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.

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.

Share Improve this question edited Jan 19 at 19:36 willeM_ Van Onsem 477k33 gold badges472 silver badges609 bronze badges asked Jan 19 at 19:07 BazBaz 13.1k40 gold badges151 silver badges279 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

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); and
  • pk_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.

发布评论

评论列表(0)

  1. 暂无评论