简体   繁体   English

Django连接临时pre_save信号

[英]Django connect temporary pre_save signal

I've been struggling with a Django signal issue for a few days now and would appreciate your thoughts. 我已经为Django信号问题苦苦挣扎了几天,请多多关照。

Scenario : 场景

I wish to use a black box method (it's actually the LayerMapping loader in geodjango, but that's not important here) that generates and saves model instances. 我希望使用一个黑盒方法(实际上是geodjango中的LayerMapping加载器,但这在这里并不重要),该方法可以生成并保存模型实例。 For some reason, it cannot set one of the fields in my model. 由于某种原因,它无法设置模型中的字段之一。 Unfortunately, that field cannot be null, so the black box method fails with an IntegrityError. 不幸的是,该字段不能为null,因此黑盒方法失败,并显示IntegrityError。 Example code: 示例代码:

models.py models.py

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

call_black_box.py call_black_box.py

from some_app import black_box
from models import MyModel

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

The black box routine tries to create some instances of MyModel, but will fail with the error: IntegrityError: null value in column "field3" violates not-null constraint 黑匣子例程尝试创建MyModel的某些实例,但将失败,并显示以下错误:IntegrityError:“ field3”列中的null值违反了非null约束

My solution : 我的解决方案

I have generated a pre_save callback dynamically, attached it to MyModel, then disconnected it at the end (because I don't necessarily always want this behaviour): 我已经动态生成了一个pre_save回调,将其附加到MyModel上,然后在最后将其断开连接(因为我不一定总是想要这种行为):

call_black_box.py 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)

It works, but is there a nicer way? 它有效,但是有更好的方法吗? I'm guessing this could go wrong if some other actions were executed at the same time as this function. 我猜测如果与此功能同时执行其他一些操作,则可能会出错。 Not a problem for me as I currently do everything sequentially, but not ideal? 对我来说这不是问题,因为我目前按顺序进行所有操作,但并不理想吗?

Thanks! 谢谢!

edit : 编辑

I didn't give enough detail. 我没有提供足够的细节。 The value assigned to field3 will be different for a second function: 对于第二个功能,分配给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)

So I can't give a default value, or override the save method - because these options only allow me to specify a single value, whereas I need the flexibility to apply an arbitrary one. 所以我不能提供默认值,也不能覆盖save方法-因为这些选项仅允许我指定一个值,而我需要灵活地应用一个任意值。

If I understood your question correctly, you can define the default value for the third field in your model 如果我正确理解了您的问题,则可以为模型中的第三个字段定义默认值

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

So if the value is not specified then Django will take 1 as default 因此,如果未指定该值,则Django将默认值为1

Django signals are mostly used as a hook point. Django信号通常用作挂钩点。 Say you are writing a third party app which will be used by other people and you want to provide them with some hook points to manipulate your code, then signals would be used. 假设您正在编写将由其他人使用的第三方应用程序,并且想要向他们提供一些挂钩点来操纵您的代码,然后将使用信号。

In your scenario, I would rather override the save() method of Model than use a signal. 在您的方案中,我宁愿覆盖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