Mutiple Forms With Class Based View. How to show errors on one page?

views.py

from forms.py import PersonCreateForm

class PersonCreateView(CreateView):
    model = Person
    form_class = PersonCreateForm
    template_name = "my_app/create_person.html"

    def form_valid(self, form):
        self.object = form.save()
        return redirect('/homepage/')


class PeopleListView(ListView):
        [...]
        context.update({
            'task_form': TaskCreateForm(),

        return context

      

In my template, I just add an action url that the PersonCreateView handles.

<form action="{% url 'people_create' %}" method="post">{% csrf_token %}

      

When the form is valid, all data is saved without issue and redirects me to the page / main page. But when my form is invalid it redirects me to {% url 'people_create' %}

and shows errors to / homepage / people _create /

How can I avoid this? I want all errors to be displayed on one page without redirecting.

+3


source to share


1 answer


Process the form in the same view that you create it, otherwise the page will change. You can mix django.views.generic.edit.ModelFormMixin

into PeopleListView

yours so that it has most of the features you need.

class PeopleListView(ModelFormMixin, ListView):
    success_url = '/homepage/'  # should use reverse() here

    def get_context_data(self, **kwargs):
        # only add the form if it is not already given to us
        if not 'task_form' in kwargs:
            kwargs['task_form'] = self.get_form()
        return super(PeopleListView, self).get_context_data(**kwargs)

    def post(self, request, *args, **kwargs):
        # ListView won't have a post method, we define one
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)   # default behavior will save and redirect
        else:
            return self.form_invalid(form) # default behavior has to be overridden (see below)

    def form_invalid(self, form):
        # Whatever you wanna do. This example simply reloads the list
        self.object_list = self.get_queryset()
        context = self.get_context_data(task_form=form)
        return self.render_to_response(context)

      

There are three code paths there:



  • The initial display will load the list as usual, only an empty form will be added to the context.
  • On submitting valid input, a method is called form_valid

    that will be redirected to /homepage/

    .
  • When an invalid input is submitted, our overridden method is called form_invalid

    , which will render the page normally, except that the form will contain validation errors.

You can make the whole thing a little more persistent by using the caching property for the form, but then you start working with Django-provided views instead, and you can also just use the base class View

and implement all the logic yourself. I would stick with the Django views, but ymmv.

+1


source







All Articles