vijay shanker
vijay shanker

Reputation: 2673

Form's clean method not getting called

I am trying to create some objects with django's CBV FormView the code for form_class is like this:

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

and i use this view to render the form:

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())

The url should be unique, so i try to raise ValidationError if There exists a Url with same value.But the catch is, its not going into form's clean method nor in form_valid or form_invalid, it simply shoots to post method and tries to create url and seo objects. Why is my form's clean method /form_valid/invalid not getting called .. i am at my wits end !!

Upvotes: 1

Views: 6001

Answers (3)

Tarun Behal
Tarun Behal

Reputation: 918

your post method is wrong. you must either use form_valid method like below

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())

or if you want to use Post method use it like below:

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())

I'vent tested the code but it will work. Let me explain why your code didnt worked. In your post method you didnt initialized the form with post arguments. once the form is initialized you can run clean method and it will raise exceptions if any. Also since you are using FormView, there is a form_valid method (my recommendation is to first read before development). Another advice, since you are using form to create object, why not use CreateView and ModelForm.. :)

Upvotes: 5

GwynBleidD
GwynBleidD

Reputation: 20569

This won't work because you're overriding entire post method in view. That post method is by default responsible for calling validation on form and calling form_valid or form_invalid method after that.

What is the point of using FormView if you're not using form at all.

Also: you sholud refer to form's cleaned_data instead of request.POST. It will contain only fully cleaned data.

Upvotes: 4

gamer
gamer

Reputation: 5863

When calling clean you have to return clean data with 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

Upvotes: 2

Related Questions