Django:在迁移过程中禁用信号

问题描述 投票:0回答:4

我正在 Django 中编写一个小型审核日志应用程序,它挂钩各种信号并将事件写入数据库。不幸的是,其中一些事件在相应的表存在之前就已经被触发,从而导致各种麻烦。

为了避免这种情况,我尝试添加一些触发器以在

migration
/
syncdb
期间暂时禁用日志记录 - 像这样:

from django.db.models.signals import pre_save, post_save, pre_delete
from django.db.models.signals import pre_syncdb, post_syncdb
from south.signals            import pre_migrate, post_migrate

IS_MIGRATING = False

@receiver(post_save)
def log_model_update(sender, **kwargs):
    if IS_MIGRATING:
        return
    ...

@receiver(pre_syncdb)
@receiver(pre_migrate)
def _disable_auditlog(sender, **kwargs):
    global IS_MIGRATING
    IS_MIGRATING = True

不幸的是,这并没有按预期工作。我缺少什么?或者有“官方”方法可以做到这一点吗?

django django-south
4个回答
1
投票

在 Django 中,可以断开信号。因此,您可以尝试在导致问题的迁移代码之前断开某个位置的信号

必须澄清,我还没有尝试过,所以不完全确定它是否有效,但我希望它能以某种方式有所帮助


1
投票

我现在通过做一个丑陋的黑客并检查

sys.argv
并在
test
syncdb
migrate
期间禁用事件处理程序解决了这个问题。这显然不是一个好的解决方案,但是如问题所示禁用事件处理程序是不够的,并且会导致对其他几乎不可追踪的 django 应用程序的干扰。

测试时需要禁用它,因为 Django/South 显然会在测试过程中迁移数据库。涉及事件处理程序的测试需要显式激活事件处理。


0
投票

您可以使用:

#run inside signal function
if sender._meta.object_name != 'Migrate':
  #signal logic

或者,您可以创建信号运行的模型列表,这更好,因为这样您就可以准确地知道信号何时运行:

ALLOWED_MODELS = [
   'model_1',
   'model_2',
]

#run inside signal function
if sender.meta.object_name in ALLOWED_MODELS:
   #signal logic

为了避免创建列表,您可以将其基于任何具有字段的模型:

#run inside signal function
if "field name" in [field.name for field in sender._meta.get_fields()]:
   #signal logic

如果您想知道哪个对象触发了您的信号,请将其放入您的信号中:

print(sender._meta.object_name)

0
投票

在 Django 中,您可以使用

QuerySet.update()
绕过所有信号。


请记住,如果您有一个 QuerySet,则调用

update(arg1=value1, arg2=value2)
将会在所有 QuerySet 项的 arg1
arg2
字段中写入
相同的值

所以如果需要给每个对象设置不同的值,可以用这个来一一更新:

def update_and_skip_signals(my_obj: MyModel, **kwargs):
    # NOTE: do no use get() here, it will return a single instance 
    #       and we want a QuerySet instead
    qs = MyModel.objects.filter(pk=my_obj.pk)
    qs.update(**kwargs)

for item in my_queryset.all():
    update_and_skip_signals(item, arg1=value1, arg2=value2)
© www.soinside.com 2019 - 2024. All rights reserved.