如何在验证URLField之前删除空格?
使用“clean_ [fieldname]()”似乎是来自https://docs.djangoproject.com/en/dev/ref/forms/validation/的文档化方式,但它不适用于URLField。我把它简化为一个基本的测试用例,可以在django shell中运行:
class XXXTestModel(models.Model):
url = models.URLField('URL',null=True,blank=True)
name = models.CharField(max_length=200)
class XXXTestForm(ModelForm):
def clean_url(self):
return self.cleaned_data['url'].strip()
def clean_name(self):
return self.cleaned_data['name'].strip()
class Meta:
model = XXXTestModel
fields = (
'url',
)
使用:
从Django shell测试>>> django.VERSION
(1, 5, 1, 'final', 0)
>>> from xxx import XXXTestForm,XXXTestModel
>>> data = dict(url=' http://www.example.com/ ',name=' example ')
>>> f=XXXTestForm(data)
>>> f.is_valid();f.errors
False
{'url': [u'Enter a valid URL.']}
>>> f.cleaned_data
{'name': example'}
这个问题有很多关于堆栈溢出的密切欺骗,但没有一个答案指导解决方案。
答案 0 :(得分:7)
这里的问题是django.forms.URLField
如何运作。
django.forms.Field.clean
定义为:
def clean(self, value):
"""
Validates the given value and returns its "cleaned" value as an
appropriate Python object.
Raises ValidationError for any errors.
"""
value = self.to_python(value)
self.validate(value)
self.run_validators(value)
return value
请注意,to_python
在任何验证之前执行。这是问题所在 - django.forms.URLField
无法理解你给它的值,因此它产生的值使得已经定义为django.forms.URLField
一部分的验证器集失败(即django.core.validators.URLValidator
})。
失败的原因是django尝试“规范化”URL。这包括在需要的地方添加"http://"
等内容。在给出您的示例网址" http://www.example.com "
时,django使用urlparse.urlsplit
来获取网址的“部分”。然而,领先的空间将其混乱,整个价值成为path
的一部分。因此,django找不到scheme
,并将网址重新设为"http:// http://www.example.com "
。然后将其提供给django.core.validators.URLValidator
,这显然会失败。
为避免这种情况,我们需要为表单
定义自己的URLField
from django import forms
class StrippedURLField(forms.URLField):
def to_python(self, value):
return super(StrippedURLField, self).to_python(value and value.strip())
使用它可以确保流程完全符合预期,我们不需要clean_url
方法。 (注意:你应尽可能使用clean_*
,但这里不是)
class XXXTestForm(forms.ModelForm):
url = StrippedURLField(blank=True, null=True)