Cómo hacer un Formulario Wizard con Django

how-to-do-a-wizard-form-with-django

Muchas veces, tenemos un formulario con muchos campos y necesitamos usarlo, pero no queremos que los usuarios se aburran de llenar el formulario o que se detengan a la mitad del formulario y terminen saliendo del sitio web. Para evitar estas situaciones, puede dividir su formulario en tantos pasos como desee. Ahora, vamos a verificar qué necesitamos hacer con los formularios.

Primero, necesitamos configurar su proyecto. En este caso, vamos a usar Django y una librería llamada django-formtools.

Primero que todo, necesitamos instalar django-formtools:

pip install django-formtools

Luego, debemos añadir   add 'formtools' ta nuestra configuración INSTALLED_APPS :

INSTALLED_APPS = (
    'formtools',
)

Luego, continuaremos con la creación de los formularios. Cada paso debe tener un formulario. Si desea 3 pasos, deberá crear 3 formularios. En este caso solo queremos dos pasos, así que vamos a crear dos formularios:

from django import forms

class FormStepOne(forms.Form):
    name = forms.CharField(max_length=100)
    last_name = forms.CharField(max_length=100)
    phone = forms. CharField(max_length=100)
    email = forms.EmailField()

class FormStepTwo(forms.Form):
    job = forms.CharField(max_length=100)
    salary = forms.CharField(max_length=100)
    job_description = forms.CharField(widget=forms.Textarea)

Ahora, vamos a agregar la vista para nuestros formularios. Podemos usar las clases SessionWizardViewCookieWizardView. Esas clases están diseñadas para guardar la información en cada paso (como indican sus nombres, sesiones del lado del servidor y cookies del navegador respectivamente), en este caso vamos a utilizar un SessionWizardView  porque queremos almacenar la información del servidor del formulario:

from django.shortcuts import render
from .forms import FormStepOne, FormStepTwo
from formtools.wizard.views import SessionWizardView

class FormWizardView(SessionWizardView):
    template_name = "path/to/template"
    form_list = [FormStepOne, FormStepTwo]

    def done(self, form_list, **kwargs):
        return render(self.request, 'done.html', {
            'form_data': [form.cleaned_data for form in form_list],
        })

SessionWizardView necesita tener un método done(). Este método se llama cuando el usuario llena todos los formularios y todos los campos son válidos. En este método, puede procesar toda la información y guardarla. Finalmente, necesitamos una plantilla para representar nuestros formularios:
 

{% extends "base.html" %}
{% load i18n %}

{% block content %}
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form action="" method="post">
  {% csrf_token %}
  <table>
  {{ wizard.management_form }}
  {% if wizard.form.forms %}
    {{ wizard.form.management_form }}
    {% for form in wizard.form.forms %}
      {{ form }}
    {% endfor %}
  {% else %}
    {{ wizard.form }}
  {% endif %}
  </table>
  {% if wizard.steps.prev %}
  <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">{% trans "first step" %}</button>
  <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">{% trans "prev step" %}</button>
  {% endif %}
  <input type="submit" value="{% trans "submit" %}"/>
</form>
{% endblock %}

Todo se ve genial, ¿verdad? pero, ¿qué sucede si nuestro usuario dejó el sitio web antes de que se haya completado el formulario? Bueno, hay muchas soluciones para este problema. Una de ellas es que puede procesar cada paso después de que el usuario lo envíe. Puede hacerlo con el método process_step() o puede almacenar la información en sesiones. ¿Cómo hacerlo? Bueno, por defecto SessionWizardView almacena información en sesiones pero, ¿cómo puede restaurar esa información cuando el usuario accede nuevamente al formulario? Es posible, pero necesita sobrescribir el método get().

def get(self, request, *args, **kwargs):
    try:
        return self.render(self.get_form())
    except KeyError:
        return super().get(request, *args, **kwargs)

 

Con ese método, puede restaurar toda la información de sus formularios cuando el usuario acceda nuevamente para continuar llenándolos, pero debe definir si el usuario desea restaurar su información o si desea completar un nuevo formulario. Deberá editar ese código si desea admitir esta opción. Otra cosa que debe definir es: ¿cuánto tiempo desea que se almacene esa información? Bueno, puede configurar su vida con SESSION_COOKIE_AGE. Por defecto, SESSION_COOKIE_AGE se establece en 1209600 (2 semanas, en segundos), pero en el caso de que no desee que esa información se almacene durante 2 semanas, puede cambiar esa variable con otro valor que prefiera.

En conclusión, django-formtools nos ayuda a estructurar un formulario que puede ser largo y tedioso en un formulario simple con pasos, lo que aumenta la participación de nuestros usuarios. Si desea obtener más información al respecto, puede ir a la documentación oficial, aquí.