8

我有一个状态字段,它有 3 个值:挂起、激活和拒绝。如果我要更改状态的值,我希望检查已激活不能更改为待处理。我不想为此编写存储过程。在保存之前我可以在 Django 中获得以前的值吗?

表示新旧价值。

4

5 回答 5

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子类中。请参阅 Django 文档。

于 2009-05-15T13:34:23.270 回答
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 项目正在进行中,以启用“模型验证”,但这要几个月才能准备好。

如果您想在管理员中做类似的事情,最好的方法是定义一个自定义 ModelForm 并覆盖一个clean()方法。但是,这一次,因为这是一种形式,您已经可以访问旧值而无需再次访问数据库。另一个好处是您可以向用户返回表单验证错误。

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
于 2009-05-15T06:35:08.113 回答
1

这已在 Stack Overflow 的其他地方得到解答,但正确的方法是使用类似这样的方法来跟踪字段是否脏。然后,您可以使用信号来表示重要的事情发生了变化。(即你的领域)

于 2011-11-10T19:28:50.377 回答
0

与其重写 save 方法,这不是一个使用信号的好地方吗?在提交前拦截保存,检查数据库中的当前值,然后转发保存,或者拒绝它?

现在我不确定信号是否阻止了保存请求或者它是否发生异步,所以如果不能使用信号来防止在验证时发生保存,请随意对这个答案投反对票。

如果有另一个同样有效的内置工具,我反对覆盖内置方法。

于 2009-05-15T10:47:26.837 回答
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)
于 2012-02-20T19:35:59.207 回答