保存模型和相关 m2m(组)字段后如何触发操作?

tom*_*eit 5 python django m2m

如何在 Django 用户模型保存后执行某些操作,包括对 m2m 字段的相关更改,例如django.contrib.auth.models.Group

\n\n

情况

\n\n

我有一个自定义 Django 用户模型,并且希望在用户实例(包含 m2m 组成员身份等相关更改)成功保存到数据库后触发一些操作。\n这里的用例是 Wagtail CMS,我在其中ProfilePage为每个用户实例创建 s。根据用户实例的组成员身份,我需要做一些事情。

\n\n

问题

\n\n

在自定义模型save()方法中,我无法引用更改后的组成员身份,因为 m2m 是在保存用户实例后保存的。即使在调用后运行我的自定义函数super().save(),新的组成员资格仍不可用。\n但我需要获取新的组成员身份,以便根据该用户的新组执行某些操作。

\n\n

我尝试过的

\n\n

[\xe2\x9c\x98] 自定义模型save()

\n\n
# file: users/models.py\nclass CustomUser(AbstractUser):\n    super().save(*args, **kwargs)\n    do_something()\n
Run Code Online (Sandbox Code Playgroud)\n\n

[\xe2\x9c\x98] 信号 post_save

\n\n

由于上面简单的 save() 方法没有达到目的,我尝试了post_save用户模型的信号:

\n\n
# file users/signals.py\n@receiver(post_save, sender=get_user_model())\ndef handle_profilepage(sender, instance, created, **kwargs):\n    action = \'created\' if created else \'updated\'\n    do_something()\n
Run Code Online (Sandbox Code Playgroud)\n\n

...但即使在这里,我也总是从小组成员中获取“旧”价值观。

\n\n

[\xe2\x9c\x94] 信号:m2m_changed

\n\n

我了解到有一个m2m_changed信号可以用来监视表的变化Users.groups(.through)

\n\n

我的以下实现满足了我的需要:

\n\n
@receiver(m2m_changed, sender=User.groups.through)\ndef user_groups_changed_handler(sender, instance, **kwargs):\n    USER_GROUPS = instance.groups.values_list(\'name\', flat=True)\n    if set(USER_GROUPS) & set(settings.PROFILE_GROUPS):\n        do_something_because_some_groups_match()\n    else:\n        do_something_else()\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的愿望清单

\n\n

如果有机会在模型方法中解决这个问题,我很乐意远离信号save()- 但我被困住了......

\n

klo*_*ant 0

你问了黑魔法。告诉我,为了避免使用信号,您愿意牺牲什么?你会拥抱更大的邪恶吗?如果我建议您可以启动一个新线程并休眠几秒钟,直到您认为在执行任何操作之前 M2M 关系可能已保存,该怎么办?

from threading import Thread
from time import sleep

# file: users/models.py
class CustomUser(AbstractUser):
    super().save(*args, **kwargs)

    def do_something(obj):
        sleep(3)
        # stuff

    thread = Thread(target = do_something, args = [self], daemon=True)
    thread.start()
Run Code Online (Sandbox Code Playgroud)