我有一个状态字段,其中包含3个值:pending,activated 并拒绝。如果我要更改我想要的状态值 有一个检查,激活无法更改为待处理。一世 不想为此编写存储过程。我可以吗? 保存之前Django中的前一个值?
意味着新旧价值。
答案 0 :(得分:10)
def clean_status(self):
status = self.cleaned_data.get('status')
if status == 'pending':
if self.instance and self.instance.status == 'activated':
raise forms.ValidationError('You cannot change activated to pending')
return status
此方法将添加到Form
子类中。它的名字是clean_FIELD_NAME
。
cleaned_data
包含以前的值。新值存储在self.instance
。
或者,可以将validate()
方法添加到forms.Field
子类中。 See Django documentation.
答案 1 :(得分:9)
您可以使用重写的save
方法执行此操作。要记住的是Django模型实例不是实际的数据库对象,它们只是在加载时从那里获取它们的值。因此,您可以在保存当前对象之前轻松返回数据库以获取现有值。
def save(self, *args, **kwargs):
if self.status == 'pending':
old_instance = MyClass.objects.get(pk=self.pk)
if old_instance.status == 'activated':
raise SomeError
super(MyModel, self).save(*args, **kwargs)
除了引发异常之外,目前没有向用户返回错误消息的好方法。目前正在进行Google Summer of Code项目以启用“模型验证”,但这将在几个月内完成。
如果您想在管理员中执行类似操作,最好的方法是使用重写的clean()
方法定义自定义ModelForm。但是,这次是因为这是一个表单,您已经可以访问旧值而无需再次访问数据库。另一个好处是您可以向用户返回表单验证错误。
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def clean_status(self):
status = self.cleaned_data.get('status', '')
if status == 'pending':
if self.instance and self.instance.status == 'activated':
raise forms.ValidationError(
'You cannot change activated to pending'
)
return status
class MyModelAdmin(forms.ModelAdmin):
form = MyModelForm
model = MyModel
答案 2 :(得分:1)
这已在Stack Overflow的其他地方得到解答,但正确的方法是使用类似this的内容来跟踪字段是否脏。然后你可以使用一个信号来表示某些事情发生了重要变化。 (即你的领域)
答案 3 :(得分:0)
而不是覆盖保存方法,这不是一个使用信号的好地方吗?在提交之前拦截保存,检查数据库中的当前值,然后转发保存,还是拒绝它?
现在我不确定信号是否阻止了保存请求,或者它是否发生异步,所以如果信号无法用于阻止验证时发生保存,请随时关注此答案。
如果有另一个内置工具也能正常工作,我反对覆盖内置方法。
答案 4 :(得分:0)
在搜索同一问题的答案时找到此帖子。为什么不做这样的事情?这样就可以避免触及数据库。并且内置__init__
只是稍微扩展一点。我认为这比使用信号简单得多。
class MyModel(models.Model):
my_fair_field = ....
def __init__(self, *args, **kwargs):
super(MyModel, self).__init__(*args, **kwargs)
self.__clean_fair_field = self.my_fair_field
def save(self, *args, **kwargs):
# check if field value changed
if self.__clean_fair_field != self.my_fair_field
# ...do some work...
super(MyModel, self).save(*args, **kwargs)