9

也许我在这里遗漏了一些东西,但根据 django 文档,我应该能够覆盖从 clean() 方法中从管理表单发送的值。来自 django 文档

def clean(self):
    from django.core.exceptions import ValidationError
    # Don't allow draft entries to have a pub_date.
    if self.status == 'draft' and self.pub_date is not None:
        raise ValidationError('Draft entries may not have a publication date.')
    # Set the pub_date for published items if it hasn't been set already.
    if self.status == 'published' and self.pub_date is None:
        self.pub_date = datetime.date.today()

我已经剥离了我的代码,只是在管理员内部尝试了一个基本示例

模型.py

class Test(models.Model):
name = models.CharField(max_length=255,)

def clean(self):
    self.name = 'Robin Hood'
    return self

因此,当我尝试添加新的测试记录时,如果我将名称字段留空,它应该从 clean 方法中获取值并保存。

但是会发生什么,表单没有验证,并且该字段保持为空。

我在这里错过了什么明显的东西吗?

4

5 回答 5

8

您甚至无法运行模型清理方法。Django 将首先运行表单的验证代码,并且由于您的字段未使用 定义blank=True,因此表单将首先强制执行该约束。

您应该做的是覆盖表单,设置字段,然后编写一个表单required=False清理方法,该方法在 - 中设置值并返回 - :nameself.cleaned_data

class TestForm(forms.ModelForm):
    name = forms.CharField(required=False)

    class Meta:
        model = Test

    def clean(self):
        self.cleaned_data['name'] = 'Robin Hood'
        return self.cleaned_data

并在您的管理类中引用该表单:

class TestAdmin(admin.ModelAdmin):
    form = TestForm
于 2013-01-23T19:43:52.280 回答
5

clean()从管理站点创建对象时不调用模型方法。clean()仅在之后调用,full_clean()但 Django 管理站点上的保存和对象不调用该函数。

正如您在Mode.clean() 的官方文档中看到的那样,full_clean()调用它来捕获额外的验证错误。

from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
try:
    article.full_clean()
except ValidationError, e:
    non_field_errors = e.message_dict[NON_FIELD_ERRORS]

为此,您将需要覆盖 save() 方法。

于 2013-01-23T19:54:48.760 回答
2

解决此问题的 2 个小步骤 :)

1)full_clean()在clean()之前调用,所以在models.py中设置pub_date为:

pub_date = models.DateField(null=True)

2)只需从clean函数返回cleaned_data dict来操作pub_date模型字段值。试试这个:

def clean(self):
    from django.core.exceptions import ValidationError
    # Don't allow draft entries to have a pub_date.
    if self.cleaned_data['status'] == 'draft' and self.cleaned_data['pub_date'] is not None:
        raise ValidationError('Draft entries may not have a publication date.')
    # Set the pub_date for published items if it hasn't been set already.
    if self.cleaned_data['status'] == 'published' and self.cleaned_data['pub_date'] is None:
       self.cleaned_data['pub_date'] = datetime.date.today()
    return self.cleaned_data
  • 怜悯其他开发人员并在 forms.py 文件顶部导入 ValidationError ,而不是不时将其导入每个干净的函数中:)
于 2014-06-23T06:18:40.013 回答
1

尝试这个。您需要返回所有已清理的数据。此外,如果您还没有这样做,您需要blank=True在表单字段上设置以使其为空白。

def clean(self,*args,**kwargs):
    cleaned_data = super(Test,self).clean(*args,**kwargs)

    # Check to see if name is entered, if not set it to robin hood. 
    if not cleaned_data['name']:
        cleaned_data['name'] = 'Robin Hood'

    return cleaned_data
于 2013-01-23T19:55:00.287 回答
1

假设您有一个具有三个字段 field1、2 和 3 的模型,并且您希望将 field3 设置为 field1 和 field2 的组合,您可以这样编写:

class MyModel(models.Model):
    field1 = ...
    field2 = ...
    field3 = ...

    def clean(self):
        #simply set field3 as the value you want, and note that RETURN is NOT NEEDED in this function
        self.field3 = "%s-%s" % (self.field1, self.field2)
于 2014-01-14T02:36:16.200 回答