Django:如何清理表单域并避免代码复制 [英] Django: how to cleanup form fields and avoid code duplication
问题描述
clean_< fieldname>
方法执行此操作并不困难: #两个文本字段的简化模型
class MyModel(models.Model):
title = models.CharField()
description = models.CharField()
#基于模型的表单
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
def clean_title(self):
title = self.cleaned_data ['title']
return re.sub(r'\s {2,}','',title.strip())
def clean_description(self) :
description = self.cleaned_data ['description']
return re.sub(r'\s {2,}','',description.strip())
它完全符合我所需要,并且有一个很好的副作用,我喜欢:如果用户只输入空格,该字段将被认为是空的,因此无效(如果需要的话),甚至不需要抛出一个 ValidationError
。
这里的明显问题是代码重复。即使我会为此创建一些功能,例如 my_text_filter
,我必须为所有表单中的每个文本字段调用它:
从$ m code code code code
$ model = MyModel
def clean_title(self):
return my_text_filter(self.cleaned_data ['title'])
def clean_description(self):
return my_text_filter(self.cleaned_data ['description'])
问题是:是否有任何标准和在Django中简单的方法(如果有重要的话,我使用1.2版本)来做(例如,通过添加属性 validators = {'title':my_text_filter,'description':my_text_filter}
到 MyModel
),或至少有一些或多或少的标准解决方法?我已经阅读了文档中的表单验证和验证器,但是找不到我需要的内容。
知道Django没有任何原生解决方案来解决你的问题。
我可以只显示我为自己解决这个问题。
我建议您为您的ModelForm使用装饰器。
这里的工作代码(我也使用日志模块):
#DECORATOR
def applyValidators(model_form):
def apply(* args,** kwargs):
try:
if hasattr(model_form.Meta.model,validators):
for field_name,fnc in model_form.Meta.model.validators.items():
setattr(model_form,clean_%s%field_name,fnc)
除了异常,err:
log.error(str(err))
return model_form(* args,** kwargs)
return apply
#VALIDATORS
def validator(* args,* * kwargs)
返回SOMEVALUE
#MODEL
class MyModel(models.Model):
#你的字段
..... ..
.......
.......
#VALIDATE DICT
validators = {username:验证器,电子邮件:validator}
#MODEL FORM
@applyValidators
class MyModelForm(forms.ModelForm):
class Meta:
model = M yModel
.......
.......
.......
Quite often I need to filter some form data before using it (saving to database etc.) Let's say I want to strip whitespaces and replace repeating whitespaces with a single one in most of the text fields, in many forms. It's not difficult to do this using clean_<fieldname>
methods:
# Simplified model with two text fields
class MyModel(models.Model):
title = models.CharField()
description = models.CharField()
# Model-based form
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
def clean_title(self):
title = self.cleaned_data['title']
return re.sub(r'\s{2,}', ' ', title.strip())
def clean_description(self):
description = self.cleaned_data['description']
return re.sub(r'\s{2,}', ' ', description.strip())
It does exactly what I need, and has a nice side effect which I like: if user enters only whitespaces, the field will be considered empty and therefore invalid (if it is required) and I don't even have to throw a ValidationError
.
The obvious problem here is code duplication. Even if I'll create some function for that, say my_text_filter
, I'll have to call it for every text field in all my forms:
from myproject.filters import my_text_filter
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
def clean_title(self):
return my_text_filter(self.cleaned_data['title'])
def clean_description(self):
return my_text_filter(self.cleaned_data['description'])
The question: is there any standard and simple way in Django (I use version 1.2 if that matters) to do this (like, for example, by adding property validators = {'title': my_text_filter, 'description': my_text_filter}
to MyModel
), or at least some more or less standard workaround? I've read about form validation and validators in the documentation, but couldn't find what I need there.
as i know Django don't have any native solutions to resolve you question. I can show only how i resolve this problem for myself. I advice you to use decorator for you ModelForm. Here the working code(also i use logging module):
#DECORATOR
def applyValidators(model_form):
def apply(*args,**kwargs):
try:
if hasattr(model_form.Meta.model,"validators"):
for field_name,fnc in model_form.Meta.model.validators.items():
setattr(model_form,"clean_%s" % field_name,fnc)
except Exception,err:
logging.error(str(err))
return model_form(*args,**kwargs)
return apply
#VALIDATORS
def validator(*args,**kwargs):
return "SOMEVALUE"
#MODEL
class MyModel(models.Model):
#Your fields
.......
.......
.......
#VALIDATE DICT
validators = {"username":validator,"email":validator}
#MODEL FORM
@applyValidators
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
.......
.......
.......
这篇关于Django:如何清理表单域并避免代码复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!