【问题标题】:clean method not working for URLField清洁方法不适用于 URLField
【发布时间】:2018-01-12 19:35:35
【问题描述】:

我正在做一些要求用户输入 URL 的事情。然后我意识到大多数用户在编写 URL 时不会在前面加上“http://”,然后我决定使用一种干净的方法。在检查了很多 URLField 清理方法的地方后,我想出了这个:

from django import forms
from rango.models import Category, Page

class CategoryForm(forms.ModelForm):
    name = forms.CharField(max_length=128, help_text="Please enter category name")
    views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
    likes = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
    slug = forms.CharField(widget=forms.HiddenInput(), required=False)

    # Create an inline class to provide extra information about the form
    class Meta:
        # Provide the association between a model form and a model
        model = Category
        fields = ('name',)

class PageForm(forms.ModelForm):
    title = forms.CharField(max_length=128, help_text="Please enter the title of the page")
    url = forms.URLField(max_length=200, help_text="Please enter the url of the page", initial="http://")
    views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)

    def clean(self):
        cleaned_data = self.cleaned_data
        url = cleaned_data.get('url')

        # If url is not empty and doesn't start with http://, prepend it
        if url and not url.startswith('http://'):
            url = 'http://' + url
            cleaned_data['url'] = url

            return cleaned_data

    class Meta:
        # Provide association between model form and model
        model = Page
        # What fields do we want to include or exclude from our form?
        exclude = ('category',)

不幸的是,这不起作用,因为我仍然收到无效的 url 错误。有什么我想念的吗?如果是,是什么?

【问题讨论】:

  • 您的意见是什么?你得到/期待什么? “super().clean()”是什么意思?
  • @Heri 假设我想输入 www.google.com,如果我以这种方式输入网址,则会收到 http:// 丢失的错误消息。所以我正在寻找一个自动添加“http://”的功能
  • 如果你输入google.com它不会引发验证错误?
  • @lmr2391 我不希望它引发验证错误
  • 如果表单的 validate 函数引发 ValidationError,则此异常会在调用权重的某处被捕获,并将消息保存到 form.errors。所以你不会收到 500 服务器错误

标签: django


【解决方案1】:

如果您没有为 URL 输入方案(例如 http://),那么 Django 将默认为 http://。因此您不需要clean_url 方法,可以将其删除。

问题在于,因为 Django 使用type=url 呈现表单,所以您的浏览器也在验证输入。因为浏览器认为输入无效,所以表单永远不会提交给 Django。

一种选择是将输入更改为TextInput,这将阻止您的浏览器将其验证为 URL。

url = forms.URLField(max_length=200, widget=forms.TextInput, help_text="Please enter the url of the page")

另一种选择是将novalidate 添加到表单标记中,但这会关闭整个表单的浏览器验证。

<form method="post" novalidate>
  {{ form }}
</form>

【讨论】:

  • TextInput 效果很好,谢谢。我只是留下对 Docs 的引用:(docs.djangoproject.com/en/2.2/topics/forms) HTML5 输入类型和浏览器验证。就我而言,因为我只需要小部件,所以我在表单中添加了这个:widgets={'url':TextInput()}。从 django.forms 导入的 TextInput。
【解决方案2】:

由于您只验证一个字段,因此不应在表单清理方法中执行此操作,而应在clean_url-方法中执行此操作。对我来说,这很好用:

class PageForm(forms.ModelForm):
    def clean_url(self):
        url = self.cleaned_data.get('url')
        if not url.startswith('http://'):
            url = 'http://' + url
        return url

【讨论】:

    猜你喜欢
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    相关资源
    最近更新 更多