ModelForm clean_xxxx()适用于CharField,不适用于URLField.Django 1.5

Bry*_*yce 4 django django-models django-forms

在验证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',
        )
Run Code Online (Sandbox Code Playgroud)

从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'}
Run Code Online (Sandbox Code Playgroud)

关于堆栈溢出,这个问题有很多密切的愚蠢,但没有一个答案指导解决方案.

Dan*_*elB 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
Run Code Online (Sandbox Code Playgroud)

请注意,to_python在任何验证之前执行.这是这里的问题- django.forms.URLField不明白,你给它的价值,所以它产生的价值无法设定验证的已定义为的一部分django.forms.URLField(即,django.core.validators.URLValidator).

它失败的原因是django试图"规范化"URL.这包括诸如"http://"在需要的地方添加的内容.当给出你的示例url时" http://www.example.com ",django用urlparse.urlsplit它来获取url的"部分".然而,领先的空间将其混乱,整个价值成为其中的一部分path.因此,django发现没有scheme,并重新构建URL为"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())
Run Code Online (Sandbox Code Playgroud)

使用它确保过程将按预期进行,我们不需要一个clean_url方法.(注意:你应该clean_*尽可能使用,但这里不是)

class XXXTestForm(forms.ModelForm):
    url = StrippedURLField(blank=True, null=True)
Run Code Online (Sandbox Code Playgroud)