Python Django Admin Clean() 方法未覆盖值
我可能漏掉了什么,但根据Django的文档,我应该可以在clean()方法中覆盖从管理员表单发送的值。
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()
我把代码简化了,现在只是想在管理员界面试一个基本的例子。
Models.py
class Test(models.Model):
name = models.CharField(max_length=255,)
def clean(self):
self.name = 'Robin Hood'
return self
所以当我尝试添加一个新的测试记录时,如果我把名字字段留空,它应该能从clean方法中获取值并保存。
但实际上,表单没有通过验证,字段还是空的。
我是不是漏掉了什么明显的东西?
5 个回答
4
解决这个问题只需要两个简单的步骤 :)
1) 在调用 clean() 之前会先调用 full_clean(),所以在 models.py 文件中把 pub_date 设置成:
pub_date = models.DateField(null=True)
2) 只需从 clean 函数返回 cleaned_data 字典,以便修改 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,而不是在每个 clean 函数里时不时地导入它 :)
5
在Django的管理后台创建对象时,模型的 clean()
方法不会被调用。其实,clean()
这个方法只有在调用 full_clean()
后才会执行,但在Django的管理后台保存对象时,并不会自动调用这个方法。
正如你在 官方文档中关于 Model.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()
方法。
8
你甚至连运行模型的清理方法都不会执行。Django会先运行表单的验证代码,因为你的字段没有设置为 blank=True
,所以表单会首先强制执行这个限制。
你应该做的是重写这个表单,把 name
字段的 required
设置为 False
,然后写一个 form 的清理方法,这个方法会设置值并返回 self.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