【问题标题】:Django pre_delete signal gets ignoredDjango pre_delete 信号被忽略
【发布时间】:2016-01-22 13:41:50
【问题描述】:

这是在模型文档的 pre_delete 上运行的内容。当按照建议的最佳实践放入单独的文件 (signals.py) 时,此代码会被完全忽略。放入模型文件后,效果很好。

from django.db.models.signals import pre_delete, pre_save
from django.dispatch import receiver
from _myTools.functions import ImageProcessing
from content_image.models import Document
import os

# Image deletion when deleting entire entry
@receiver(pre_delete, sender=Document, dispatch_uid='document_delete_signal')
def entry_deletion_images_delete(sender, instance, using, **kwargs):
    for key, value in instance.imageSizes.items():
        name_of_image_field = str(getattr(instance, key))  # Converts to string, if not is object itself
        os.remove(instance.baseDir + name_of_image_field)
        setattr(instance, key, None)

那么问题是什么?我应该在那里进口更多的东西吗?或者我应该在某个地方导入这个文件?

【问题讨论】:

    标签: python django django-signals


    【解决方案1】:

    问题在于,如果您将其放入signals.py(按照建议)但什么也不做,那么没有人会导入该文件。

    你应该关注this advice,尤其是

    实际上,信号处理程序通常定义在与其相关的应用程序的信号子模块中。信号接收器连接在应用程序配置类的 ready() 方法中。如果您使用的是 receiver() 装饰器,只需在 ready() 中导入信号子模块。

    ready() 负责导入模块,从而引发信号“连接”并允许信号接收器工作。


    完整的程序应该是:

    # my_app/__init__.py
    
    default_app_config = 'my_app.apps.ConfigForMyApp'
    

    apps.py 应该是:

    # my_app/apps.py
    
    from django.apps import AppConfig
    
    class ConfigForMyApp(AppConfig):
        # Optionally add `name` and `verbose_name`
        # for the app
        def ready(self): # overriding the ready method
            # This will trigger the @receiver decorator 
            # and thus connect the signals
            import my_app.signals
    

    【讨论】:

    • 谢谢它的工作。是否值得额外的复杂性?把它留在模型中有什么问题吗?
    • 取决于您计划发展多少应用程序。如果它不会增长,则将其留在models 中。如果您打算重新分发它,使用一堆迁移的东西,一些奇怪的连接,添加单元测试等,那么它可能值得这样做,因为您可能会避免一些错误并且代码会更加干净整洁。
    • 谢谢,如果我希望它是系统范围的(与特定应用程序无关),我不应该将它们放在 app 目录中,而是放在项目 apps.py 和 init ?
    【解决方案2】:

    虽然 MariusSiuram 提供的答案是 django >= 1.7 的新推荐方式,但这是另一种模式,无论 django 的版本如何:

    在您的 models.py 文件中:

    from django.db.models.signals import pre_delete
    from myapp.signals import pre_delete_signal_dispatcher
    
    pre_delete.connect(pre_delete_signal_dispatcher, sender=MyModel, dispatch_uid="delete_signal_dispatch")
    

    这样,在解析models.py文件时,信号被连接,并在pre_delete事件上触发,你可以继续增长你的signals.py文件。但是,是的,如果信号连接的数量增加,在应用程序配置中管理它们会更容易。

    【讨论】:

    • 这也希望删除 @received 装饰器,不是吗?它确实提供了更简洁的代码,尽管模型加载时信号连接的潜在问题可能仍然是一个问题。但是,+1 :)
    猜你喜欢
    • 2012-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    • 1970-01-01
    相关资源
    最近更新 更多