I've been struggling with a Django signal issue for a few days now and would appreciate your thoughts.
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. 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. Example code:
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
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
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):
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:
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.