Form的干净方法没有被调用

时间:2015-08-18 07:16:02

标签: python django django-forms django-views django-class-based-views

我正在尝试使用django的CBV创建一些对象FormView form_class的代码是这样的:

class UrlForm(forms.Form):
    url = forms.CharField(required=True,
                help_text=_("This should be an absolute path, excluding the domain name.\
                             Example: '/events/search/'."),
                widget=forms.TextInput(attrs={'style':'width:400px;'}))
    title = forms.CharField(required=True, widget=forms.Textarea())
    description = forms.CharField(required=True, widget=forms.Textarea())
    keywords = forms.CharField(required=True, widget=forms.Textarea())

    def clean(self):
        cleaned_data = super(UrlForm, self).clean()
        url = cleaned_data.get('url')
        try:
            Url.objects.get(url=url)
            raise forms.ValidationError("Seo Url already exists.")
        except:
            pass
        return cleaned_data

我使用此视图呈现表单:

class CreateSeoByUrl(FormView):
    template_name = 'create_seo_by_url.html'
    form_class = UrlForm

    def get_success_url(self):
        return reverse('dashboard:index')

    def post(self, request, *args, **kwargs):
        url = Url.objects.create(url= request.POST.get('url'))
        seo = Seo.objects.create(
                    title = request.POST.get('title'),
                    description = request.POST.get('description'),
                    keywords = request.POST.get('keywords'),
                    content_object=url)

        return redirect(self.get_success_url())

网址应该是唯一的,所以如果存在一个具有相同值的网址,我会尝试引发ValidationError。但问题是,它不会进入表单的清理方法,也不会进入form_valid或{{ 1}},它只是拍摄post方法并尝试创建url和seo对象。为什么我的表单是干净的方法/ form_valid / invalid没有被调用..我在我的智慧结束!

3 个答案:

答案 0 :(得分:4)

你的帖子方法错了。你必须使用如下所示的form_valid方法

def form_valid(self, form):
    url = Url.objects.create(url= form.cleaned_data['url'])
    seo = Seo.objects.create(
                title = form.cleaned_data['title'],
                description = form.cleaned_data['description'],
                keywords = form.cleaned_data['keywords'],
                content_object=url)

    return redirect(self.get_success_url())

或者如果你想使用Post方法,请使用如下所示:

def post(self, request, *args, **kwargs):
    form = self.form_class(request.POST)
    if form.is_valid():
        url = Url.objects.create(url= form.cleaned_data['url'])
        seo = Seo.objects.create(
                title = form.cleaned_data['title'],
                description = form.cleaned_data['description'],
                keywords = form.cleaned_data['keywords'],
                content_object=url)

    return redirect(self.get_success_url())

我通过测试代码但它会起作用。让我解释为什么你的代码没有用。在你的post方法中,你没有使用post参数初始化表单。一旦表单初始化,你可以运行clean方法,如果有的话会引发异常。此外,由于您使用的是FormView,因此有一个form_valid方法(我的建议是在开发之前先阅读)。另一个建议是,因为你使用form来创建对象,为什么不使用CreateView和ModelForm .. :)

答案 1 :(得分:2)

这不会起作用,因为您在视图中覆盖了整个post方法。默认情况下,post方法负责在表单上调用验证并在此之后调用form_validform_invalid方法。

如果您根本不使用表单,则使用FormView有什么意义。

另外:你sholud参考表格cleaned_data而不是request.POST。它只包含完全清理的数据。

答案 2 :(得分:1)

调用clean时,你必须使用self

返回干净的数据
def clean(self):
    url = self.cleaned_data.get('url')
    try:
        my_url = Url.objects.get(url=url)
        if my_url:
            raise forms.ValidationError("Seo Url already exists.")
    except Url.DoesNotExist:
        pass
    return self.cleaned_data