【问题标题】:Django - How to dynamically create signals inside model MixinDjango - 如何在模型 Mixin 中动态创建信号
【发布时间】:2020-01-05 08:44:02
【问题描述】:

我正在开发一个模型Mixin,它需要根据一个属性动态设置信号。

它更复杂,但为了简单起见,假设 Mixin 有这个属性:

models = ['app.model1','app.model2']

这个属性在model 中定义,它扩展了这个mixin。

如何动态注册信号?

我尝试创建一个类方法:

@classmethod
def set_signals(cls):
    def status_sig(sender, instance, created, *args, **kwargs):
        print('SIGNAL')
        ... do som things

    for m in cls.get_target_models():
        post_save.connect(status_sig,m)

我的想法是在类的某个地方自动调用此方法(例如__call__ 方法),但现在,我只是尝试调用它,然后save 模型以查看它是否有效,但它没有。

from django.db.models.signals import post_save

print(post_save.receivers)
Realestate.set_signals()
print(post_save.receivers)

r = Realestate.objects.first()
r.status = 1
r.save()

输出

[]
[((139967044372680, 46800232), <weakref at 0x7f4c9d702408; dead>), ((139967044372680, 46793464), <weakref at 0x7f4c9d702408; dead>)]

所以您看到它注册了这些模型,但在保存房地产后没有触发任何信号。

你知道如何让它工作吗?不用显式调用方法就更好了?

编辑:

我不能只将信号创建放在mixin 文件中,因为模型依赖于子模型中的字符串。

【问题讨论】:

  • signals.connect()方法的sender属性必须是Python对象,get_target_models()返回的是类还是字符串?
  • 我也不明白你上次的编辑,为什么这不能在混音中。如果get_target_models() 使用cls.models,它将获取子类中设置的那些。
  • @dirkgroten get_target_models() 返回模型类的列表,而不是字符串。
  • @dirkgroten 它不能在类外的文件中,因为可以在解释器知道子类(使用 mixin 的类)中定义的“模型”属性后创建信号
  • 这取决于你打电话给set_signals

标签: python django django-models django-signals


【解决方案1】:

如果你还没有解决这个问题:

connect 方法中,设置weak=False。默认为True,因此如果对象实例被垃圾回收,本地定义的函数引用将丢失。

这可能是您的status_sig 函数发生的情况;正如您在 post_save 接收器的打印输出中看到的那样,weakref 已死,因此将始终返回 None

Django docs

weak – Django 默认将信号处理程序存储为弱引用。因此,如果您的接收器是本地函数,它可能会被垃圾回收。为防止这种情况发生,请在调用信号的 connect() 方法时传递 weak=False。

有关weakrefs 的更多信息,请参阅Python docs

【讨论】:

    猜你喜欢
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    • 2017-04-13
    • 1970-01-01
    • 2011-04-12
    • 2021-08-08
    • 1970-01-01
    • 2012-06-11
    相关资源
    最近更新 更多