繁体   English   中英

Django连接临时pre_save信号

[英]Django connect temporary pre_save signal

我已经为Django信号问题苦苦挣扎了几天,请多多关照。

场景

我希望使用一个黑盒方法(实际上是geodjango中的LayerMapping加载器,但这在这里并不重要),该方法可以生成并保存模型实例。 由于某种原因,它无法设置模型中的字段之一。 不幸的是,该字段不能为null,因此黑盒方法失败,并显示IntegrityError。 示例代码:

models.py

class MyModel(models.Model):
    field1 = models.IntegerField()
    field2 = models.IntegerField()
    field3 = models.IntegerField() # This one is the problem

call_black_box.py

from some_app import black_box
from models import MyModel

def call_it():
    black_box(MyModel, some_other_args) # Fails

黑匣子例程尝试创建MyModel的某些实例,但将失败,并显示以下错误:IntegrityError:“ field3”列中的null值违反了非null约束

我的解决方案

我已经动态生成了一个pre_save回调,将其附加到MyModel上,然后在最后将其断开连接(因为我不一定总是想要这种行为):

call_black_box.py

from some_app import black_box
from models import MyModel
from django.db.models.signals import pre_save

def call_it():
    def pre_save_callback(sender, instance, *args, **kwargs):
        instance.field3 = 1
    pre_save.connect(pre_save_callback, sender=MyModel)
    try:
        black_box(MyModel, some_other_args) # OK
    finally:
        pre_save.disconnect(pre_save_callback, sender=MyModel)

它有效,但是有更好的方法吗? 我猜测如果与此功能同时执行其他一些操作,则可能会出错。 对我来说这不是问题,因为我目前按顺序进行所有操作,但并不理想吗?

谢谢!

编辑

我没有提供足够的细节。 对于第二个功能,分配给field3的值将有所不同:

def call_it_differently():
    def pre_save_callback(sender, instance, *args, **kwargs):
        instance.field3 = some_other_value
    pre_save.connect(pre_save_callback, sender=MyModel)
    try:
        black_box(MyModel, some_other_args) # OK
    finally:
        pre_save.disconnect(pre_save_callback, sender=MyModel)

所以我不能提供默认值,也不能覆盖save方法-因为这些选项仅允许我指定一个值,而我需要灵活地应用一个任意值。

如果我正确理解了您的问题,则可以为模型中的第三个字段定义默认值

class MyModel(models.Model):
    field1 = models.IntegerField()
    field2 = models.IntegerField()
    field3 = models.IntegerField(default=1) # This one is the problem

因此,如果未指定该值,则Django将默认值为1

Django信号通常用作挂钩点。 假设您正在编写将由其他人使用的第三方应用程序,并且想要向他们提供一些挂钩点来操纵您的代码,然后将使用信号。

在您的方案中,我宁愿覆盖Model的save()方法,也不愿使用信号。

class MyModel(models.Model):
    field1 = models.IntegerField()
    ///
    field3 = models.IntegerField()

    def save(self, *args, **kwargs):
        self.field3 = 1
        super(MyModel, self).save(*args, **kwargs)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM