当 m2m_changed 调用“pre_clear”时如何访问 pk_set?

Posted

技术标签:

【中文标题】当 m2m_changed 调用“pre_clear”时如何访问 pk_set?【英文标题】:how to access pk_set when m2m_changed call with action "pre_clear"? 【发布时间】:2016-02-28 05:43:06 【问题描述】:

我想在删除 ManyToMany 字段中的 realtion 时使用m2m_changed 信号。我把这段代码写在models.py:

class Unit(Model):
    # ....

class Package(Model):
    # ...
    Lesson = ManyToManyField(Unit, blank=True)

def toppings_changed(sender, **kwargs):
    if kwargs.get("pk_set") and kwargs.get("action") == "pre_clear":
        # get id of lesson to delete and do something with it
m2m_changed.connect(toppings_changed, sender=Packages.Lesson.through)

在删除Package 模型中的Lesson 关系时,我想做一些事情。但是当我删除关系时pre_clear 将调用并且我无法访问pk_set(它是无)。删除课程模型中的关系时有没有办法访问Unit id。

【问题讨论】:

【参考方案1】:

根据文档:

pk_set ... 对于 pre_clear 和 post_clear 操作,这是 None。https://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed

【讨论】:

【参考方案2】:
    首先:m2m_changed多对多 关系的两侧的任何 发生变化时被调用。即some_unit.package_set.clear()some_package.Lesson.clear()可以触发注册信号。 第二:在pre_clear 状态下,所有关系仍然存在(因为它实际上是pre-clear)。所以你可以像这样看到要删除的内容:
def toppings_changed(sender, reverse, action, **kwargs):
    if action == "pre_clear":
        if reverse:
            # sender is of type Unit
            # i.e. current signal is raised by: some_unit.package_set.clear()
            packages_to_be_removed = sender.package_set.all()
        else:
            # sender is of type Package
            # i.e. current signal is raised by: some_package.Lesson.clear()
            lessons_to_be_removed = sender.Lesson.all()

【讨论】:

我有一段时间对大写的Lesson 感到困惑。它确实是Package 类上的一个字段。 @dhill 你是对的。这不是一个合适的命名。但我只是试图与有问题的例子保持一致。

以上是关于当 m2m_changed 调用“pre_clear”时如何访问 pk_set?的主要内容,如果未能解决你的问题,请参考以下文章

删除关系时,Django Python m2m_change 不起作用

如何在 Django 中使 m2m_changed 信号原子化?

Django:删除关系结束时未触发 m2m_changed

GenericRelation 的 Django m2m_changed 信号,有可能吗?

使用 Django 的 m2m_changed 修改正在保存的内容 pre_add

django的内置信号