.. .. META INFORMATION OF TRANSLATION .. .. $TranslationStatus: Done, waiting for revision $ .. $OriginalRevision: 11332 $ .. $TranslationAuthors: Robson Mendonça $ .. .. INFO OF THIS FILE (DO NOT EDIT! UPDATED BY SUBVERSION) .. .. $HeadURL$ .. $LastChangedRevision$ .. $LastChangedBy$ .. $LastChangedDate$ .. .. _ref-contrib-formtools-form-wizard: =========== Form wizard =========== .. module:: django.contrib.formtools.wizard :synopsis: Divide formulários em múltiplas páginas Web. O Django vem acompanhado uma aplicação opicional "form wizard" que divide :doc:`formulários ` em várias páginas Web. Ele mantém o estado num hash HTML de campos :samp:``, e os dados não são processados no lado do servidor até que a última parte do formulário seja submetida. Você pode querer usar isto com formulários muito compridos que seriam desagradáveis de se mostrar numa única página. A primeira página pode pedir ao usuário informações centrais, a segunda coisas menos importantes, e assim por diante. o termo "wizard" (em português "assistente") neste contexto, é `explicado na Wikipedia`_. .. _explicado na Wikipedia: http://en.wikipedia.org/wiki/Wizard_%28software%29 .. _forms: ../forms/ Como ele funciona ================= Aqui temos o fluxo de funcionamento básico de como um usuário poderia usar um wizard: 1. O usuário visita a primeira página do wizard, preenche o formulário e o submete. 2. O servidor valida os dados. Se eles forem inválidos, o formulário é mostrado novamente, com mensagens de erro. Se for válido, o servidor calcula um hash seguro dos dados e apresenta ao usuário o próximo formulário, poupando os dados validados e o hash em campos :samp:``. 3. Repete o passo 1 e 2, para todos os formulários subsequentes do wizard. 4. Um vez que o usuário tenha submetido todos os formulários e todos os dados estejam validados, o wizard processa os dados -- salvando-os no banco de dados, enviando um e-mail, ou seja lá o que for que a aplicação precise fazer. Uso === Esta aplicação manipula tantos mecanismos para você quanto possível. Geralmente, você só tem que fazer estas coisas: 1. Definir um número de classes :class:`~django.forms.Form` -- uma por página do wizard. 2. Criar uma classe :class:`FormWizard` que especifica o que fazer uma vez que todos os seus formulários foram submetidos e validados. Isso também permite você sobrescrever alguns comportamentos do wizard. 3. Criar alguns templates que renderizam formulários. Você pode definir um único template genérico para manipular todos os formulários, ou definir um template específico para cada formulário. 4. Apontar seu URLconf para sua classe :class:`FormWizard`. Definindo classes ``Form`` ========================== o primeiro passo para criar um "form wizard" é criar as classes :class:`~django.forms.forms.Form`. Estes devel ser classses :class:`django.forms.Form` padrão conforme explicado na :doc:`documentação do forms `. Estas classes podem estar em qualquer lugar de sua base de código, mas por convenção são postas num arquivo chamado :file:`forms.py` dentro da sua aplicação. Por exemplo, vamos escrever um wizard "contact form", onde a primeira página coleta o endereço de email do remetente e o assunto, e a segunda página coleta a mensagem em si. Aqui tem um exemplo de como o :file:`forms.py` pode ficar:: from django import forms class ContactForm1(forms.Form): subject = forms.CharField(max_length=100) sender = forms.EmailField() class ContactForm2(forms.Form): message = forms.CharField(widget=forms.Textarea) **Limitação importante:** Pelo wizard usar campos HTML hidden para armazenar dados entre as páginas, você não pode incluir um :class:`~django.forms.fields.FileField` em qualquer outra página, a não ser na última. Criando uma classe ``FormWizard`` ================================= O próximo passo é criar uma classe :class:`~django.contrib.formtools.wizard.FormWizard`, que deveria ser uma subclasse do ``django.contrib.formtools.wizard.FormWizard``. Assim como suas classes :class:`~django.forms.forms.Form`, esta classe :class:`~django.contrib.formtools.wizard.FormWizard` pode estar em qualquer lugar da sua base de código, mas por convenção é colocado no :file:`forms.py`. O único requerimento desta subclasse é que ela implementa um método :meth:`~django.contrib.formtools.wizard.FormWizard.done()`, que especifica o que deve acontecer quando *todos* os formulários foram submetidos e validados. A este método é passado dois argumentos: * ``request`` -- um objeto :class:`~django.http.HttpRequest` * ``form_list`` -- uma lista de classes :mod:`django.forms` :class:`~django.forms.forms.Form` Neste exemplo simplista, ao invés de executar qualquer operação de banco de dados, o método simplesmente renderiza um template com os dados validados:: from django.shortcuts import render_to_response from django.contrib.formtools.wizard import FormWizard class ContactWizard(FormWizard): def done(self, request, form_list): return render_to_response('done.html', { 'form_data': [form.cleaned_data for form in form_list], }) Note que este método será chamado via ``POST``, então ele realmente deveria ser um bom cidadão Web e redirecionar depois de processar os dados. Aqui tem outro exemplo:: from django.http import HttpResponseRedirect from django.contrib.formtools.wizard import FormWizard class ContactWizard(FormWizard): def done(self, request, form_list): do_something_with_the_form_data(form_list) return HttpResponseRedirect('/page-to-redirect-to-when-done/') Veja a seção `Métodos avançados do FormWizard`_ abaixo para aprender mais sobre os hooks do :class:`~django.contrib.formtools.wizard.FormWizard`. Criando templates para formulários ================================== Agora, precisamos criar um template que renderize os forumlários do wizard. Por padrão, todo formulário usa um template chamado :file:`forms/wizard.html`. (Você pode mudar este nome sobrescrevendo o método :meth:`~django.contrib.formtools.wizard..get_template()`, que está documentado abaixo. Este hook também permite você usar um template diferente para cada formulário.) Este template aguarda o seguinte contexto: * ``step_field`` -- O nome do campo hidden contento o passo. * ``step0`` -- O passo atual (partindo de zero). * ``step`` -- O passo atual (partindo de um). * ``step_count`` -- O total de passos. * ``form`` -- A instância do :class:`~django.forms.forms.Form` para o passo atual (vazio ou com erros). * ``previous_fields`` -- Uma string representando todos os campos de dados anteriores, mais os hashes de formulários completados, todos em campos hidden de formulário. Note que você precisará executar isto através do template filter :meth:`~django.template.defaultfilters.safe`, para previnir o auto escape, por ele é um HTML puro. Ele também será transmitido a quaisquer objetos no :data:`extra_context`, que é um dicionário que você pode especificar contendo valores extra a serem adicionados ao contexto. Você pode especificá-lo de duas formas: * Sete o atributo :attr:`~django.contrib.formtools.wizard.FormWizard.extra_context` na sua subclasse :class:`~django.contrib.formtools.wizard.FormWizard` para um dicionário. * Passe :attr:`~django.contrib.formtools.wizard.FormWizard.extra_context` como parâmetros extra no URLconf. Aqui tem um exemplo de template completo: .. code-block:: html+django {% extends "base.html" %} {% block content %}
Step {{ step }} of {{ step_count }}
{% endblock %} Note que ``previous_fields``, ``step_field`` e ``step0`` são todos obrigatórios para o wizard funcionar perfeitamente. Ligando o wizard num URLconf ============================ Finalmente, dê ao seu novo objeto :class:`~django.contrib.formtools.wizard.FormWizard` uma URL no ``urls.py``. O wizard recebe uma lista de seus objetos form como argumentos:: from django.conf.urls.defaults import * from mysite.testapp.forms import ContactForm1, ContactForm2, ContactWizard urlpatterns = patterns('', (r'^contact/$', ContactWizard([ContactForm1, ContactForm2])), ) Métodos avançados do FormWizard =============================== .. class:: FormWizard Além do método :meth:`~django.contrib.formtools.wizard.FormWizard.done()`, o :class:`~django.contrib.formtools.wizard.FormWizard` oferece alguns métodos avançados que permitem você customizar o funcionamento do seu wizard. Alguns destes métodos recebem um argumento ``step``, que é um contador, partindo de zero, representando o passo corrente do wizard. (E.g., o primeiro form é ``0`` e o segundo form é ``1``.) .. method:: FormWizard.prefix_for_step Dado um passo, retorna um prefixo de :class:`~django.forms.forms.Form` para uso. Por padrão, este simplesmente usa o passo em si. Para mais, veja a :ref:`documentação do prefixo de formulário