Se você já tentou implementar um formulário dividido em vários passos com certeza já encontrou problemas provavelmente em manter todos os dados ou não perder os dados digitados nos passos anteriores após validação dos dados novos.
Esqueça às dores de cabeça, na versão 1.0 do Django foi lançanda a Form Wizard, ferramenta que tem como objetivo facilitar a criação de formulários com vários passos.
Vamos a um exemplo funcional com FormWizard, para isso eu criei um projeto chamado “templo” e uma aplicação chamada “mago”, dentro da minha aplicação eu criei o arquivo forms.py com o seguinte código:
from django import forms from django.contrib.formtools.wizard import FormWizard from django.shortcuts import render_to_response class Pessoa(forms.Form): nome = forms.CharField(max_length=50) email = forms.EmailField() class Mensagem(forms.Form): assunto = forms.CharField(max_length=30) mensagem = forms.CharField(widget=forms.widgets.Textarea) class Formumago(FormWizard): def done(self, request, form_list): form_data = {} for form in form_list: for field, value in form.cleaned_data.iteritems(): form_data[field] = value return render_to_response('agradecimento.html', { 'form_data': form_data, })
A primeira classe Pessoa é um formulário normal como todos os outros em Django com o dados da pessoa que está enviando a mensagem, a segunda classe Mensagem é outro formulário normal com os dados da mensagem, já o Formumago é um formulário especial que herda de FormWizard e tem uma função implementada done que possui o paramêtro form_list além dos comuns self e request e que é chamada após o usuário validar todos os passos.
Depois explicaremos melhor a função done vamos agora para o urls.py para fazer nossa aplicação exemplo funcionar:
from django.conf.urls.defaults import * from templo.mago.forms import Pessoa, Mensagem, Formumago urlpatterns = patterns('', (r'^contato/$', Formumago([Pessoa, Mensagem])), )
No arquivo urls.py acontece a magia onde criamos um formulário com dois passos o primeiro é o formulário de Pessoa e o segundo de Mensagem. Por padrão o FormWizard procura pelo template em “forms/wizard.html” mas você pode usar outro caminho definindo uma função get_template em Formumago como explicado na documentação.
E o arquivo “forms/wizard.html” que usaremos como template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <form action="." method="post">
<table border="0">
{% ifequal step 1 %}
<h1>Primeiro passo</h1>
<h2>Seus dados pessoais</h2>
{% endifequal %}
{% ifequal step 2 %}
<h1>Segundo e último passo</h1>
<h2>Dados da mensagem</h2>
{% endifequal %}
<input name="{{ step_field }}" type="hidden" value="{{ step0 }}" />
{{ previous_fields|safe }}
{{ form }}</table>
<input type="submit" value="Submit" />
</form> |
Como explicado na documentação o input na linha 12 e a variável previous_fields na linha 13 são necessárias para o funcionamento correto do FormWizard.
Temos também o template “agradecimento.html” mencionado no método done da classe Formumago e que exibe os dados que o usuário digitou:
<h1>Obrigado pelo contato</h1>
<h2>Sua mensagem foi enviada com os seguintes dados</h2>
<h3>Dados pessoais</h3>
<ul>
<li>Nome: {{ form_data.nome }}</li>
<li>Email: {{ form_data.email }}</li>
</ul>
<h3>Dados da mensagem</h3>
<ul>
<li>Assunto: {{ form_data.assunto }}</li>
<li>Mensagem: {{ form_data.mensagem }}</li>
</ul>Ao executar o servidor do Django e acessarmos a página de contato, obtemos o resultado:
O primeiro passo é exibido corretamente e se preencho algo errado a validação reclama prontamente.
Ao digitar os dados corretamente o segundo passo é exibido:
Novamente a validação do formulário funciona normalmente.
Por fim o método done de Formumago pega os valores limpos e passa ao template de agradecimento apenas com o intuito de mostrar que tipo de dado vem em form_list:
def done(self, request, form_list): form_data = {} for form in form_list: for field, value in form.cleaned_data.iteritems(): form_data[field] = value return render_to_response('agradecimento.html', { 'form_data': form_data, })
O conteúdo de form_list é uma lista de objetos que herdam de forms, algo do tipo [form1, form2] e cada formulário possui seus próprios métodos, save, clean, entre outros, no caso de done a informação válida digitada no formulário é iterada formando uma novo dicionário form_data com todos os campos preenchidos à serem exibidos na página de agradecimento.
Com isso fica fácil implementar formulários com múltiplos passos apenas aproveitando os formulários que já funcionam no projeto.



Muito bom, uma excelente contribuição para a comunidade Django!
Olá Danilo, obrigado pelo tutorial.
Um abraço.
Vlw cabello!
Tava precisando de algo parecido com isso!