你最好的办法是在保存对象的同时进行这样的计算。所以覆盖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 和测试用例