关于Django信号管理的更好方法

2024-06-17 13:45:43 发布

您现在位置:Python中文网/ 问答频道 /正文

嗯,我有一个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的“last\u update”字段。理想情况下,当发生以下任何情况时,“last\u update”的值将更新为当前时间戳:

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

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

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

一般的方法是重写每个模型的.save(),或者将信号挂接到每个模型的预保存。你知道吗

不过,我想要更干净的东西。理想情况下,我只需要一种方法,它将接收不同的信号,并以相同的方式作出反应-更新模型A的“last\u update”字段

提前谢谢。你知道吗

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


Tags: 项目django方法用户模型信号models情况
1条回答
网友
1楼 · 发布于 2024-06-17 13:45:43

如果这是你的应用程序的核心,你可能想创建一个通用的信号接收器,听所有模型保存。如果仍然有很多模型没有直接连接到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

通过构造queryset并使用update方法,可以防止在保存单个实例时多次触发信号。你知道吗

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

相关问题 更多 >