Django 连接临时 pre_save 信号
我最近在处理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: null value in column "field3" violates not-null constraint
我的解决方案:
我动态生成了一个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)
所以我不能给一个默认值,也不能重写保存方法——因为这些选项只能让我指定一个单一的值,而我需要灵活性来应用任意的值。
2 个回答
Django信号主要用作钩子点。比如说,你正在写一个第三方应用,这个应用会被其他人使用,你想给他们一些可以操作你代码的钩子点,这时候就可以使用信号。
在你的情况下,我更倾向于重写模型的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)
如果我理解你的问题没错的话,你可以为你模型中的第三个字段设置一个默认值。
class MyModel(models.Model):
field1 = models.IntegerField()
field2 = models.IntegerField()
field3 = models.IntegerField(default=1) # This one is the problem
这样如果没有指定这个值,Django 就会默认使用 1 作为这个字段的值。