オブジェクトを保存するときにそのような計算を行うのが最善です。だからオーバーライドModel.save
または、より一般的な方法は、カスタム フィールドを記述してpre_saveをオーバーライドすることです。
class DependentIntegerField(models.IntegerField):
def pre_save(self, model_instance, add):
if not add: # set the default only while adding model
return super(self, DependentIntegerField).pre_save(model_instance, add)
return model_instance.number*50
それをさらに拡張してDependentIntegerField
ジェネリックにすることで、callable を渡して任意の計算を行うことができます。また、デフォルト値を使用する前にユーザーが値を設定したかどうかをチェックするなどのさらなる拡張を行うことができ、よりジェネリックにすることができます。フィールドクラスをファクトリ関数に渡すことにより、任意のフィールドを依存フィールドとして作成できます。例えば
from django.db import models
class_map = {}
def depends_field_pre_save(self, model_instance, add):
"""
if default is not callable or it is not a model add, lets skip our hook
"""
if not add or not callable(self.default):
super(self.__class__, self).__init__(self,*args, **kwargs)
value = self.default(model_instance)
setattr(model_instance, self.attname, value)
return value
def FieldDepends(field_class):
"""
return a dervied class from field_class which supports dependent default
"""
if field_class in class_map:
# we already created this class so return that
return class_map[field_class]
new_class = type('Depends'+field_class.__name__, (field_class,), {'pre_save':depends_field_pre_save })
class_map[field_class] = new_class
return new_class
そして、このように使用します
class DependentModel(models.Model):
def threshold_default(model_instance=None):
if model_instance is None:
return 10
return model_instance.number*10
number = models.IntegerField(null=True, blank=True, default=10)
threshold = FieldDepends(models.IntegerField)(null=True, blank=True, default=threshold_default,editable=False)
小さな django プロジェクトdjangodepends on bitbucket with test cases を作成しました