<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Danilo Cabello &#187; Django</title>
	<atom:link href="http://blog.danilocabello.com/etiqueta/django/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.danilocabello.com</link>
	<description>Barba, Cabello e bigode</description>
	<lastBuildDate>Sun, 18 Jul 2010 22:17:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1-alpha</generator>
		<item>
		<title>Debugando no Django com winpdb</title>
		<link>http://blog.danilocabello.com/arquivo/debugando-no-django-com-winpdb/</link>
		<comments>http://blog.danilocabello.com/arquivo/debugando-no-django-com-winpdb/#comments</comments>
		<pubDate>Sat, 26 Sep 2009 00:11:07 +0000</pubDate>
		<dc:creator>Danilo Cabello</dc:creator>
				<category><![CDATA[Sem categoria]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[pdb]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[winpdb]]></category>

		<guid isPermaLink="false">http://blog.danilocabello.com/?p=325</guid>
		<description><![CDATA[Continuando o post anterior[1], além do pdb[2] que é totalmente via linha de comando, há o winpdb[3] que possui uma interface gráfica para facilitar a depuração. Instalá-lo é muito fácil, se você possui easy_install é só executar: sudo easy_install winpdb &#8230; <a href="http://blog.danilocabello.com/arquivo/debugando-no-django-com-winpdb/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Continuando o <a href="http://blog.danilocabello.com/arquivo/debugando-no-django/">post anterior</a>[1], além do <a href="http://docs.python.org/library/pdb.html">pdb</a>[2] que é totalmente via linha de comando, há o <a href="http://winpdb.org/">winpdb</a>[3] que possui uma interface gráfica para facilitar a depuração.</p>
<p>Instalá-lo é muito fácil, se você possui <code>easy_install</code> é só executar:</p>
<pre class="brush: bash;">
sudo easy_install winpdb
</pre>
<p>Se você não tem <code>easy_install</code>, mas tem <code>apt-get</code>:</p>
<pre class="brush: bash;">
sudo apt-get install winpdb
</pre>
<p>Se você não tem nada disso ainda dá pra baixar pelo <a href="http://winpdb.org/">site</a>[3] e funciona no Windows também, mas eu não testei.</p>
<p>Usarei como exemplo o código criado pelo <a href="http://blog.danilocabello.com/arquivo/debugando-no-django/">post anterior</a>, é um projeto bem simples com apenas uma view para atestar o poder do debug.</p>
<p>Lembra da nossa view, ela é simples assim:</p>
<pre class="brush: python;">
def hello(request):
    a = 2
    b = 3
    c = [1,2,3]
    c.pop()
    d = soma(3,4)
    response = HttpResponse(&quot;Hello World&quot;)
    return response
</pre>
<p>Como o <code>winpdb</code> possui a funcionalidade de adicionar <em>breakpoints</em> eu tirei aquele código de debug do <code>pdb</code> senão eles conflitariam entre si.</p>
<p>Abra o <code>winpdb</code>:</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/01.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/01-300x173.png" alt="winpdb" title="winpdb" width="300" height="173" class="aligncenter size-medium wp-image-327" /></a></p>
<p>A interface dele é bem simples, ficará mais clara quando estivermos executando alguma coisa.</p>
<p>Vá até <code>File->Launch</code> e na janela aberta escolha o <code>manage.py</code> do projeto que vamos depurar, por fim adicione <code>runserver --noreload</code> no comando e então clique em <code>OK</code> para iniciar o servidor.</p>
<p>O seu <code>winpdb</code> deve ficar parecido com a imagem abaixo, além de um terminal que será aberto pelo próprio <code>winpdb</code>.</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/02.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/02-300x173.png" alt="winpdb executando django runserver --noreload" title="winpdb executando django runserver --noreload" width="300" height="173" class="aligncenter size-medium wp-image-328" /></a></p>
<p>Antes de continuar qualquer coisa, vá até <code>File->Open Source</code> e na janela aberta escolha o arquivo <code>views.py</code>, adicione um <em>breakpoint</em> na linha <code>a = 2</code> clicando à direita do número da linha. Tente acessar a URL que executa a <em>view</em> <code>hello</code> e volte ao <code>winpdb</code>, você verá algo como abaixo (a diferença é que eu já andei duas linhas no código):</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/03.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/03-300x173.png" alt="winpdb na view hello" title="winpdb na view hello" width="300" height="173" class="aligncenter size-medium wp-image-329" /></a></p>
<p>Essa imagem é bem interessante pois mostra valores das variáveis, um console escondido abaixo do código, o arquivo em que o <em>debugger</em> se encontra, controles de avanço do <em>debug</em>, etc.</p>
<p>Avance com <code>Control->Next</code> até a chamada de <code>soma</code> e entre com <code>Control->Step Into</code>, avance duas linhas e você ficará assim:</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/04.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/04-300x173.png" alt="winpdb na função soma" title="winpdb na função soma" width="300" height="173" class="aligncenter size-medium wp-image-330" /></a></p>
<p>As variáveis do escopo local mudaram, o <em>debugger</em> continua no <code>views.py</code> mas agora dentro da função <code>soma</code>, dê <code>Control->Return</code> para ir até antes da função retornar pro escopo de <code>hello</code>.</p>
<p>Com <code>Control->Next</code> vá até antes da linha que executa <code>return response</code> e vamos brincar um pouco com o console que se encontra abaixo do código-fonte:</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/05.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/05-300x173.png" alt="winpdb e o console" title="winpdb e o console" width="300" height="173" class="aligncenter size-medium wp-image-331" /></a></p>
<p>Como você pode ver na imagem, o comando <code>v</code> (de <em>eval</em>) seguido de uma expressão retorna o valor da expressão, já o comando <code>x</code> (de <em>exec</em>) seguido de uma expressão executa a expressão informada.</p>
<p>Vamos fazer igual ao <a href="http://blog.danilocabello.com/arquivo/debugando-no-django/">post anterior</a> e verificar as propriedades de <code>response</code>:</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/06.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/06-300x173.png" alt="winpdb e o console alterando a response" title="winpdb e o console alterando a response" width="300" height="173" class="aligncenter size-medium wp-image-332" /></a></p>
<p>Na imagem acima, executamos um <code>dir</code> na variável <code>response</code>, exibimos seu <code>content</code> com <code>v</code>, alteramos o <code>content</code> com <code>x</code> e por fim com <code>Control->Go</code> visualizamos o resultado no navegador:</p>
<p><a href="http://blog.danilocabello.com/wp-content/uploads/2009/09/07.png"><img src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2009/09/07-300x170.png" alt="resultado final no navegador" title="resultado final no navegador" width="300" height="170" class="aligncenter size-medium wp-image-333" /></a></p>
<p>Para saber de mais funcionalidades que o <code>winpdb</code> pode te oferecer dê uma olhada no <a href="http://winpdb.org/cgi-bin/moin.cgi/WinpdbTutorial">tutorial</a>[4] (bem completo por sinal) que se encontra na própria <a href="http://winpdb.org/cgi-bin/moin.cgi/FrontPage">wiki</a>[5] deles.</p>
<p>[1] &#8211; <a href="http://blog.danilocabello.com/arquivo/debugando-no-django/">http://blog.danilocabello.com/arquivo/debugando-no-django/</a><br />
[2] &#8211; <a href="http://docs.python.org/library/pdb.html">http://docs.python.org/library/pdb.html</a><br />
[3] &#8211; <a href="http://winpdb.org/">http://winpdb.org/</a><br />
[4] &#8211; <a href="http://winpdb.org/cgi-bin/moin.cgi/WinpdbTutorial">http://winpdb.org/cgi-bin/moin.cgi/WinpdbTutorial</a><br />
[5] &#8211; <a href="http://winpdb.org/cgi-bin/moin.cgi/FrontPage">http://winpdb.org/cgi-bin/moin.cgi/FrontPage</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.danilocabello.com/arquivo/debugando-no-django-com-winpdb/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Debugando no Django</title>
		<link>http://blog.danilocabello.com/arquivo/debugando-no-django/</link>
		<comments>http://blog.danilocabello.com/arquivo/debugando-no-django/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 03:45:20 +0000</pubDate>
		<dc:creator>Danilo Cabello</dc:creator>
				<category><![CDATA[Sem categoria]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[pdb]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.danilocabello.com/?p=311</guid>
		<description><![CDATA[Bem que você tentou, releu o código diversas vezes, escreveu um monte de prints, mas não conseguiu descobrir o que está causando aquele bug indesejado. É chegada a hora de debugar seu código, a seguir darei algumas dicas de como &#8230; <a href="http://blog.danilocabello.com/arquivo/debugando-no-django/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Bem que você tentou, releu o código diversas vezes, escreveu um monte de <em>prints</em>, mas não conseguiu descobrir o que está causando aquele bug indesejado. É chegada a hora de debugar seu código, a seguir darei algumas dicas de como debugar com pdb seu projeto em Django<a href="http://www.djangoproject.com/">[1]</a>.</p>
<p>Primeiramente, debugar um projeto em Python<a href="http://www.python.org/">[2]</a> e debugar um projeto em Django não tem muita diferença, a coisa toda é muito parecida, você só precisa do pontapé inicial para se virar dali pra frente.</p>
<p>Para aprender como utilizar o pdb<a href="http://docs.python.org/library/pdb.html">[3]</a> (vulgo Python Debugger) crie um novo projeto chamado <code>djdebug</code>, logo em seguida crie um arquivo vazio chamado <code>views.py</code> na própria raiz do projeto, ficando com a seguinte estrutura de arquivos:</p>
<pre>
djdebug
  - __init__.py
  - manage.py
  - settings.py
  - urls.py
  - views.py
</pre>
<p>No arquivo <code>views.py</code> cole o seguinte código:</p>
<pre class="brush: python;">
from django.shortcuts import HttpResponse

def soma(a,b):
    arg1 = a
    arg2 = b
    soma = arg1 + arg2
    return soma

def hello(request):
    a = 2
    b = 3
    c = [1,2,3]
    c.pop()
    d = soma(3,4)
    response = HttpResponse(&quot;Hello World&quot;)
    return response
</pre>
<p>Como podemos ver o arquivo contém uma função <code>soma</code>, que não faz nada de muito complexo e uma função <code>hello</code> que retorna uma response com o conteúdo <code>"Hello World"</code>.</p>
<p>No arquivo <code>urls.py</code> importe a view <code>hello</code> e adicione uma URL para podemos acessá-la:</p>
<pre class="brush: python;">
from views import hello

urlpatterns = patterns('',
    ...
    (r'^hello', hello),
)
</pre>
<p>Execute o servidor de testes, navegue até <code>http://localhost:8000/hello</code> e verifique que está tudo funcionando:</p>
<pre class="brush: bash;">
./manage runserver
</pre>
<p>Suponha que há um bug em alguma parte da view <code>hello</code> e então adicione o código para possibilitar o debug:</p>
<pre class="brush: python;">
def hello(request):
    a = 2
    import pdb
    pdb.set_trace()
    ...
</pre>
<p>Apenas para esclarecer, o <code>import pdb</code> importa o Python debugger, já o <code>pdb.set_trace()</code> serve pra colocar um breakpoint no código, há maneiras de se colocar um breakpoint no código sem alterá-lo através do próprio pdb<a href="http://docs.python.org/library/pdb.html">[3]</a>.</p>
<p>Execute o servidor de testes mas desta vez adicione o parâmetro necessário para evitar recarregamento automático do código-fonte:</p>
<pre class="brush: bash;">
./manage runserver --noreload
</pre>
<p>Abra novamente a view <code>hello</code> no seu navegador, ela ficará parada e no terminal que você iniciou o servidor o pdb<a href="http://docs.python.org/library/pdb.html">[3]</a> estará parado esperando por comandos:</p>
<pre class="brush: python;">
&gt; /home/.../djdebug/views.py(13)hello()
-&gt; b = 3
(Pdb)
</pre>
<p>Vamos começar, temos um comando interessante que é o <code>l</code> (de <em>list</em>, lista o código na região do debugger) que lista onde se encontra o debugger:</p>
<pre class="brush: python;">
(Pdb) l
  8
  9  	def hello(request):
 10  	    a = 2
 11  	    import pdb
 12  	    pdb.set_trace()
 13      -&gt;  b = 3
 14  	    c = [1,2,3]
 15  	    c.pop()
 16  	    d = soma(3,4)
 17  	    response = HttpResponse(&quot;Hello World&quot;)
 18  	    return response
</pre>
<p>É importante notar que o debugger se encontra no exato momento <strong>antes</strong> de executar a linha apontada pela seta, isto é, se executarmos <code>p</code> (de <em>print</em>, imprime a expressão passada como argumento) para inspecionarmos a variável <code>b</code>, ela não estará definida:</p>
<pre class="brush: python;">
(Pdb) p a
2
(Pdb) p b
*** NameError: NameError(&quot;name 'b' is not defined&quot;,)
</pre>
<p>Vamos para próxima linha com <code>n</code> (de <em>next</em>, segue para a próxima linha):</p>
<pre class="brush: python;">
(Pdb) n
&gt; /home/.../djdebug/views.py(14)hello()
-&gt; c = [1,2,3]
(Pdb) p b
3
</pre>
<p>Agora sim <code>b</code> já possui valor, vamos avançar até a chamada da função <code>somar</code>:</p>
<pre class="brush: python;">
(Pdb) n
&gt; /home/.../djdebug/views.py(15)hello()
-&gt; c.pop()
(Pdb) &lt;enter&gt;
&gt; /home/.../djdebug/views.py(16)hello()
-&gt; d = soma(3,4)
</pre>
<p>A partir do primeiro <code>n</code>, <code>enter</code> executará <code>n</code> novamente. Como nós não sabemos se o problema da view <code>hello</code> é a função <code>somar</code>, vamos entrar na função somar com <code>s</code> (de <em>step into</em>, entra na função, ou seja, passo a dentro) e verificar se está tudo certo:</p>
<pre class="brush: python;">
(Pdb) s
--Call--
&gt; /home/.../djdebug/views.py(3)soma()
-&gt; def soma(a,b):
(Pdb) l
  1  	  from django.shortcuts import HttpResponse
  2
  3     -&gt; def soma(a,b):
  4  	      arg1 = a
  5  	      arg2 = b
  6  	      soma = arg1 + arg2
  7  	      return soma
  8
  9  	  def hello(request):
 10  	      a = 2
 11  	      import pdb
</pre>
<p>Como podemos ver o debugger se encontra na entrada da função <code>soma</code>, damos uma &#8220;olhada por cima&#8221; e saímos da função com <code>up</code> (de up, sobe uma chamada na pilha):</p>
<pre class="brush: python;">
&gt; /home/.../djdebug/views.py(4)soma()
-&gt; arg1 = a
(Pdb) n
&gt; /home/.../djdebug/views.py(5)soma()
-&gt; arg2 = b
(Pdb) n
&gt; /home/.../djdebug/views.py(6)soma()
-&gt; soma = arg1 + arg2
(Pdb) u
&gt; /home/.../djdebug/views.py(16)hello()
-&gt; d = soma(3,4)
</pre>
<p>Como podemos ver, voltamos a view <code>hello</code>, vamos avançar até antes de retornar a resposta da requisição e atestar umas coisinhas:</p>
<pre class="brush: python;">
(Pdb) n
&gt; /home/.../djdebug/views.py(17)hello()
-&gt; response = HttpResponse(&quot;Hello World&quot;)
(Pdb) n
&gt; /home/.../djdebug/views.py(18)hello()
-&gt; return response
(Pdb) dir(response)
['__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_charset', '_container', '_convert_to_ascii', '_get_content', '_headers', '_is_string', '_set_content', 'close', 'content', 'cookies', 'delete_cookie', 'flush', 'get', 'has_header', 'items', 'next', 'set_cookie', 'status_code', 'tell', 'write']
(Pdb) response.content
'Hello World'
(Pdb) response.content = 'Django debugado'
(Pdb) c
</pre>
<p>Como podemos verificar, o pdb<a href="http://docs.python.org/library/pdb.html">[3]</a> fornece um shell do Python<a href="http://www.python.org/">[2]</a> você pode executar <code>dir</code>, verificar valores de variáveis e até mudar conteúdo de variáveis (poder e perigo andando juntos), por fim executamos <code>c</code> (de <em>continue</em>, para continuar a execução), veja o resultado no seu navegador, a mensagem <code>"Hello World"</code> foi trocada por <code>"Django debugado"</code>.</p>
<p>Recomendo a leitura do paper &#8220;Debugging in Python&#8221;<a href="http://www.ferg.org/papers/debugging_in_python.html">[4]</a> para mais alguns detalhes do pdb<a href="http://docs.python.org/library/pdb.html">[3]</a>. É muito interessante saber &#8220;brincar&#8221; com o shell do Python e do Django, com essas ferramentas fica mais fácil rastrear o chato do bug.</p>
<p>[1] -<a href="http://www.djangoproject.com/"> http://www.djangoproject.com/</a><br />
[2] &#8211; <a href="http://www.python.org/">http://www.python.org/</a><br />
[3] &#8211; <a href="http://docs.python.org/library/pdb.html">http://docs.python.org/library/pdb.html</a><br />
[4] &#8211; <a href="http://www.ferg.org/papers/debugging_in_python.html">http://www.ferg.org/papers/debugging_in_python.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.danilocabello.com/arquivo/debugando-no-django/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>django-registration faciltando o cadastro de usuários</title>
		<link>http://blog.danilocabello.com/arquivo/django-registration-faciltando-o-cadastro-de-usuarios/</link>
		<comments>http://blog.danilocabello.com/arquivo/django-registration-faciltando-o-cadastro-de-usuarios/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 01:33:05 +0000</pubDate>
		<dc:creator>Danilo Cabello</dc:creator>
				<category><![CDATA[Sem categoria]]></category>
		<category><![CDATA[Django]]></category>

		<guid isPermaLink="false">http://blog.danilocabello.com/?p=305</guid>
		<description><![CDATA[Estava procurando por uma forma de bloquear e-mails duplicados no django.contrib.auth[1], eis que encontro o projeto &#8220;plugável&#8221; django-registration[2] que não só implementa essa funcionalidade como e-mails de confirmação e a confirmação ainda expira conforme um número de dias definido nas &#8230; <a href="http://blog.danilocabello.com/arquivo/django-registration-faciltando-o-cadastro-de-usuarios/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Estava procurando por uma forma de bloquear e-mails duplicados no <code>django.contrib.auth</code><a href="http://docs.djangoproject.com/en/dev/topics/auth/#topics-auth">[1]</a>, eis que encontro o projeto &#8220;plugável&#8221; <code>django-registration</code><a href="http://bitbucket.org/ubernostrum/django-registration/">[2]</a> que não só implementa essa funcionalidade como e-mails de confirmação e a confirmação ainda expira conforme um número de dias definido nas suas <code>settings.py</code>.</p>
<p>A aplicação é muito completa, possui testes e exige o mínimo de conhecimento em Django que é saber criar templates. Ao baixar a aplicação eu pensei que iria ter que adaptar um monte de coisa para se encaixar na minha aplicação, que nada, a aplicação está no limite da plugabilidade que o Django investe.</p>
<p>Give a try.</p>
<p>[1] &#8211; <a href="http://docs.djangoproject.com/en/dev/topics/auth/#topics-auth">http://docs.djangoproject.com/en/dev/topics/auth/#topics-auth</a><br />
[2] &#8211; <a href="http://bitbucket.org/ubernostrum/django-registration/">http://bitbucket.org/ubernostrum/django-registration/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.danilocabello.com/arquivo/django-registration-faciltando-o-cadastro-de-usuarios/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Form Wizard: formulários passo a passo com Django</title>
		<link>http://blog.danilocabello.com/arquivo/form-wizard-formularios-passo-a-passo-com-django/</link>
		<comments>http://blog.danilocabello.com/arquivo/form-wizard-formularios-passo-a-passo-com-django/#comments</comments>
		<pubDate>Fri, 05 Dec 2008 17:14:35 +0000</pubDate>
		<dc:creator>Danilo Cabello</dc:creator>
				<category><![CDATA[Sem categoria]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.danilocabello.com/?p=107</guid>
		<description><![CDATA[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 &#8230; <a href="http://blog.danilocabello.com/arquivo/form-wizard-formularios-passo-a-passo-com-django/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>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.</p>
<p>Esqueça às dores de cabeça, na versão 1.0 do <a href="http://www.djangoproject.com" target="_blank">Django</a> foi lançanda a <a href="http://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/" target="_blank">Form Wizard</a>, ferramenta que tem como objetivo facilitar a criação de formulários com vários passos.</p>
<p>Vamos a um exemplo funcional com FormWizard, para isso eu criei um projeto chamado &#8220;templo&#8221; e uma aplicação chamada &#8220;mago&#8221;, dentro da minha aplicação eu criei o arquivo <code>forms.py</code> com o seguinte código:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django <span style="color: #ff7700;font-weight:bold;">import</span> forms
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">formtools</span>.<span style="color: black;">wizard</span> <span style="color: #ff7700;font-weight:bold;">import</span> FormWizard
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">shortcuts</span> <span style="color: #ff7700;font-weight:bold;">import</span> render_to_response
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Pessoa<span style="color: black;">&#40;</span>forms.<span style="color: black;">Form</span><span style="color: black;">&#41;</span>:
    nome = forms.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">50</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">email</span> = forms.<span style="color: black;">EmailField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Mensagem<span style="color: black;">&#40;</span>forms.<span style="color: black;">Form</span><span style="color: black;">&#41;</span>:
    assunto = forms.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">30</span><span style="color: black;">&#41;</span>
    mensagem = forms.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>widget=forms.<span style="color: black;">widgets</span>.<span style="color: black;">Textarea</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Formumago<span style="color: black;">&#40;</span>FormWizard<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> done<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request, form_list<span style="color: black;">&#41;</span>:
        form_data = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> form <span style="color: #ff7700;font-weight:bold;">in</span> form_list:
            <span style="color: #ff7700;font-weight:bold;">for</span> field, value <span style="color: #ff7700;font-weight:bold;">in</span> form.<span style="color: black;">cleaned_data</span>.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
                form_data<span style="color: black;">&#91;</span>field<span style="color: black;">&#93;</span> = value
        <span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'agradecimento.html'</span>, <span style="color: black;">&#123;</span>
            <span style="color: #483d8b;">'form_data'</span>: form_data,
        <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>A primeira classe <code>Pessoa</code> é um formulário normal como todos os outros em Django com o dados da pessoa que está enviando a mensagem, a segunda classe <code>Mensagem</code> é outro formulário normal com os dados da mensagem, já o <code>Formumago</code> é um formulário especial que herda de FormWizard e tem uma função implementada <code>done</code> que possui o paramêtro <code>form_list</code> além dos comuns <code>self</code> e <code>request</code> e que é chamada após o usuário validar todos os passos.</p>
<p>Depois explicaremos melhor a função <code>done</code> vamos agora para o <code>urls.py</code> para fazer nossa aplicação exemplo funcionar:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span>.<span style="color: black;">urls</span>.<span style="color: black;">defaults</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">from</span> templo.<span style="color: black;">mago</span>.<span style="color: black;">forms</span> <span style="color: #ff7700;font-weight:bold;">import</span> Pessoa, Mensagem, Formumago
&nbsp;
urlpatterns = patterns<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>,
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^contato/$'</span>, Formumago<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>Pessoa, Mensagem<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
<span style="color: black;">&#41;</span></pre></div></div>

<p>No arquivo <code>urls.py</code> acontece a magia onde criamos um formulário com dois passos o primeiro é o formulário de <code>Pessoa</code> e o segundo de <code>Mensagem</code>. Por padrão o FormWizard procura pelo template em &#8220;forms/wizard.html&#8221; mas você pode usar outro caminho definindo uma função <code>get_template</code> em <code>Formumago</code> como explicado na documentação.</p>
<p>E o arquivo &#8220;forms/wizard.html&#8221; que usaremos como template:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;form action=&quot;.&quot; method=&quot;post&quot;&gt;
&lt;table border=&quot;0&quot;&gt;
    {% ifequal step 1 %}
        &lt;h1&gt;Primeiro passo&lt;/h1&gt;
        &lt;h2&gt;Seus dados pessoais&lt;/h2&gt;
    {% endifequal %}
&nbsp;
    {% ifequal step 2 %}
        &lt;h1&gt;Segundo e último passo&lt;/h1&gt;
        &lt;h2&gt;Dados da mensagem&lt;/h2&gt;
    {% endifequal %}
    &lt;input name=&quot;{{ step_field }}&quot; type=&quot;hidden&quot; value=&quot;{{ step0 }}&quot; /&gt;
    {{ previous_fields|safe }}
    {{ form }}&lt;/table&gt;
&lt;input type=&quot;submit&quot; value=&quot;Submit&quot; /&gt;
&lt;/form&gt;</pre></td></tr></table></div>

<p>Como explicado na <a href="http://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/" target="_blank">documentação</a> o <code>input</code> na linha 12 e a variável <code>previous_fields</code> na linha 13 são necessárias para o funcionamento correto do FormWizard.</p>
<p>Temos também o template &#8220;agradecimento.html&#8221; mencionado no método <code>done</code> da classe <code>Formumago</code> e que exibe os dados que o usuário digitou:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;h1&gt;Obrigado pelo contato&lt;/h1&gt;
&lt;h2&gt;Sua mensagem foi enviada com os seguintes dados&lt;/h2&gt;
&lt;h3&gt;Dados pessoais&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;Nome: {{ form_data.nome }}&lt;/li&gt;
	&lt;li&gt;Email: {{ form_data.email }}&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Dados da mensagem&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;Assunto: {{ form_data.assunto }}&lt;/li&gt;
	&lt;li&gt;Mensagem: {{ form_data.mensagem }}&lt;/li&gt;
&lt;/ul&gt;</pre></div></div>

<p>Ao executar o servidor do Django e acessarmos a página de contato, obtemos o resultado:</p>
<p style="text-align:center;"><a href="http://blog.danilocabello.com/wp-content/uploads/2008/12/formwizard-passo-1.png"><img class="aligncenter size-medium wp-image-117" title="FormWizard Passo 1" src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2008/12/formwizard-passo-1-300x210.png" alt="" width="300" height="210" /></a></p>
<p>O primeiro passo é exibido corretamente e se preencho algo errado a validação reclama prontamente.</p>
<p>Ao digitar os dados corretamente o segundo passo é exibido:</p>
<p style="text-align:center;"><a href="http://blog.danilocabello.com/wp-content/uploads/2008/12/formwizard-passo-2.png"><img class="aligncenter size-medium wp-image-118" title="FormWizard Passo 2" src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2008/12/formwizard-passo-2-300x210.png" alt="" width="300" height="210" /></a></p>
<p>Novamente a validação do formulário funciona normalmente.</p>
<p>Por fim o método <code>done</code> de <code>Formumago</code> pega os valores limpos e passa ao template de agradecimento apenas com o intuito de mostrar que tipo de dado vem em <code>form_list</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> done<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request, form_list<span style="color: black;">&#41;</span>:
        form_data = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> form <span style="color: #ff7700;font-weight:bold;">in</span> form_list:
            <span style="color: #ff7700;font-weight:bold;">for</span> field, value <span style="color: #ff7700;font-weight:bold;">in</span> form.<span style="color: black;">cleaned_data</span>.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
                form_data<span style="color: black;">&#91;</span>field<span style="color: black;">&#93;</span> = value
        <span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'agradecimento.html'</span>, <span style="color: black;">&#123;</span>
            <span style="color: #483d8b;">'form_data'</span>: form_data,
        <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>O conteúdo de <code>form_list</code> é uma lista de objetos que herdam de <code>forms</code>, algo do tipo <code>[form1, form2]</code> e cada formulário possui seus próprios métodos, <code>save</code>, <code>clean</code>, entre outros, no caso de <code>done</code> a informação válida digitada no formulário é iterada formando uma novo dicionário <code>form_data</code> com todos os campos preenchidos à serem exibidos na página de agradecimento.</p>
<p style="text-align:center;"><a href="http://blog.danilocabello.com/wp-content/uploads/2008/12/formwizard-agradecimento.png"><img class="aligncenter size-medium wp-image-120" title="FormWizard Agradecimento" src="http://blog.danilocabello.com/index.php?feedimage=wp-content/uploads/2008/12/formwizard-agradecimento-300x210.png" alt="" width="300" height="210" /></a></p>
<p>Com isso fica fácil implementar formulários com múltiplos passos apenas aproveitando os formulários que já funcionam no projeto.</p>
<p><a href='http://blog.danilocabello.com/wp-content/uploads/2008/12/templo.zip'>Baixe o projeto exemplo</a>.</p>
<ul>
<li><a href="http://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/" target="_blank">Documentação Form Wizard</a></li>
<li><a href="http://superjared.com/entry/formwizard-multiple-step-forms-django/" target="_blank">Inspiração e Fonte</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.danilocabello.com/arquivo/form-wizard-formularios-passo-a-passo-com-django/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
