django - ModelForm clean_xxxx() 适用于 CharField,不适用于 URLField。 Django 1.5

标签 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',
        )

从 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'}

关于堆栈溢出,这个问题有很多密密麻麻的重复,但没有一个答案指导解决方案。

最佳答案

这里的问题是如何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 ,并将 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())

使用它可以确保整个过程按预期进行,而且我们不需要 clean_url方法。 (注意:你应该尽可能使用 clean_*,但这里不是)
class XXXTestForm(forms.ModelForm):
    url = StrippedURLField(blank=True, null=True)

关于django - ModelForm clean_xxxx() 适用于 CharField,不适用于 URLField。 Django 1.5,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19868000/

相关文章:

django - 类型错误 : __init__() got an unexpected keyword argument 'on_delete'

python - Django1.5 - python2.7 -如何显示和更新具有3个外键的数据库

django InlineFormsets 错误报告,表单集错误列表为空

python - Django:使用 form=MyForm(instance=MyID) 更新现有记录不起作用

django - 如何在 django 评论中包含用户个人资料的图像/ Logo

django - django-haystack:预测构面

django - GeoDjango 项目缺少数据库模式中的字段

python - 找不到页面 (404) 请求方法 : POST Request URL: http://127. 0.0.1:8000/accounts/signup/signup

Django自定义用户模型无法登录管理页面

django - 用于创建具有一对多关系的新对象的内联表单集?