Kirill_Ja
Kirill_Ja

Reputation: 5

Form validation does not work. How to call clean_field methods

I'm going to add records to DBase using form. So I need data to be written to a database when the request.method = 'Post' and form.is_valid. I have this written in my views.py

def makepicturepost(request):
    form = PostForm2()
    print('View called')
    print('Request_method ' + request.method + ' Form.is_valid ' + str(form.is_valid()))

    if request.method == 'POST' and form.is_valid():
        author = form.author
        comment = form.comment
        picture = form.picture
        newpost = PicturePost(author=author, comment=comment, picture=picture)
        newpost.save()
        return HttpResponseRedirect('/')

    context = {
        "form": form
    }
    return render(request, "makepost.htm", context)

The form validation should be checked after calling form.is_valid(), so I wrote some validation methodes in my forms.py

class PostForm2(forms.Form):
    author = forms.CharField(max_length=30, widget=forms.TextInput)
    comment = forms.CharField(max_length=1500, widget=forms.Textarea)
    picture = forms.ImageField()

    def clean_author(self):
        print('cleaned_author')
        author = self.cleaned_data.get('author')
        if not author:
            raise forms.ValidationError("Autor name shouldn't be blank")
        return author

    def clean_comment(self):
        print('cleaned_comment')
        comment = self.cleaned_data.get('comment')
        if not comment:
            raise forms.ValidationError("Write a pair of lines as a comment")
        return comment

    def clean_picture(self):
        print('cleaned_picture')
        picture = self.cleaned_data.get('picture')
        print(picture)
        return picture

I was going to inspect picture object to find out how to check it to be only an image. But my clean_field methods seem not called at all. That's what I have in console:

View called
Request_method POST Form.is_valid False
[13/Jun/2017 11:12:38] "POST /post/ HTTP/1.1" 200 788

As I understood docs, they should run, but they didn't. Where am I wrong?

Upvotes: 0

Views: 470

Answers (3)

Shkelqim Memolla
Shkelqim Memolla

Reputation: 65

For this to work you have to consider some points:

  • your makepost.htm template form should include enctype="multipart/form-data"
  • as mentioned by Exprator you need to get the post data
  • you need also to get request.FILES in order to access files
  • you should access form fields by using form.cleaned_data['field']

Having these in mind this code give your desired result

def makepicturepost(request):
    if request.method == 'POST':
        form = PostForm2(request.POST, request.FILES)
        if form.is_valid():
            author = form.cleaned_data['author']
            comment = form.cleaned_data['comment']
            picture = form.cleaned_data['picture']
            newpost = PicturePost(author=author, comment=comment, picture=picture)
            newpost.save()
            return HttpResponseRedirect('/')
    else:
        form = PostForm2()

    context = {
            'form': form
        }
    return render(request, 'makepost.htm', context)

Upvotes: 3

Resley Rodrigues
Resley Rodrigues

Reputation: 2288

1) You need to initialize the form with the POST data
2) You need to use form.cleaned_data

def makepicturepost(request):
    form = PostForm2(request.POST)
    if request.method == 'POST' and form.is_valid():
        author = form.cleaned_data['author']
        comment = form.cleaned_data['comment']
        picture = form.cleaned_data['picture']
        newpost = PicturePost(author=author, comment=comment, picture=picture)
        newpost.save()
        return HttpResponseRedirect('/')

    context = {
        "form": form
    }
    return render(request, "makepost.htm", context)

A simpler approach would be to use a ModelForm and let the form create a new instance for you on save.

class PostForm2(forms.ModelForm):
    class Meta:
        model = PicturePost
        fields = ['author', 'comment', 'picture']
#  I've removed your clean methods as the the form does it for you
#  But the message may be different


def makepicturepost(request):
    form = PostForm2(request.POST)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return HttpResponseRedirect('/')

    context = {
        "form": form
    }
    return render(request, "makepost.htm", context)

Upvotes: 0

Exprator
Exprator

Reputation: 27513

def makepicturepost(request):
    form = PostForm2(request.POST)
    print('View called')
    print('Request_method ' + request.method + ' Form.is_valid ' + str(form.is_valid()))

    if request.method == 'POST' and form.is_valid():
        author = form.author
        comment = form.comment
        picture = form.picture
        newpost = PicturePost(author=author, comment=comment, picture=picture)
        newpost.save()
        return HttpResponseRedirect('/')

    context = {
        "form": form
    }
    return render(request, "makepost.htm", context)

you are not taking the post data to check for the clean methods for the PostForm2

Upvotes: 1

Related Questions