2

I recently tried the forms validations and faced an issue with ValidationError().

The form error does not appear in my website when I submit the form.

Here is the code:

forms.py

class ArticleForm(forms.ModelForm):

    def clean_titre(self):
        titre = self.cleaned_data['titre']
        if len(titre) < 5:
            raise ValidationError('myError')
        return titre

form = ArticleForm()

template.html

<div class="form-group">TITRE
  {{ form.titre.errors }}
  {{ form.titre }}
</div>

views.py

def AddArticle(request):
    form = ArticleForm(request.POST, request.FILES)

    if form.is_valid():
        save_it = form.save(commit=False)
        save_it.user = request.user
        save_it.save()
        form.save_m2m()
        return HttpResponseRedirect('/')

What did I do wrong?

--- EDIT ---

Full template.html

<form class="form" action="{% url "article.views.AddArticle" %}" method="post" enctype='multipart/form-data'>
    {% csrf_token %}

    <div class="form-group">TITRE
      {{ form.titre.errors }}
      {{ form.titre }}
    </div>
    <div class="form-group">SUMMARY
      {{ form.media }}
      {{ form.summary.errors }}
      {{ form.summary }}
    </div>
    <div class="form-group">CONTENU
      {{ form.media }}
      {{ form.contenu.errors }}
      {{ form.contenu }}
    </div>
    <div class="form-group">
      {{ form.image.errors }}
      {{ form.image }}
   </div>
   <div class="form-group">TAGS
      {{ form.tags.errors }}
      {{ form.tags }}
   </div>
   <input type="submit" class="btn btn-default" value="Submit" autocomplete="off" autocorrect="off" />
</form>

I'll post the full forms.py too, it may help.

forms.py

class ArticleForm(forms.ModelForm):

    def clean_titre(self):
        titre = self.cleaned_data['titre']
        if len(titre) < 5:
            raise ValidationError('myError')
        return titre

    class Meta:
        model = Article
        exclude = ['date', 'rating', 'user']

        widgets={
            "titre":forms.TextInput(attrs={'placeholder':'Le titre', 'class':'form-control'}),
            "contenu":forms.Textarea(attrs={'placeholder':'Le Contenu de votre message', 'class':'form-control'}),
            "image":forms.FileInput(attrs={'placeholder':'Votre Image', 'id':'uploadBtn'}),
            "tags":TagWidget(attrs={'placeholder':'Vos Tags', 'class':'form-control'}),
        }

form = ArticleForm()
3
  • Where's the rest of that view? What happens if is_valid is not True? Or if it's not a POST? Commented Jul 25, 2015 at 19:46
  • I don't have the rest, I didn't know I needed one, what should I write it the "else:"? Commented Jul 25, 2015 at 19:50
  • In that case you would definitely get an exception, because every view must return a response. If your form is not valid but you are not getting an exception, you cannot be using this view at all. Commented Jul 25, 2015 at 19:52

1 Answer 1

4

You are missing the else portion within your view. Here is the general flow of what forms usually do:

  1. Users navigate to a page via GET which presents them with a form
  2. Users fill in the form and submit it by using POST
  3. If the form is valid, users are directed to a different page
  4. If the form is not valid, users are presented with the same page as in step 1 with the validation errors displayed. After users correct them, they are process to step 2.

Here is that flow in django view:

def AddArticle(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST, request.FILES)
        if form.is_valid():
            save_it = form.save(commit=False)
            save_it.user = request.user
            save_it.save()
            form.save_m2m()
            return HttpResponseRedirect('/')

    else:
       form = ArticleForm()

    return render(request, 'template.html', {'form': form'})

I would however look into using class based views in Django. Initially they can seem very confusing but over time you will learn to appreciate them. Docs. Another useful resource when learning CBV.

By using CBV, the above can be simplified to:

class AddArticleView(CreateView):
    success_url = 'name_of_view_here'
    form_class = ArticleForm
    template_name = 'template.html'

# urls.py
urlpatterns = patterns('', url(r'^articles/add/$', AddArticleView.as_view()))

Template

You also need to include the overall form error in the template, in addition to each field errors:

<form class="form" action="{% url "article.views.AddArticle" %}" method="post" enctype='multipart/form-data'>
    {% csrf_token %}
    {{ form.non_field_errors }}
    ...
</form>

Please note that you might need to wrap the errors with some bootstrap markup. More info in docs

Sign up to request clarification or add additional context in comments.

3 Comments

But the mystery is that the view couldn't possibly have worked the way it is now, so there is something OP is not telling us.
@Sia can you post your complete form template since currently you only posted template for a single form field
not sure as well. try debugging with ipdb to verify that form is indeed invalid and that errors are present in the view. if so, then a bug is in the template. if not, then bug could with with form or view

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.