python - Django 信号管理的更好方法

标签 python django signals

嗯,我有一个运行良好的 django 项目。

在这个项目中,我有以下模型:

class A:
    b = models.ForeignKey(B)
    c = models.ForeignKey(C)
    d = models.ForeignKey(D)
    last_update = models.DateTimeField()

class B:
    # whatever

class C:
    # whatever

class D:
    # whatever

class E:
    a = models.ForeignKey(A)

# And more models...

所以总体思路是我有模型 A,它是我的结构的核心。还有一些其他的模型,要么是模型A引用的,要么是模型A引用的。

真正的问题是模型 A 的“last_update”字段。理想情况下,当发生以下任何情况时,“last_update”的值将更新为当前时间戳:

  1. 用户修改模型A的字段值

  2. 用户添加、更改、删​​除B、C、D类

  3. 用户添加、更改、删​​除E类

一般方法是重写每个模型的 .save() 或将信号 Hook 到每个模型的 pre_save。

但是,我想要更干净的东西。理想情况下,我只需要一种方法来接收不同的信号并以相同的方式使用react - 更新模型 A 的“last_update”字段。

提前致谢。

PS:请不要提及有关数据库级别修改的解决方案(我的意思是触发器之类的东西)。我们只关注 Django。

最佳答案

如果这是您应用程序的核心,您可能需要创建一个通用信号接收器来监听所有模型保存。如果您还有很多型号没有直接连接到A模型,您可能不想这样做。

import datetime

@receiver(post_save, sender=None, dispatch_uid='update_last_modified')
def update_last_modified(sender, instance, raw, using, update_fields):
    if raw: # database might not be in a consistent state yet
        return
    if sender in (B, C, D): # all models which A has a fk/m2m to
        qs = instance.a_set.using(using)
    elif sender in (E,): # all models which have a fk/o2o to A
        qs = A.objects.filter(pk=instance.a.pk).using(using)
    elif sender is A:
        qs = A.objects.filter(pk=instance.pk).using(using)
    try:
        qs.update(last_update=datetime.datetime.now())
    except NameError:
        pass

通过构建查询集并使用 update方法,您可以在保存单个实例时防止信号多次触发。

我会挂入post_save方法而不是 pre_save方法,以便在信号触发之前保存新创建对象的 m2m 关系,并且 last_update如果在第一种情况下保存模型时发生错误,则字段不会更新。

关于python - Django 信号管理的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23022882/

相关文章:

python - 在 Python 中使异步调用同步

python - pyinstaller,导入错误: no module named pywintypes

1 个模型的 django-rest-framework 多个序列化程序?

concurrency - 如何保证多个子进程的信号传递

c - 如何使用信号安全函数将格式化字符串写入文件?

python - 根据python matplotlib中的数据集生成带有颜色渐变的网格

python - 添加输入变量以在 Python 中绘制标题/图例

python - "No installed app with label ' 管理员 '"运行 Django 迁移。该应用程序已正确安装

python - 在 Django 中,放置 HTML 格式数据的简短片段的最佳位置在哪里?

python - 为什么 SIGVTALRM 不在 time.sleep() 内部触发?