<?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>Profissionais TI - Pra quem respira informação &#187; Django</title>
	<atom:link href="http://www.profissionaisti.com.br/tag/django/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.profissionaisti.com.br</link>
	<description>Pra quem respira informação</description>
	<lastBuildDate>Fri, 10 Feb 2012 16:02:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Ferramentas de testes em Django &#8211; Parte 2</title>
		<link>http://www.profissionaisti.com.br/2011/08/ferramentas-de-testes-em-django-parte-2/</link>
		<comments>http://www.profissionaisti.com.br/2011/08/ferramentas-de-testes-em-django-parte-2/#comments</comments>
		<pubDate>Fri, 12 Aug 2011 11:14:14 +0000</pubDate>
		<dc:creator>Klaus Peter Laube</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Utilidades]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Testes]]></category>

		<guid isPermaLink="false">http://www.profissionaisti.com.br/?p=18777</guid>
		<description><![CDATA[No post anterior, conhecemos as ferramentas default para construção de testes automatizados em Django. Acontece que você pode &#8220;sair um pouco da caixa&#8221; e usufruir de ferramentas &#8220;third-party&#8220;, que enriquecerão o seu ambiente de desenvolvimento e lhe trarão maior segurança em seus testes de software. splinter &#8211; Testando a sua aplicação com um navegador É [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;"><img class="alignleft size-full wp-image-18780" style="margin-left: 5px; margin-right: 5px;" title="boneco-testes" src="http://www.profissionaisti.com.br/wp-content/uploads/2011/08/boneco-testes.jpg" alt="" width="154" height="108" />No <a title="Ferramentas de testes em Django - Parte 1" href="http://www.klauslaube.com.br/2011/07/ferramentas-de-testes-em-django-parte-1/"><em>post </em>anterior</a>, conhecemos as ferramentas <em>default </em>para construção de testes automatizados em <em><a title="Leia mais sobre Django" href="http://www.profissionaisti.com.br/tag/django/">Django</a></em>. Acontece que você pode &#8220;sair um pouco da caixa&#8221; e usufruir de ferramentas &#8220;<em>third-party</em>&#8220;, que enriquecerão o seu ambiente de desenvolvimento e lhe trarão maior segurança em seus <a title="Leia mais sobre testes" href="http://www.profissionaisti.com.br/tag/testes/">testes de <em>software</em></a>.</p>
<h3 style="text-align: justify;"><em>splinter</em> &#8211; Testando a sua aplicação com um navegador</h3>
<p style="text-align: justify;">É perfeitamente possível criar testes de aceitação em<em> Django </em>com a <em><a title="Testando aplicações web com test client em Django" href="https://docs.djangoproject.com/en/dev/topics/testing/#module-django.test.client">TestClient</a> </em>e <em><a title="Faça parser XML e HTML com lxml" href="http://lxml.de/">lxml</a></em>. Mas vamos ser sinceros, é deveras trabalhoso &#8220;parsear&#8221; os resultados das suas <em>views</em>.</p>
<p style="text-align: justify;">Com a <em><a title="Visite a documentação oficial da Splinter" href="http://splinter.cobrateam.info/">Splinter</a></em>, uma ferramenta para testes de aplicações <em>web</em>, você pode automatizar ações executadas por navegadores, como visitar uma página, preencher um formulário ou clicar em um <em>link</em>; tudo isso sem preocupar-se com <em>parsing</em>, nós, <em>DOM</em>, nem nada do tipo:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> splinter.<span style="color: black;">browser</span> <span style="color: #ff7700;font-weight:bold;">import</span> Browser
browser = Browser<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># Visitar uma URL</span>
url = <span style="color: #483d8b;">&quot;http://search.twitter.com&quot;</span>
browser.<span style="color: black;">visit</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
browser.<span style="color: black;">fill</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'q'</span>, <span style="color: #483d8b;">&quot;#cobrateam&quot;</span><span style="color: black;">&#41;</span> 
&nbsp;
<span style="color: #808080; font-style: italic;"># Procurar e clicar no botão 'search'</span>
button = browser.<span style="color: black;">find_by_css</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;#searchButton input&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">first</span> 
&nbsp;
<span style="color: #808080; font-style: italic;"># Interagir com os elementos</span>
button.<span style="color: black;">click</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">if</span> browser.<span style="color: black;">is_text_present</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;No results for #cobrateam&quot;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;nobody likes us =(&quot;</span>
<span style="color: #ff7700;font-weight:bold;">else</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;we're popular =)&quot;</span></pre></div></div>

<p style="text-align: justify;">O que eu acho mais bacana nesta ferramenta são os seletores, facilitam muito na hora de checar resultados e comportamentos.</p>
<p style="text-align: justify;">A comunidade em volta desta ferramenta está em constante crescimento e atividade. Portanto, caso você queira contribuir com o projeto, vá agora mesmo para o <a title="Repositório da Splinter no GitHub" href="https://github.com/cobrateam/splinter">repositório no <em>GitHub </em>e colabore</a>.</p>
<h3 style="text-align: justify;"><em>nose</em> &#8211; Caçando testes em seu projeto (<em>Python</em>)</h3>
<p style="text-align: justify;">E quando queremos fugir da regra? Aposto que chegará um momento em que a estrutura de diretórios padrão, necessária para a execução dos seus testes em <em>Django</em>, não te satisfará mais. O que fazer neste caso? Simples, recorra ao <em>Nose</em>!</p>
<p style="text-align: justify;">O <em><a title="Nose - is nicer testing for Python" href="http://somethingaboutorange.com/mrl/projects/nose/1.0.0/">Nose</a> </em>estende os recursos da <em>unittest </em>e facilita a escrita e carregamento dos testes em projetos <em><a title="Leia mais sobre Python" href="http://www.profissionaisti.com.br/tag/python/">Python</a></em>. De uma forma mais detalhada, ele percorre o seu projeto (ou uma determinada região de seu escolha) executando subclasses da <em>unittest.TestCase </em>ou funções que contenham &#8220;<em>test&#8221;</em>. Por exemplo:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># test_subclasse.py</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> SubclasseTest<span style="color: black;">&#40;</span><span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> test_um_eh_verdadeiro<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># test_funcao.py</span>
<span style="color: #ff7700;font-weight:bold;">def</span> test_zero_eh_falso<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: #ff4500;">0</span> == <span style="color: #008000;">False</span></pre></div></div>

<p style="text-align: justify;">Ao executar o comando <em><strong>nosetests </strong></em>o <em>nose </em>se encarregará de procurar e carregar os testes:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ nosetests
..
<span style="color: #660033;">----------------------------------------------------------------------</span>
Ran <span style="color: #000000;">2</span> tests <span style="color: #000000; font-weight: bold;">in</span> 0.005s
&nbsp;
OK</pre></div></div>

<p style="text-align: justify;">É claro que existe uma &#8220;mágica&#8221; aí. Na verdade o <em>nose </em>pesquisará por arquivos <em>Python </em>com &#8220;<em>test</em>&#8221; em seu nome, por funções com &#8220;<em>test</em>&#8221; em seu enunciado, e por classes<em> </em>com métodos &#8220;<em>test</em>&#8221; em sua declaração. Ele age mesmo como um &#8220;<em>runner</em>&#8220;, tendo a capacidade de lidar com testes escritos com <em>unittest </em>ou não.</p>
<p style="text-align: justify;">Essa é só a ponta do <em>iceberg</em>. É possível construir <em>plugins </em>para o <em>nose</em>, permitindo melhorar ainda mais o seu ambiente de testes (como por exemplo, permitir que o <a title="Conheça o nosepipe" href="http://pypi.python.org/pypi/nosepipe/"><em>nose </em>funcione em <em>subprocess </em>separados</a>).</p>
<p style="text-align: justify;"><strong>Caçando testes em seu projeto (<em>Django</em>)</strong></p>
<p style="text-align: justify;">Para facilitar ainda mais a escrita de testes em <em>Django </em>existem <em>plugins </em>como o <em><a title="Utilize o nose em seus projetos Django" href="http://pypi.python.org/pypi/django-nose">django-nose</a></em>, que permite que você substitua o <em>Test Runner </em>padrão da <em>framework </em>por um específico que utiliza o <em>nose</em>, unindo assim a facilidade e &#8220;<em>add-ons</em>&#8221; do <em>nose </em>com o ambiente de testes do <em>Django</em>.</p>
<h3 style="text-align: justify;"><em>lettuce</em> - <em>BDD</em> em <em>Django</em></h3>
<p style="text-align: justify;">E se você estava se perguntando sobre <em><a title="Leia mais sobre BDD" href="http://www.profissionaisti.com.br/2010/01/bdd-desenvolvimento-orientado-a-comportamento/">BDD</a> </em>em <em>Django</em>, eu apresento a <em><a title="Saiba mais sobre a lettuce" href="http://lettuce.it/intro/overview.html#intro-overview">Lettuce</a></em>!</p>
<p style="text-align: justify;">Esta ferramenta, baseada na <em><a title="Cucumber - Making BDD fun" href="http://cukes.info/">Cucumber</a></em>, permite com que você escreva estórias utilizando linguagem ubíqua, mais próxima da área de negócios do que da área técnica, e automatize a validação delas.</p>
<p style="text-align: justify;">O mais bacana é que ela já vem preparada para o <em>Django</em>, permitindo que a gente execute os testes de comportamento de forma fácil e rápida:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">Feature: Rocking with lettuce and django
&nbsp;
    Scenario: Simple Hello World
        Given I access the url &quot;/&quot;
        Then I see the header &quot;Hello World&quot;
&nbsp;
    Scenario: Hello + capitalized name
        Given I access the url &quot;/some-name&quot;
        Then I see the header &quot;Hello Some Name&quot;</pre></div></div>

<p style="text-align: justify;" lang="python">Estória escrita, vamos escrever o <em>script Python </em>que validará se está tudo de acordo:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> lettuce <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">from</span> lxml <span style="color: #ff7700;font-weight:bold;">import</span> html
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: #dc143c;">test</span>.<span style="color: black;">client</span> <span style="color: #ff7700;font-weight:bold;">import</span> Client
&nbsp;
@before.<span style="color: #008000;">all</span>
<span style="color: #ff7700;font-weight:bold;">def</span> set_browser<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    world.<span style="color: black;">browser</span> = Client<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
@step<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'I access the url &quot;(.*)&quot;'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> access_url<span style="color: black;">&#40;</span>step, url<span style="color: black;">&#41;</span>:
    response = world.<span style="color: black;">browser</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
    world.<span style="color: black;">dom</span> = html.<span style="color: black;">fromstring</span><span style="color: black;">&#40;</span>response.<span style="color: black;">content</span><span style="color: black;">&#41;</span>
&nbsp;
@step<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'I see the header &quot;(.*)&quot;'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> see_header<span style="color: black;">&#40;</span>step, text<span style="color: black;">&#41;</span>:
    header = world.<span style="color: black;">dom</span>.<span style="color: black;">cssselect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'h1'</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">assert</span> header.<span style="color: black;">text</span> == text</pre></div></div>

<p style="text-align: justify;">Basta executá-lo da seguinte maneira:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python manage.py harvest</pre></div></div>

<p style="text-align: justify;"><a title="Django + Lettuce, uma dupla interessante!" href="http://lettuce.it/recipes/django-lxml.html#recipes-django-lxml">Confira mais informações sobre como utilizar o <em>lettuce </em>com <em>Django</em></a>.</p>
<h3 style="text-align: justify;"><em>fudge</em> &#8211; Ajude o <em>Python </em>a mentir</h3>
<p style="text-align: justify;">O <em><a title="Fudge, criando objetos mentirosos" href="http://farmdev.com/projects/fudge/">Fudge</a></em> é um módulo <em>Python </em>que auxilia na construção de objetos &#8220;dublês&#8221; (<a title="Mocks não são Stubs" href="http://www.infoq.com/br/articles/mocks-Arent-Stubs"><em>mocks </em>e <em>stubs</em></a>), que permitem escrever testes sem necessariamente possuir um serviço ativo ou um objeto construído.</p>
<p style="text-align: justify;">Um caso comum: Você está construindo uma <em>API </em>que autentica via <em>OAuth </em>ao<em> Twitter </em>e está utilizando testes para guiar o seu desenvolvimento. Não é interessante que nossos testes sejam dependentes da disponibilidade do serviço do <em>Twitter</em>, portanto, escrevemos um &#8220;objeto mentiroso&#8221;, que simulará este serviço, aceitando uma entrada e gerando um saída:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> fudge
@fudge.<span style="color: black;">patch</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'oauthtwitter.OAuthApi'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span>FakeOAuthApi<span style="color: black;">&#41;</span>:
        <span style="color: black;">&#40;</span>FakeOAuthApi.<span style="color: black;">expects_call</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            .<span style="color: black;">with_args</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>, <span style="color: #483d8b;">''</span>,
                         <span style="color: #483d8b;">''</span>, <span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span>
            .<span style="color: black;">returns_fake</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            .<span style="color: black;">expects</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'UpdateStatus'</span><span style="color: black;">&#41;</span>.<span style="color: black;">with_arg_count</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
post_msg_to_twitter<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;hey there fellow testing freaks!&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p style="text-align: justify;">Pronto! Sabendo que valores serão passados, e quais os resultados, podemos simular o comportamento daquele serviço. Prático, não?</p>
<h3 style="text-align: justify;">Considerações finais</h3>
<p style="text-align: justify;">Estas são as ferramentas que eu costumo utilizar em meus projetos <em>Python/Django</em>. É claro que existem outras, na verdade existem várias. Tenha em mente que a ferramenta é apenas um meio de garantir, através de testes, que você está guiando a sua aplicação para o lugar certo. Os testes automatizados no final servem para garantir que ela ainda segue este caminho, que contribuições realizadas tardiamente não &#8220;quebraram&#8221; o comportamento que você escreveu no início do desenvolvimento.</p>
<p style="text-align: justify;">Tenho a intenção de escrever um <em>post </em>mais prático sobre testes e <em>Django</em>. Fiquem no aguardo <img src='http://www.profissionaisti.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p style="text-align: justify;">E você? Tem alguma ferramenta para recomendar? Utilize os comentários abaixo para compartilhá-la.</p>
<h3 style="text-align: justify;">Referências</h3>
<ul style="text-align: justify;">
<li><em><a title="Leia sobre Django, BDD, Lettuce e Splinter" href="http://cilliano.com/blog/2011/02/07/django-bdd-with-lettuce-and-splinter/" target="_blank">CillianO &#8211; Django Full Stack Testing and BDD with Lettuce and Splinter</a></em></li>
<li><em><a title="Não sabe o que é BDD? Conheça neste artigo de Danilo Sato" href="http://www.dtsato.com/blog/work/introduzindo_desenvolvimento_orientado_comportamento_bdd/">Danilo Sato &#8211; Introduzindo Desenvolvimento Orientado por Comportamento (BDD)</a></em></li>
<li><em><a title="Visite o repositório do django-nose no GitHub" href="https://github.com/jbalogh/django-nose">django-nose &#8211; GitHub repository</a></em></li>
<li><em><a title="Documentação oficial do Fudge" href="http://farmdev.com/projects/fudge/using-fudge.html#fudging-a-web-service">Fudge &#8211; Using Fudge</a></em></li>
<li><em><a title="Testes em Python passam a ser mais fáceis com nose" href="http://jpz-log.info/archives/2010/06/08/nose-testing-in-python-made-easy/">JPz&#8217;log &#8211; nose: Testing in Python made easy</a></em></li>
<li><em><a title="Aprenda a escrever testes Python com o Nose" href="http://somethingaboutorange.com/mrl/projects/nose/1.0.0/writing_tests.html">Nose &#8211; Writing tests</a></em></li>
<li><em><a title="Conheça o projeto Splinter, e envolva-se" href="http://splinter.cobrateam.info/">Splinter &#8211; Test framework for web applications</a></em></li>
</ul>
<p style="text-align: justify;">Até a próxima&#8230;</p>
<p style="text-align: justify;"><strong>Fonte: </strong><a title="Ferramentas de testes em Django - Parte 2" href="http://www.klauslaube.com.br/2011/07/ferramentas-de-testes-em-django-parte-2/" target="_blank">Klaus Laube</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.profissionaisti.com.br/2011/08/ferramentas-de-testes-em-django-parte-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ferramentas de testes em Django &#8211; Parte 1</title>
		<link>http://www.profissionaisti.com.br/2011/08/ferramentas-de-testes-em-django-parte-1/</link>
		<comments>http://www.profissionaisti.com.br/2011/08/ferramentas-de-testes-em-django-parte-1/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 15:44:55 +0000</pubDate>
		<dc:creator>Klaus Peter Laube</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Utilidades]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Testes]]></category>

		<guid isPermaLink="false">http://www.profissionaisti.com.br/?p=18776</guid>
		<description><![CDATA[Dando continuidade à série de posts sobre Django, vou indicar algumas ferramentas de testes para que você também possa deixar com que os testes guiem o desenvolvimento de suas aplicações. Afinal, testar é preciso &#160; Testar em Django é possível? Sem dúvida nenhuma! Mas não espere que o framework adeque-se a você, você precisa ter [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;"><img class="alignleft size-full wp-image-18779" style="margin-left: 5px; margin-right: 5px;" title="gm_test_500_2-300x189" src="http://www.profissionaisti.com.br/wp-content/uploads/2011/08/gm_test_500_2-300x189.jpg" alt="" width="180" height="113" />Dando continuidade à série de <em>posts </em>sobre <em><a title="Leia mais sobre Django" href="http://www.profissionaisti.com.br/tag/django/">Django</a></em>, vou indicar algumas ferramentas<em> </em>de testes para que você também possa deixar com que os <a title="TDD: Desenvolvimento Orientado a Testes" href="http://www.profissionaisti.com.br/2009/11/tdd-desenvolvimento-orientado-a-testes/">testes guiem o desenvolvimento de suas aplicações</a>.</p>
<p style="text-align: justify;">Afinal, testar é preciso <img src='http://www.profissionaisti.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p style="text-align: justify;">&nbsp;</p>
<h3 style="text-align: justify;">Testar em <em>Django</em> é possível?</h3>
<p style="text-align: justify;">Sem dúvida nenhuma! Mas não espere que o <em>framework </em>adeque-se a você, você precisa ter a iniciativa de tentar compreender as melhores maneiras para escrever testes em <em>Django</em>.</p>
<p style="text-align: justify;">Por exemplo, se você tem por hábito isolar os modelos para <a title="Leia mais sobre testes" href="http://www.profissionaisti.com.br/tag/testes/">testá-los</a> de forma unitária, pode passar por certa dor de cabeça com o <em><a title="Leia mais sobre Python" href="http://www.profissionaisti.com.br/tag/python/">Python</a></em>/<em><a title="Leia mais sobre Django" href="http://www.profissionaisti.com.br/tag/django/">Django</a></em>. Não que seja impossível, mas o comportamento <em>default </em>do <em>framework</em> é criar uma base de dados &#8220;<em>fake</em>&#8221; para você não precisar ter este trabalho.</p>
<p style="text-align: justify;">Enfim, talvez a forma de <strong>utilizar</strong> estas ferramentas <strong>caiba em um outro <em>post</em></strong>, o objetivo deste é <strong>apenas apresentá-las</strong>.</p>
<h3 style="text-align: justify;"><em>unittest</em> &#8211; Testando unidades através de classes</h3>
<p style="text-align: justify;">A <em><a title="unittest — Unit testing framework" href="http://docs.python.org/library/unittest.html" target="_blank">unittest</a> </em>é uma biblioteca padrão do <em>Python </em>que ajuda (e muito) a escrever testes automatizados com a linguagem.</p>
<p style="text-align: justify;">Os testes são escritos através de classes, onde utilizamos os esquemas de <em><a title="Veja a lista de asserts da unittest" href="http://docs.python.org/library/unittest.html#assert-methods" target="_blank">assertions</a></em> para garantir o comportamento do código testado (nenhuma novidade até aqui). Para quem utiliza testes unitários no <em>Java</em> não vai sentir grandes mudanças na abordagem, já que a <em>unittest </em>é inspirada na <em><a title="Leia mais sobre a JUnit" href="http://javafree.uol.com.br/wiki/JUnit" target="_blank">JUnit</a></em><em> </em>(sendo muitas vezes até chamada de <em>PyUnit</em>):</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
<span style="color: #ff7700;font-weight:bold;">from</span> myapp.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> Animal
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> AnimalTestCase<span style="color: black;">&#40;</span><span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> setUp<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">lion</span> = Animal.<span style="color: black;">objects</span>.<span style="color: black;">create</span><span style="color: black;">&#40;</span>name=<span style="color: #483d8b;">&quot;lion&quot;</span>, sound=<span style="color: #483d8b;">&quot;roar&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">cat</span> = Animal.<span style="color: black;">objects</span>.<span style="color: black;">create</span><span style="color: black;">&#40;</span>name=<span style="color: #483d8b;">&quot;cat&quot;</span>, sound=<span style="color: #483d8b;">&quot;meow&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> testSpeaking<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEquals</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">lion</span>.<span style="color: black;">speak</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'The lion says &quot;roar&quot;'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEquals</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">cat</span>.<span style="color: black;">speak</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'The cat says &quot;meow&quot;'</span><span style="color: black;">&#41;</span></pre></div></div>

<p style="text-align: justify;">O <em>test runner</em> padrão do <em>Django</em> irá procurar por subclasses de <em>unittest.TestCase </em>nos arquivos <em>models.py </em>e <em>tests.py</em>. A suíte de testes tenta facilitar ao máximo a sua vida&#8230; execute a seguinte instrução e confira se a sua aplicação está <em>ok </em>ou não:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python manage.py <span style="color: #7a0874; font-weight: bold;">test</span></pre></div></div>

<p style="text-align: justify;"><strong>Peraí que não acabou! Apresentando a <em>TestCase</em></strong></p>
<p style="text-align: justify;">Testar aplicações <em>Web </em>com a<em> unittest </em>pode ser dureza. Pensando nisso o <em>Django </em>disponibiliza a <em>TestCase</em>, que estende a <em>unittest</em> adicionando funcionalidades como carregamento de <em>fixtures</em>, roteamento de <em>urls </em>e um <em>client</em> para fazer requisições <em>Web </em>e testar as suas <em>views </em>(o <em>TestClient</em>, detalhado mais abaixo).</p>
<h3 style="text-align: justify;"><em>doctest</em> &#8211; Testando através de <em>docstrings</em></h3>
<p style="text-align: justify;">Admito que escrever documentação de <em>software </em>não é o meu forte&#8230; mas com <em>doctests </em>pode-se documentar métodos ao mesmo tempo em que escreve-se testes!</p>
<p style="text-align: justify;">A <em><a title="Leia mais sobre a doctest" href="http://docs.python.org/library/doctest.html" target="_blank">doctest</a> </em>é uma biblioteca padrão do <em>Python </em>que procura e interpreta <em>docstrings </em>na aplicação. A sintaxe nesses trechos de <em><a title="Entenda o que é uma docstring" href="http://www.python.org/dev/peps/pep-0257/">docstrings</a> </em>é diferenciada, simulando um interpretador interativo do <em>Python</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># models.py</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> models
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Animal<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    An animal that knows how to make noise
&nbsp;
    # Create some animals
    &gt;&gt;&gt; lion = Animal.objects.create(name=&quot;lion&quot;, sound=&quot;roar&quot;)
    &gt;&gt;&gt; cat = Animal.objects.create(name=&quot;cat&quot;, sound=&quot;meow&quot;)
&nbsp;
    # Make 'em speak
    &gt;&gt;&gt; lion.speak()
    'The lion says &quot;roar&quot;'
    &gt;&gt;&gt; cat.speak()
    'The cat says &quot;meow&quot;'
    &quot;&quot;&quot;</span>
    name = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">20</span><span style="color: black;">&#41;</span>
    sound = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">20</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> speak<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">'The %s says &quot;%s&quot;'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">name</span>, <span style="color: #008000;">self</span>.<span style="color: black;">sound</span><span style="color: black;">&#41;</span></pre></div></div>

<p style="text-align: justify;">Assim como com a <em>unittest</em>, o <em>test runner </em>padrão do <em>Django </em>procurará por ocorrências de <em>docstests </em>em <em>models.py </em>e <em>tests.py</em>.</p>
<h3 style="text-align: justify;"><em>Django Test Client</em> &#8211; Testando a sua aplicação como se fosse um navegador</h3>
<p style="text-align: justify;">E como fazer para testar requisições <em>Web</em>? Por exemplo, você não quer testar a sua <em>view </em>de forma isolada, quer testar desde a parte de roteamento ao comportamento com o banco de dados, como se você se estivesse realmente visitando a página. Neste caso entra a <em><a title="Testando aplicações Django com requisições Web falsas" href="https://docs.djangoproject.com/en/dev/topics/testing/#module-django.test.client">test client</a></em>.</p>
<p style="text-align: justify;">Toda a classe <em>TestCase </em>possui uma instância da <em>Django Test Client</em>. Então escrever testes com requisições à sua aplicação fica muito simples utilizando classes:</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: #dc143c;">test</span> <span style="color: #ff7700;font-weight:bold;">import</span> TestCase
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> SimpleTest<span style="color: black;">&#40;</span>TestCase<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> test_details<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        response = <span style="color: #008000;">self</span>.<span style="color: black;">client</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/customer/details/'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>response.<span style="color: black;">status_code</span>, <span style="color: #ff4500;">200</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_index<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        response = <span style="color: #008000;">self</span>.<span style="color: black;">client</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/customer/index/'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>response.<span style="color: black;">status_code</span>, <span style="color: #ff4500;">200</span><span style="color: black;">&#41;</span></pre></div></div>

<p style="text-align: justify;">É perfeitamente possível utilizar a <em>test client </em>em <em>doctests </em>também:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
&gt;&gt;&gt; from django.test.client import Client
&gt;&gt;&gt; c = Client()
&gt;&gt;&gt; response = c.post('/login/', {'username': 'john',
...        'password': 'smith'})
&gt;&gt;&gt; response.status_code
200
&quot;&quot;&quot;</span></pre></div></div>

<h3 style="text-align: justify;">Considerações finais</h3>
<p style="text-align: justify;">Particularmente, tive a oportunidade de implementar testes unitários já no início do meu aprendizado em <em>Django</em>. Deixar os testes te guiarem é uma prática excelente!</p>
<p style="text-align: justify;">Tudo parte do bom senso, óbvio. Nenhum processo ou ferramenta deveria substituir o &#8220;<em>feeling</em>&#8221; do profissional&#8230; também não é muito sadio ser extremamente &#8220;<em>by the book</em>&#8220;. Mas se puder utilizar testes para guiar o seu desenvolvimento, use-os!</p>
<p style="text-align: justify;">Na segunda parte deste <em>post</em> pretendo apresentar algumas ferramentas que irão turbinar ainda mais o seu desenvolvimento orientado a testes.</p>
<p style="text-align: justify;">Até lá!</p>
<h3 style="text-align: justify;">Referências</h3>
<ul style="text-align: justify;">
<li><a title="Leia direto da fonte como escrever testes em Django" href="https://docs.djangoproject.com/en/1.1/topics/testing/#writing-unit-tests"><em>Django Documentation &#8211; Writing unit tests</em></a></li>
<li><a title="Leia direto da fonte sobre como escrever testes com docstrings" href="https://docs.djangoproject.com/en/1.1/topics/testing/#writing-doctests"><em>Django Documentation &#8211; Writing doctests</em></a></li>
<li><em><a title="Entenda a diferença entre unittest do Python e o TestCase do Django" href="https://docs.djangoproject.com/en/1.1/topics/testing/#testcase">Django Documentation &#8211; TestCase</a></em></li>
<li><em><a title="Leia sobre a unittest direto da documentação do Python" href="http://docs.python.org/library/unittest.html">Python Documentation &#8211; unittest: Unit testing framework</a></em></li>
<li><em><a title="Aprenda a testar a sua primeira aplicação em Django" href="http://dougalmatthews.com/articles/2010/jan/20/testing-your-first-django-app/">Dougal Matthews &#8211; Testing your first Django app</a></em></li>
<li><a title="O Konrad apresenta algumas ferramentas muito boas para testes com Django" href="&amp; kokoko.fluxionary.net/testing-django-part-1-nose"><em>Konrad&#8217;s Kode, Konfigs &amp; Konstructions &#8211; Testing Django</em></a></li>
<li><a title="Aprenda Django de uma forma divertida com o Marinho" href="http://www.marinhobrandao.com/blog/programacao-dirigida-a-testes-no-django/">Marinho Brandão &#8211; Programação dirigida a testes no <em>Django</em></a></li>
</ul>
<p style="text-align: justify;"><strong>Fonte: </strong><a title="Ferramentas de testes em Django - Parte 1" href="http://www.klauslaube.com.br/2011/07/ferramentas-de-testes-em-django-parte-1/" target="_blank">Klaus Laube</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.profissionaisti.com.br/2011/08/ferramentas-de-testes-em-django-parte-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python/Django: Quando usar gettext e gettext_lazy?</title>
		<link>http://www.profissionaisti.com.br/2011/06/pythondjango-quando-usar-gettext-e-gettext_lazy/</link>
		<comments>http://www.profissionaisti.com.br/2011/06/pythondjango-quando-usar-gettext-e-gettext_lazy/#comments</comments>
		<pubDate>Fri, 17 Jun 2011 16:00:07 +0000</pubDate>
		<dc:creator>Klaus Peter Laube</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Papinho de TI]]></category>
		<category><![CDATA[Dica]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.profissionaisti.com.br/?p=17349</guid>
		<description><![CDATA[Olá pessoas! Para vocês que desenvolvem em Python e Django preocupando-se com internacionalização, já devem ter feito a seguinte pergunta: Quando usar gettext e gettext_lazy? Acredito que antes de responder esta pergunta, temos que responder outra questão pertinente: Devo utilizar gettext ou ugettext? gettext vs ugettext Essas duas funções seguem o mesmo princípio dos métodos [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Olá pessoas!</p>
<p style="text-align: justify;">Para vocês que desenvolvem em <em><a title="Leia mais sobre Python" href="http://www.profissionaisti.com.br/tag/python/">Python</a> </em>e<em> <a title="Leia mais sobre Django" href="http://www.profissionaisti.com.br/tag/django/">Django</a> </em>preocupando-se com internacionalização, já devem ter feito a seguinte pergunta: <em>Quando usar gettext e gettext_lazy? </em></p>
<p style="text-align: justify;">Acredito que antes de responder esta pergunta, temos que responder outra questão pertinente: <em>Devo utilizar gettext ou ugettext?<br />
</em></p>
<h3 style="text-align: justify;"><em>gettext </em>vs <em>ugettext</em></h3>
<p style="text-align: justify;">Essas duas funções seguem o mesmo princípio dos métodos mágicos <em>__str__ </em>e <em>__unicode__</em>. Onde <em>gettext </em>retornará um texto traduzido como uma <em>string </em>&#8220;comum&#8221;, e <em>ugettext </em>retornará um texto traduzido como uma <em>string Unicode</em>.</p>
<p style="text-align: justify;">Como nosso idioma nativo abusa do uso de caracteres especiais, aconselho sempre que possível a utilização do <em>ugettext</em>. Na verdade, é uma forma de garantir sucesso na tradução de qualquer idioma sem quebrar a cabeça com <em>encoding</em> (já que o <em>Unicode </em>tem uma ampla tabela  de caracteres).</p>
<p style="text-align: justify;">Além disso, passe a mensagem como <em>Unicode </em>para a função sempre que necessário:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">texto_traduzido = ugettext<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'Descrição do produto em estoque'</span><span style="color: black;">&#41;</span></pre></div></div>

<h3 style="text-align: justify;"><em>ugettext </em>vs <em>ugettext_lazy</em></h3>
<p style="text-align: justify;">A principal diferença entre <em>ugettext </em>e <em>ugettext_lazy </em>é que o último é literalmente um preguiçoso. Ele faz uma referência para a <em>string </em>(e não necessariamente para a tradução), fazendo com que a operação seja executada apenas quando a renderização da <em>string </em>é necessária (ao contrário de <em>ugettext </em>que é processado assim que a expressão é interpretada).</p>
<p style="text-align: justify;">Confuso? Talvez o <em><a title="Aprendendo Django no Planeta Terra - O mesmo site em vários idiomas" href="http://www.aprendendodjango.com/o-mesmo-site-em-varios-idiomas/" target="_blank">Marinho Brandão</a> </em>possa ser mais claro:</p>
<pre>A função <strong>"ugettext_lazy()"</strong> é <strong>preguiçosa</strong>. Isso significa que a 
tradução é feita somente quando ela é requisitada, o que é
relativamente melhor para o caso de classes de modelo, pois elas
são constantemente utilizadas sem que a tradução de um termo seja
necessário de fato.

Por outro lado a função <strong>"ugettext()"</strong> traduz a string
instantaneamente, o que é melhor para casos como o de formulários
dinâmicos e <em>views</em>, pois eles não são usados de maneira tão constante
quanto classes de modelo.</pre>
<p style="text-align: justify;">Então&#8230; utilize <em>ugettext_lazy </em>nos campos e meta-informações dos modelos (onde a tradução pode ser feita sob demanda), e <em>ugettext </em>em métodos, funções e <em>views </em>(onde a tradução tem quer ser &#8220;instantânea&#8221;).</p>
<h3 style="text-align: justify;">Referências</h3>
<ul style="text-align: justify;">
<li><em><a title="gettext - Multilingual internationalization services" href="http://docs.python.org/library/gettext.html" target="_blank">Python Documentation &#8211; gettext</a></em></li>
<li><em><a title="Django Docs - Lazy Translation" href="https://docs.djangoproject.com/en/dev/topics/i18n/internationalization/#lazy-translation" target="_blank">Django Documentation &#8211; Internationalization</a></em></li>
<li><em><a title="The Django Book - i18n" href="http://www.djangobook.com/en/1.0/chapter18/" target="_blank">The Django Book &#8211; Internationalization</a></em></li>
<li><a title="Aprendendo Django - O mesmo site em vários idiomas" href="http://www.aprendendodjango.com/o-mesmo-site-em-varios-idiomas/" target="_blank">Aprendendo <em>Django </em>no Planeta Terra &#8211; O mesmo site em vários idiomas</a></li>
</ul>
<p style="text-align: justify;">Até a próxima&#8230;</p>
<p style="text-align: justify;"><strong>Fonte: </strong><a title="Quando usar gettext e gettext_lazy?" href="http://www.klauslaube.com.br/2011/06/quando-usar-gettext-gettext_lazy/">Blog Klaus Laube</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.profissionaisti.com.br/2011/06/pythondjango-quando-usar-gettext-e-gettext_lazy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Como versionar projetos Django com o Mercurial &#8211; Parte 3</title>
		<link>http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-3/</link>
		<comments>http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-3/#comments</comments>
		<pubDate>Wed, 08 Jun 2011 16:26:53 +0000</pubDate>
		<dc:creator>Klaus Peter Laube</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Software Livre]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[Versionamento]]></category>

		<guid isPermaLink="false">http://www.profissionaisti.com.br/?p=17408</guid>
		<description><![CDATA[Olá pessoas! Dando continuidade a micro-série &#8220;Como versionar projetos Django com o Mercurial&#8221; (confira a parte 1 e a parte 2), vamos finalizar com um exemplo prático de um projeto Django usando o  Mercurial. Começando&#8230; Vamos reutilizar a estrutura dos posts anteriores. Para isso, inicie um projeto com o virtualenv: $ cd ~/Projetos/ $ virtualenv DjangoComHG [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Olá pessoas!</p>
<p style="text-align: justify;">Dando continuidade a micro-série &#8220;<em>Como versionar projetos Django com o Mercurial</em>&#8221; (confira a <a title="Como versionar projetos Django com o Mercurial - Parte 1" href="http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-1/">parte 1</a> e a <a title="Como versionar projetos Django com o Mercurial - Parte 2" href="http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-2/">parte 2</a>), vamos finalizar com um exemplo prático de um projeto <em><a title="Leia mais sobre Django" href="http://www.profissionaisti.com.br/tag/django/">Django</a> </em>usando o  <em><a title="Leia mais sobre Mercurial" href="http://www.profissionaisti.com.br/tag/mercurial/">Mercurial</a></em>.</p>
<h2 style="text-align: justify;">Começando&#8230;</h2>
<p style="text-align: justify;">Vamos reutilizar a estrutura dos <em>posts </em>anteriores. Para isso, inicie um projeto com o <em>virtualenv</em>:</p>
<pre>$ cd ~/Projetos/
$ virtualenv DjangoComHG --no-site-packages
$ cd DjangoComHG/</pre>
<p style="text-align: justify;">Vamos aproveitar os procedimentos descritos na <a title="Aprenda a como criar um repositório Mercurial no Bitbucket" href="http://www.klauslaube.com.br/2011/05/como-versionar-projetos-django-mercurial-%E2%80%93-parte-2/">parte 2</a> deste <em>post</em>. Caso você ainda não tenha criado um repositório no <em><a title="Versione e compartilhe código com o Mercurial" href="http://www.bitbucket.org/">Bitbucket</a></em>, essa é uma boa oportunidade.</p>
<pre style="text-align: left;"><span style="color: #222222; font-family: 'Courier 10 Pitch', Courier, monospace; font-size: 15px; line-height: 21px; white-space: pre;">$ hg clone &lt;caminho&gt; django_com_hg
</span></pre>
<p style="text-align: justify;">Não esqueça de mudar o <strong>caminho</strong> para o <strong>endereço do seu repositório</strong>.</p>
<h2 style="text-align: justify;">Instalando o <em>Django</em></h2>
<p style="text-align: justify;">Com o <em>virtualenv </em>ativado, vamos instalar o <em>Django </em>apenas para o nosso ambiente virtual através do <em>pip</em>:</p>
<pre>$ source bin/activate
$ pip install django</pre>
<p style="text-align: justify;">Só para ter certeza que ele instalou o <em>Django </em>dentro do nosso ambiente virtual, vamos abrir o terminal do <em>Python </em>e digitar as seguintes instruções:</p>
<pre>$ import django
$ django.__path__</pre>
<p style="text-align: justify;">Você deverá obter como resposta uma <em>string </em>semelhante a esta:</p>
<pre>$HOME/Projetos/DjangoComHG/lib/python2.6/site-packages/django/</pre>
<h2 style="text-align: justify;">Iniciando um projeto</h2>
<p style="text-align: justify;">Vamos fazer uma pequena brincadeira de troca de nomes de pastas, para que possamos criar o nosso projeto <em>Django </em>com o mesmo nome do repositório <em>Mercurial</em>:</p>
<pre>$ mv post_django_com_hg post_django_com_hg.bk</pre>
<p style="text-align: justify;">Agora mandamos o <em>django-admin.py</em> iniciar o projeto:</p>
<pre>$ django-admin.py startproject post_django_com_hg</pre>
<p style="text-align: justify;">Movemos os arquivos do nosso repositório para dentro de <em>post_django_com_hg</em>:</p>
<pre>$ mv post_django_com_hg.bk/* post_django_com_hg/
$ mv post_django_com_hg.bk/.hg post_django_com_hg/
$ mv post_django_com_hg.bk/.hgignore post_django_com_hg/</pre>
<p style="text-align: justify;">Entre no diretório <em>post_django_com_hg </em>e dê um <em><strong>hg status</strong></em>. Os arquivos base do <em>Django </em>não estão no projeto. Vamos adicioná-los, comitá-los e dar um <strong><em>push </em></strong>deles para o repositório <em>Mercurial </em>no <em>Bitbucket</em>:</p>
<pre>$ hg add .
$ hg commit -m "Projeto Django iniciado"
$ hg push</pre>
<p style="text-align: justify;">Nos <em>changesets </em>do repositório, veremos a contribuição enviada:</p>
<div class="mceTemp mceIEcenter" style="text-align: justify;">
<dl id="attachment_17409" class="wp-caption aligncenter" style="width: 602px;">
<dt class="wp-caption-dt"><a href="http://www.profissionaisti.com.br/wp-content/uploads/2011/06/post-django-hg-bitbucket-changeset.png"><img class="size-full wp-image-17409 " title="post-django-hg-bitbucket-changeset" src="http://www.profissionaisti.com.br/wp-content/uploads/2011/06/post-django-hg-bitbucket-changeset.png" alt="" width="592" height="174" /></a></dt>
<dd class="wp-caption-dd">Changeset no Bitbucket</dd>
</dl>
</div>
<p style="text-align: justify;">Pronto! Basicamente, para termos o <em>Mercurial </em>versionando um projeto <em>Django</em>, são estes os procedimentos&#8230; mas eu sei como deixar a coisa ainda mais interessante <img src='http://www.profissionaisti.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h2 style="text-align: justify;">Hora de congelar!</h2>
<p style="text-align: justify;">Digamos que você tenha um colaborador envolvido com o projeto. Quer dizer que ele vai ter que criar um <em>virtualenv</em>, clonar o repositório e instalar as dependências do projeto? A resposta é &#8220;sim&#8221; &#8211; Mas podemos facilitar esta última parte através do <em>pip</em>:</p>
<pre>$ pip freeze
Django==1.3
wsgiref==0.1.2</pre>
<p style="text-align: justify;">O comando <em><strong>pip freeze </strong></em>vai coletar os pacotes <em>Python </em>instalados (nesse nosso caso, dentro do nosso ambiente virtual através do <em>virtualenv</em>) e exibir para a gente em formato de lista. Com isso, podemos criar um arquivo que armazene as dependências do nosso projeto:</p>
<pre>$ pip freeze &gt; requirements.txt</pre>
<p style="text-align: justify;">Vamos desativar o ambiente atual, criar um novo e instalar as dependências listadas nesta arquivo <strong><em>requirements.txt </em></strong>neste novo ambiente:</p>
<pre>$ deactivate
$ cd ~/Projetos/
$ virtualenv DjangoComHG-2 --no-site-packages
$ source DjangoComHG-2/bin/activate
$ pip install -r DjangoComHG/post_django_com_hg/requirements.txt</pre>
<p style="text-align: justify;">Veja a mágica acontecendo&#8230; o <em>pip </em>instalará todas as dependências contidas em<strong><em> requirements.txt </em></strong>em nosso novo ambiente virtual.</p>
<p style="text-align: justify;">Podemos resumir os comandos acima em:</p>
<pre>$ pip install -E DjangoComHG-2 -r DjangoComHG/post_django_com_hg/requirements.txt</pre>
<p style="text-align: justify;"><span style="font-size: 20px; font-weight: bold;">Versionando dependências do projeto</span></p>
<p style="text-align: justify;">Logo o <strong><em>requirements.txt </em></strong>sendo um arquivo de texto, pode ser facilmente versionado pelo <em>Mercurial</em>:</p>
<pre>$ cd ~/Projetos/DjangoComHG/post_django_com_hg
$ hg add requirements.txt
$ hg commit -m "Adicionado arquivo de dependências do pip"
$ hg push</pre>
<p style="text-align: justify;">Finalmente, temos um <a title="Confira o exemplo deste post no Bitbucket" href="https://bitbucket.org/kplaube/post-django-com-hg/" target="_blank">projeto <em>Django </em>versionado com <em>Mercurial</em>, disponível no <em>Bitbucket</em></a>, e com dependências facilmente gerenciáveis através do <em>pip </em>em conjunto com o <em>virtualenv</em>.</p>
<p style="text-align: justify;">E você&#8230; utiliza controle de versão com o <em>Django </em>de uma outra forma? Conte-nos através dos comentários abaixo.</p>
<p style="text-align: justify;">Até a próxima&#8230;</p>
<p style="text-align: justify;"><strong>Fonte: </strong><a title="Como versionar projetos Django com o Mercurial - Parte 3" href="http://www.klauslaube.com.br/2011/06/como-versionar-projetos-django-mercurial-parte-3/" target="_blank">Blog Klaus Laube</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Como versionar projetos Django com o Mercurial &#8211; Parte 2</title>
		<link>http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-2/</link>
		<comments>http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-2/#comments</comments>
		<pubDate>Tue, 07 Jun 2011 13:18:10 +0000</pubDate>
		<dc:creator>Klaus Peter Laube</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Software Livre]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[Versionamento]]></category>

		<guid isPermaLink="false">http://www.profissionaisti.com.br/?p=17346</guid>
		<description><![CDATA[Dando continuidade ao post Como versionar projetos Django com o Mercurial, vamos dar uma pincelada nos funcionamentos básicos do Mercurial. hg? Mas não era Mercurial? Mercury em português significa mercúrio (nenhuma novidade até aqui), que é um elemento químico com o símbolo Hg e o número atômico 80 (assim disse a Wikipedia (:  ).  É [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Dando continuidade ao post <em><a title="Leia a primeira parte deste post" href="http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-1/">Como versionar projetos Django com o Mercurial</a></em>, vamos dar uma pincelada nos funcionamentos básicos do <em>Mercurial</em>.</p>
<h2 style="text-align: justify;"><em>hg</em>? Mas não era <em>Mercurial</em>?</h2>
<p style="text-align: justify;"><em>Mercury </em>em português significa mercúrio (nenhuma novidade até aqui), que é um elemento químico com o símbolo <em>Hg</em> e o número atômico 80 (assim disse a <em><a title="Leia mais sobre o elemento químico Mercúrio" href="http://en.wikipedia.org/wiki/Mercury_(element)" target="_blank">Wikipedia</a> </em>(:  ).  É devido a isso que você utilizará o <em>Mercurial </em>em linha de comando através de comandos iniciados por <em><strong>hg</strong></em>.</p>
<p style="text-align: justify;">Antes de iniciarmos, vamos dizer ao <em>Mercurial </em>quem nós somos. Abra o arquivo <em><strong>.hgrc </strong></em>do seu <em>home</em>:</p>
<pre>$ vim ~/.hgrc</pre>
<p style="text-align: justify;">É fundamental que nossos <em>commits </em>estejam marcados com nosso nome, e um <em>e-mail </em>para contato. Vamos escrever estas duas informações neste arquivo:</p>
<pre>[ui]
username = seu nome &lt;seuemail@provedor.com&gt;</pre>
<p style="text-align: justify;">Salve o arquivo&#8230; e estamos prontos para iniciar.</p>
<h2 style="text-align: justify;">Primeiros passos&#8230;</h2>
<p style="text-align: justify;">Os passos que vou exemplificar aqui não são muito diferentes dos que você encontrará na <a title="Visite a página oficial do projeto Mercurial" href="http://mercurial.selenic.com/" target="_blank">página oficial do <em>Mercurial</em></a>. Preguiça minha? Talvez&#8230; mas você verá que usar o <em>Mercurial </em>é extremamente simples! As dificuldades são as exceções do dia-à-dia.</p>
<p style="text-align: justify;">Para deixar o exemplo mais interessante, vamos utilizar o <em>virtualenv</em>. Dúvidas? Confira o <em>post </em><em><a title="Construa projetos isolados do seu sistema com virtualenv" href="http://www.profissionaisti.com.br/2011/04/python-django-e-virtualenv/">Python, Django e virtualenv</a></em> e visualize aonde pretendemos chegar:</p>
<pre>$ cd ˜/Projetos/
$ virtualenv DjangoComHG --no-site-packages
$ cd DjangoComHG</pre>
<p style="text-align: justify;">Agora sim, vamos criar um projeto através da seguinte expressão:</p>
<pre>$ hg init django-com-hg</pre>
<p style="text-align: justify;">Projeto criado&#8230; vamos partir para as tarefas mais comuns no <em>Mercurial</em>.</p>
<h2 style="text-align: justify;">Altere, adicione e &#8220;comite&#8221;</h2>
<p style="text-align: justify;">O <em>Mercurial </em>é <em><a title="Leia mais sobre Distributed Version Control System" href="http://en.wikipedia.org/wiki/Distributed_revision_control" target="_blank">DVCS</a></em>, isto quer dizer que, quando você clonar um repositório remoto você terá uma cópia exata dele em seu computador. Logo, as alterações que você &#8220;persistir&#8221; estarão disponíveis apenas na sua cópia local. Pode parecer um pouco confuso, mas com o tempo faz todo o sentido.</p>
<p style="text-align: justify;">Para o primeiro <em>commit </em>(persistir nossas alterações localmente) escreva um arquivo <em>.hgignore </em>(<a title="Entenda para que serve o arquivo .hgignore" href="http://mercurial.selenic.com/wiki/.hgignore" target="_blank">saiba mais do que se trata</a>) e um arquivo <em>README</em>:</p>
<pre>$ cd django-com-hg/
$ ls -a

.hg     .hgignore     README</pre>
<p style="text-align: justify;">A pasta <em>.hg </em>na verdade é quem vai identificar e armazenar todas as informações do nosso projeto. Sem ela, você deixa de ter o controle sobre as versões dos arquivos e subpastas do projeto.</p>
<p style="text-align: justify;">Execute o comando <strong><em>hg status </em></strong>e veja o que aparece&#8230; acredito que o resultado seja auto-sugestivo. O <em>Mercurial </em>ainda não sabe o que fazer com os arquivos no projeto, portanto diremos a ele que queremos versionar estes arquivos:</p>
<pre>$ hg add .hgignore README</pre>
<p style="text-align: justify;">Uma nova execução do <strong><em>hg status </em></strong>vai apontar que os arquivos foram marcados para adição, porém, ainda não foram adicionados. Você vai confirmar está operação através do comando <em>commit</em>:</p>
<pre>$ hg commit -m "Primeiro commit com .hgignore"</pre>
<p style="text-align: justify;">O parâmetro <strong><em>-m </em></strong>serve para passarmos uma mensagem de descrição do <em>commit </em>que estamos fazendo. Isto facilita na leitura do <em>log </em>de <em>commits </em>realizados:</p>
<pre>$ hg log</pre>
<p style="text-align: justify;">Estes serão os comandos que provavelmente você usará constantemente enquanto desenvolve.</p>
<h2 style="text-align: justify;">Compartilhando as suas produções</h2>
<p style="text-align: justify;">Se você ainda não tem uma conta no <em><a title="Bitbucket, compartilhe o seu código" href="http://bitbucket.org">Bitbucket</a></em>, essa é uma grande oportunidade para fazer uma.</p>
<p style="text-align: justify;">Vamos criar um repositório para praticarmos o comando <em><strong>push. </strong></em>No<em> Bitbucket</em>:</p>
<ul style="text-align: justify;">
<li>Eu vou dar o nome de &#8220;<em>post-django-com-hg</em>&#8221; ao repositório, fique a vontade para dar o nome que você desejar;</li>
<li>Escolha o <em>Python </em>como linguagem;</li>
<li>Coloque uma pequena descrição;</li>
<li>Eu vou marcar a opção <em>Issue tracking</em>, caso haja algum problema com o código e vocês queiram sugerir melhorias.</li>
</ul>
<p style="text-align: justify;"><a title="Confira o repositório criado no Bitbucket" href="https://bitbucket.org/kplaube/post-django-com-hg">Confira o resultado</a>.</p>
<p style="text-align: justify;">No repositório local vamos utilizar o comando <em><strong>push </strong></em>com o endereço do repositório no <em>Bitbucket</em>. Isso enviará todas as alterações que persistidas em nosso repositório local para o repositório remoto, mesclando-as com as contribuições de outros usuários envolvidos no projeto:</p>
<pre>$ hg push https://bitbucket.org/kplaube/post-django-com-hg</pre>
<p style="text-align: justify;"><strong>Lembre-se</strong> de mudar o endereço acima para o endereço do seu repositório no <em>Bitbucket. </em>Visite a página do seu repositório e veja o que aconteceu&#8230; bacana, não?</p>
<p style="text-align: justify;">Mas dessa forma, teremos que sempre executar o comando <strong><em>push </em></strong>informando o endereço do repositório. Vamos deixar esta tarefa mais simples editando o arquivo <strong><em>hgrc </em></strong>dentro da pasta <em>.hg</em> do projeto:</p>
<pre>$ cd ~/Projetos/DjangoComHG/django-com-hg/
$ vim .hg/hgrc</pre>
<p style="text-align: justify;">Coloque o seguinte:</p>
<pre>[paths]
default = https://kplaube@bitbucket.org/kplaube/post-django-com-hg</pre>
<p style="text-align: justify;"><strong>Lembre-se </strong>de mudar o endereço acima para o endereço do seu repositório no <em>Bitbucket</em>.</p>
<p style="text-align: justify;">Pronto! Quando você for &#8220;pushear&#8221; não precisará mais informar o endereço do repositório remoto.</p>
<p style="text-align: justify;">Altere alguns arquivos&#8230; <em>commit</em>. Adicione alguns arquivos&#8230; <em>commit</em>. Ao final do dia, dê um <em>push </em>e deixe o resto da equipe saber o que você fez <img src='http://www.profissionaisti.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h2 style="text-align: justify;">Referências</h2>
<ul style="text-align: justify;">
<li><a title="Mercurial, work easier, work faster" href="http://mercurial.selenic.com/">Site oficial do projeto <em>Mercurial</em></a></li>
<li><a title="Leia mais sobre Mercurial na Wikipedia" href="http://en.wikipedia.org/wiki/Mercurial" target="_blank">Artigo na <em>Wikipedia </em>sobre <em>Mercurial</em></a></li>
<li><a title="Leia mais sobre Mercúrio no Wikipedia" href="http://en.wikipedia.org/wiki/Mercury_(element)" target="_blank">Artigo na <em>Wikipedia </em>sobre Mercúrio (o elemento químico)</a></li>
<li><a title="Excelente post sobre Mercurial, TI e gerência de projetos" href="http://tocadoelfo.blogspot.com/2011/03/mercurial-hg-controlando-as-versoes-do.html" target="_blank"><em>Mercurial Hg</em> &#8211; Controlando as Versões do seu <em>Software</em></a></li>
<li><em><a title="Excelente e-book de Bryan O'Sullivan sobre Mercurial" href="http://hgbook.red-bean.com/read/" target="_blank">Mercurial: The Definitive Guide</a></em></li>
</ul>
<p style="text-align: justify;">No próximo <em>post</em>, vamos concluir a trilogia mostrando uma forma bacana de utilizar o <em>Mercurial </em>para versionar seus projetos <em>Django</em>.</p>
<p style="text-align: justify;">Até a próxima&#8230;</p>
<p style="text-align: justify;"><strong>Fonte: </strong><a title="Como versionar projetos Django com Mercurial - Parte 2" href="http://www.klauslaube.com.br/2011/05/como-versionar-projetos-django-mercurial-%e2%80%93-parte-2/" target="_blank">Blog Klaus Laube</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Como versionar projetos Django com o Mercurial &#8211; Parte 1</title>
		<link>http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-1/</link>
		<comments>http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-1/#comments</comments>
		<pubDate>Mon, 06 Jun 2011 17:52:09 +0000</pubDate>
		<dc:creator>Klaus Peter Laube</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[mercurial]]></category>

		<guid isPermaLink="false">http://www.profissionaisti.com.br/?p=17345</guid>
		<description><![CDATA[Olá pessoas! Se você está começando em Django, e nunca utilizou uma ferramenta de controle de versão (as vezes por trauma do SVN ou por simples desinteresse) esta será uma grande oportunidade para você conhecer o Mercurial, e saber a forma que venho utilizando para versionar meus projetos Django. Peraí! Por que não Git? Sem [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Olá pessoas!</p>
<p style="text-align: justify;">Se você está começando em <em><a title="Leia mais sobre Django" href="http://www.profissionaisti.com.br/tag/django/">Django</a></em>, e nunca utilizou uma ferramenta de controle de versão (as vezes por trauma do <em><a title="Jogar Pedra em Gato Morto: por que Subversion não presta" href="http://akitaonrails.com/2007/09/22/jogar-pedra-em-gato-morto-por-que-subversion-no-presta">SVN</a> </em>ou por <a title="Wikipedia, Sistema de Controle de Versão" href="http://pt.wikipedia.org/wiki/Sistema_de_controle_de_vers%C3%A3o">simples desinteresse</a>) esta será uma grande oportunidade para você conhecer o <em><a title="Bitbucket: Hospede e versione softwares com Mercurial" href="http://www.profissionaisti.com.br/2009/06/bitbucket-hospede-e-versione-softwares-com-mercurial/">Mercurial</a></em>, e saber a forma que venho utilizando para versionar meus projetos <em>Django.<br />
</em></p>
<h3 style="text-align: justify;">Peraí! Por que não <em>Git</em>?</h3>
<p style="text-align: justify;"><img class="alignleft size-full wp-image-17383" style="margin: 10px;" title="git-logo" src="http://www.profissionaisti.com.br/wp-content/uploads/2011/06/git-logo.png" alt="" width="97" height="188" />Sem dúvida o <em><a title="Git é a estrela do momento tratando-se de DVCS" href="http://git-scm.com/">Git</a> </em>é a ferramenta do momento em se tratando de controle de versões, e vem sendo muito utilizada por rubistas e pythonistas (eu incluso nessa última galera).</p>
<p style="text-align: justify;">Por que não falar de <em>Git </em>aqui? Simples! Você vai ouvir falar sobre <em>Git </em>em todo o lugar. O<em> Google </em>vai te trazer toneladas de informações sobre <em>Git</em>. Você vai &#8220;ouvir&#8221; o pessoal falando que <a title="Por que Git é Melhor que X" href="http://pt.whygitisbetterthanx.com/"><em>Git </em>é melhor do que qualquer outra ferramenta</a>. Você vai até enjoar de tanto ouvir falar sobre <em>Git</em>.</p>
<p style="text-align: justify;">O <em>Mercurial </em>foi o primeiro <em><a title="DVCS - Distributed Version Control System" href="http://en.wikipedia.org/wiki/Distributed_revision_control" target="_blank">DVCS</a> </em>que utilizei (de verdade). <strong>Na minha opinião</strong>, ele é mais simples que o <em>Git</em>, é feito em <em>Python</em>, e me atende no desenvolvimento dos meus projetos pessoais.</p>
<p style="text-align: justify;">Concordo com o pessoal que diz que o <em>Git </em>é bom, e concordo com o pessoal que fala que o <em>Mercurial </em>é bom. É perfeitamente possível utilizar estas duas <strong>ferramentas</strong>, não precisamos ser radicais e iniciar um <em>flame </em>em cima deste assunto. A opção é melhor que não ter opção&#8230;</p>
<h3 style="text-align: justify;"><em>GitHub</em> x <em>Bitbucket</em></h3>
<p style="text-align: justify;"><a href="http://www.profissionaisti.com.br/wp-content/uploads/2011/06/bitbucket_and_github.png"><img class="alignleft size-full wp-image-17384" style="margin: 10px;" title="bitbucket_and_github" src="http://www.profissionaisti.com.br/wp-content/uploads/2011/06/bitbucket_and_github.png" alt="" width="132" height="132" /></a>Agora uma coisa eu não posso deixar de concordar: O <em><a title="GitHub, Social coding" href="https://github.com/" target="_blank">GitHub</a> </em>é (na minha opinião) melhor que o <em><a title="Alternativa com Mercurial ao GitHub" href="https://bitbucket.org/" target="_blank">Bitbucket</a></em>.</p>
<p style="text-align: justify;">Ambos são repositórios de código na nuvem, o primeiro usando <em>Git</em> e o segundo usando <em>Mercurial</em>. O detalhe é que o <em>Git </em>tem algumas funções mais apuradas que o <em>Bitbucket</em>, principalmente as funcionalidades que tornam a ferramenta muito mais &#8220;social&#8221;.</p>
<p style="text-align: justify;">Embora o <em>Bitbucket </em>recentemente tenha sido adquirido pela <em>Atlassian </em>e tenha recebido uma forte injencão de melhorias&#8230; o <em>GitHub </em>ainda é, para mim, a melhor forma de compartilhar código que existe no momento.</p>
<p style="text-align: justify;">Venho utilizando o <em>Bitbucket </em>pela opção de poder manter repositórios de código &#8220;fechados&#8221;. Coisa que com o &#8220;rival&#8221; só é possível através de uma conta paga.</p>
<p style="text-align: justify;">Mais uma vez&#8230; é perfeitamente possível viver utilizando as duas <strong>ferramentas</strong>.</p>
<p style="text-align: justify;">Na próxima parte deste <em>post </em>vamos abordar o básico do <em>Mercurial</em>, e também pretendo mostrar como <a title="Como organizar seus projetos Django" href="http://www.profissionaisti.com.br/2011/04/como-organizar-seus-projetos-django/">organizo os meus projetos <em>Django</em></a> &#8220;versionando-os&#8221; com o <em>Mercurial </em>e <em>Bitbucket</em>.</p>
<p style="text-align: justify;">Até a próxima&#8230;</p>
<p style="text-align: justify;"><strong>Fonte: </strong><a title="Como versionar projetos Django com o Mercurial - Parte 1" href="http://www.klauslaube.com.br/2011/05/como-versionar-projetos-django-mercurial-parte/">Blog Klaus Laube</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.profissionaisti.com.br/2011/06/como-versionar-projetos-django-com-o-mercurial-parte-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Como organizar seus projetos Django</title>
		<link>http://www.profissionaisti.com.br/2011/04/como-organizar-seus-projetos-django/</link>
		<comments>http://www.profissionaisti.com.br/2011/04/como-organizar-seus-projetos-django/#comments</comments>
		<pubDate>Mon, 25 Apr 2011 14:20:50 +0000</pubDate>
		<dc:creator>Klaus Peter Laube</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[programação]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.profissionaisti.com.br/?p=16696</guid>
		<description><![CDATA[Olá pessoas! Pretendo compartilhar com vocês a forma que venho utilizando para organizar meus projetos Django com o uso do virtualenv. Não entrarei em muitos detalhes, até porque você verá que é um procedimento muito simples, mas que poderá garantir melhor organização dos seus projetos e dos seus ambientes de desenvolvimento. É interessante que você [...]]]></description>
			<content:encoded><![CDATA[<p>Olá pessoas!</p>
<p style="text-align: justify;">Pretendo compartilhar com vocês a forma que venho utilizando para organizar meus projetos <em><a title="Leia mais sobre Django" href="http://www.profissionaisti.com.br/tag/django/" target="_blank">Django</a></em> com o uso do <em><a title="Leia mais sobre virtualenv" href="http://www.profissionaisti.com.br/tag/virtualenv/" target="_blank">virtualenv</a></em>. Não entrarei em muitos detalhes, até porque você verá que é um procedimento muito simples, mas que poderá garantir melhor organização dos seus projetos e dos seus ambientes de desenvolvimento.</p>
<p style="text-align: justify;">É interessante que você leia o <em>post</em> &#8220;<a title="Leia mais sobre a tríade Python, Django e virtualenv" href="http://www.profissionaisti.com.br/?p=16201"><em>Python</em>, <em>Django</em> e <em>virtualenv</em></a>&#8221; antes de continuar.</p>
<p style="text-align: justify;"><strong>Simplesmente um projeto <em>Django</em></strong></p>
<p style="text-align: justify;">Antes de conhecer (e utilizar) o <em>virtualenv</em>, utilizei algo parecido com o modelo &#8220;tradicional&#8221;  de organização de pastas e códigos em um projeto <em>Django</em>. Ou seja, parecido com aquela estrutura padrão gerada pelo comando <em>django-admin.py startproject</em><em>. </em></p>
<p style="text-align: justify;">O modelo é bom, e funcionou para mim durante muito tempo. Mas de uns tempos para cá venho utilizando o esquema abaixo (<a title="Estrutura de pastas de um TCC que fiz utilizando Django" href="https://bitbucket.org/kplaube/social-portal-for-soccer-players/src" target="_blank">confira um exemplo real</a>):</p>
<pre>mysite/
    apps/
        __init__.py
        eggs/
            fixtures/
                eggs_testdata.json
            tests/
                __init__.py
                models.py
                views.py
            __init__.py
            models.py
            urls.py
            views.py
    core/
        __init__.py
        extras.py
    __init__.py
    manage.py
    settings.py
    urls.py</pre>
<p style="text-align: justify;">A diferença principal está na utilização da pasta <strong>apps </strong>para encapsular as aplicações do projeto, e a criação de uma pasta (ou pacote, como preferir) <strong>core</strong>. Nesta última, gosto de armazenar <em>snippets </em>de código que serão aproveitados pelo projeto inteiro.</p>
<p style="text-align: justify;">Outro ponto que vale ser notado é a criação de uma pasta chamada <strong>tests </strong>para cada <em>app</em>. Embora haja casos em que um arquivo <strong>tests.py </strong>seja o suficiente, podemos nos deparar com um arquivo gigantesco testando vários aspectos de uma <em>app </em>(o que pode dificultar a legibilidade de código). Categorizar os testes por tipo, e em arquivos separados, irá facilitar a adição de novos testes e funcionalidades.</p>
<p style="text-align: justify;">A abordagem dos testes também pode ser utilizada para o <strong>urls.py</strong>. Quando o seu arquivo de roteamento ficar muito grande, crie uma pasta <strong>urls </strong>e &#8220;quebre&#8221; suas rotas em arquivos diferentes. Categorize-os, sinta-se &#8220;<em>zen</em>&#8221; e nunca mais tenha medo de criar <em>URLs </em>novamente <img src='http://www.profissionaisti.com.br/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p style="text-align: justify;">Comecei a utilizar esta estrutura após &#8220;xeretar&#8221; alguns projetos <em>Django open source</em>. Posso dizer por experiência própria que é uma prática interessante, e que tem me ajudado muito na organização de código.</p>
<p style="text-align: justify;"><strong>O projeto <em>Django</em> com o <em>virtualenv</em></strong></p>
<p style="text-align: justify;">Tratando-se do ambiente de desenvolvimento (construído pelo <em>virtualenv</em>), já utilizei-o de duas formas:</p>
<ul style="text-align: justify;">
<li><strong>O <em>environment </em>em uma pasta separada do projeto:</strong> Você pode possuir uma pasta &#8220;<em>environments</em>&#8221; e lá ter diferentes ambientes para diferentes projetos.</li>
<li><strong>O projeto <em>Django </em>ficar dentro da pasta de <em>environment</em>:</strong> Você primeiramente constrói um ambiente com o <em>virtualenv</em>, e depois cria um projeto dentro dessa mesma pasta (como demonstrado <a title="Trabalhando com Python e Django à moda Osvaldo" href="http://blog.triveos.com.br/2010/04/25/trabalhando-com-python-e-django/">neste <em>post </em>do <em>Osvaldo Santana</em></a>).</li>
</ul>
<p style="text-align: justify;">Particularmente eu prefiro a segunda opção (nunca precisei de 2 <em>environments </em>idênticos). Além de manter todo o seu projeto agrupado, fica mais fácil para criação de <em>scripts </em>de automatização de <em>deploy</em>, por exemplo.</p>
<p style="text-align: justify;">No fim das contas, geralmente a estrutura de pastas dos projetos <em>Django </em>fica assim:</p>
<pre>MySiteProject/
    bin/
    include/
    lib/
    mysite/
        apps/
            __init__.py
            eggs/
                fixtures/
                    eggs_testdata.json
                tests/
                    __init__.py
                    models.py
                    views.py
                __init__.py
                models.py
                urls.py
                views.py
        core/
            __init__.py
            extras.py
        __init__.py
        manage.py
        settings.py
        urls.py</pre>
<p style="text-align: justify;">E você? De que forma organiza os seus projetos em <em>Django</em>? Conte-nos através dos comentários abaixo!</p>
<p style="text-align: justify;">Até a próxima&#8230;</p>
<p style="text-align: justify;"><strong>Fonte: </strong><a href="http://www.klauslaube.com.br/2011/04/como-organizar-seus-projetos-django/" target="_blank">Blog Klaus Laube</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.profissionaisti.com.br/2011/04/como-organizar-seus-projetos-django/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Python, Django e virtualenv</title>
		<link>http://www.profissionaisti.com.br/2011/04/python-django-e-virtualenv/</link>
		<comments>http://www.profissionaisti.com.br/2011/04/python-django-e-virtualenv/#comments</comments>
		<pubDate>Mon, 25 Apr 2011 13:48:28 +0000</pubDate>
		<dc:creator>Klaus Peter Laube</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Utilidades]]></category>
		<category><![CDATA[Ambiente]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.profissionaisti.com.br/?p=16201</guid>
		<description><![CDATA[Olá pessoas! Você está começando em Python e vive ouvindo falar sobre um tal de virtualenv? Pois bem, vamos aproveitar para dar uma pincelada nesta útil ferramenta, e como usá-la com nossos amigos Python e Django. Python Conheça alguns motivos que lhe convencerão a usar Python. O Python já vem instalado na maioria das distribuições Linux. [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Olá pessoas!</p>
<p style="text-align: justify;">Você está começando em <em><a title="Leia mais sobre Python" href="http://www.profissionaisti.com.br/tag/python/">Python</a> </em>e vive ouvindo falar sobre um tal de <em><a title="Leia mais sobre virtualenv" href="http://www.profissionaisti.com.br/tag/virtualenv/">virtualenv</a></em>? Pois bem, vamos aproveitar para dar uma pincelada nesta útil ferramenta, e como usá-la com nossos amigos <em>Python </em>e <em><a title="Leia mais sobre Django" href="http://www.profissionaisti.com.br/tag/django/">Django</a></em>.</p>
<p style="text-align: justify;"><strong>Python</strong></p>
<p style="text-align: justify;"><a title="10 motivos para se usar Python" href="http://www.profissionaisti.com.br/2009/01/10-motivos-para-voce-aprender-a-programar-em-python/">Conheça alguns motivos que lhe convencerão a usar <em>Python</em></a>.</p>
<p style="text-align: justify;">O <em>Python</em> já vem instalado na maioria das distribuições <em><a title="Leia mais sobre Linux" href="http://www.profissionaisti.com.br/tag/linux/">Linux</a></em>. Na verdade, até hoje nunca usei uma distro <em>Linux</em> que não tivesse o <em>Python</em> préviamente instalado. No <em>Slackware 13.1</em>, o <em>Python</em> está na versão 2.6.4. No <em>Debian 6</em>, o <em>Python</em> está na versão 2.6.6.</p>
<p style="text-align: justify;">O portal <em>Python Brasil</em> possui um excelente material para você <a title="Inicie-se no Python" href="http://www.python.org.br/wiki/InicieSe">instalar</a> e dar os <a title="Aprenda mais sobre Python" href="http://www.python.org.br/wiki/AprendaMais">primeiros passos</a> com <em>Python</em>.</p>
<p style="text-align: justify;"><strong>virtualenv</strong></p>
<p style="text-align: justify;">A linguagem <em>Python</em> não vem &#8220;de bobeira&#8221; nas distribuições <em>Linux</em>, ela faz parte delas, sendo utilizada para criação de uma série de <em>scripts</em> fundamentais. Passei por uma situação peculiar com o <em>Python</em>: estava usando o <em>OpenSuse</em> (não recordo a versão) e decidi atualizar a versão do <em>Python</em> utilizando o sistema de pacotes da distro&#8230; confirmei algumas operações de remoção (que não deveria ter autorizado) e acabei danificando minha instalação do <em>SO</em>.</p>
<p style="text-align: justify;">Então, para aqueles que programam em computadores pessoais, e não querem comprometer tanto o <em>SO</em> quanto o <em>workspace</em>, podem criar <strong>ambientes isolados</strong> para os projetos utilizando o <em><a title="Virtual Python Environment Builder" href="http://pypi.python.org/pypi/virtualenv">virtualenv</a></em>.</p>
<p style="text-align: justify;">No <em>Slackware</em> vamos instalar o <em><a title="Download, build, install, upgrade, and uninstall Python packages" href="http://pypi.python.org/pypi/setuptools">setuptools</a></em>, que é um <em>framework</em> que facilita a instalação e criação de pacotes <em>Python</em>:</p>
<pre>wget http://peak.telecommunity.com/dist/ez_setup.py</pre>
<p style="text-align: justify;">Para instalá-lo é necessário ser <strong><em>root</em></strong>:</p>
<pre>python ez_setup.py</pre>
<p style="text-align: justify;">Em seguida, vamos instalar o <em>virtualenv</em> com a ajuda do <strong><em>easy_install </em></strong>(que faz parte do pacote <em>setuptools</em>):</p>
<pre>easy_install virtualenv</pre>
<p style="text-align: justify;">Esta é uma forma interessante para você instalar módulos <em>Python</em> em seu sistema sem recorrer ao sistema de pacotes do <em>SO</em>.</p>
<p style="text-align: justify;">Agora, como um <strong>usuário comum</strong>, vamos criar um ambiente em nosso <em>home</em> para testarmos o <strong><em>virtualenv</em></strong>:</p>
<pre>virtualenv ~/projeto_django</pre>
<p style="text-align: justify;">Entrando nesta pasta, você irá se deparar com três diretórios:</p>
<ul style="text-align: justify;">
<li><strong>bin:</strong> Os executáveis do seu ambiente isolado estarão aí. Você poderá notar o executável <em>python</em>, o <em>easy_install</em>, o <em>pip</em> e um carinha chamado &#8220;<em>activate</em>&#8221; (falaremos deste mais tarde).</li>
<li><strong>lib:</strong> Nesta pasta você encontrará os módulos e bibliotecas <em>Python</em> utilizadas por este ambiente.</li>
<li><strong>include:</strong> Segundo o <em><a title="Ambiente Isolado para Python com virtualenv" href="http://blog.triveos.com.br/2008/03/03/ambiente-isolado-para-python-com-virtualenv/">Osvaldo Santana</a></em>, dentro desse diretório estão os <em>links</em> simbólicos para todos os headers do Python que são necessário para se compilar extensões escritas em <em>C</em> para ele.</li>
</ul>
<p style="text-align: justify;">Você apenas criou seu ambiente&#8230; para ativá-lo basta dar o seguinte comando:</p>
<pre>source ~/projeto_django/bin/activate</pre>
<p style="text-align: justify;">Pronto! Se você executar o <em>Python</em> agora, você estará utilizando as <em>libs</em> <strong>deste ambiente</strong>. Isso pode permitir que você mova este ambiente entre máquinas, que você instale <em>libs</em> somente neste ambiente (deixando o <em>Python</em> do seu <em>SO</em> &#8220;limpo&#8221;, isso pode te garantir maior performance da distro) e que você tenha um controle maior sobre as dependências do seu projeto.</p>
<p style="text-align: justify;">Para &#8220;sair&#8221; do ambiente, basta executar o comando <strong><em>deactivate</em></strong>:</p>
<pre>deactivate</pre>
<p style="text-align: justify;">Pronto&#8230; muito simples, não?</p>
<p style="text-align: justify;"><strong>Django</strong></p>
<p style="text-align: justify;"><a title="Programando Python para Web" href="http://www.profissionaisti.com.br/2009/02/programando-python-para-a-web/">Saiba um pouco mais sobre a programação <em>Python </em>para <em>Web</em></a>.</p>
<p style="text-align: justify;">Vamos instalar o <em>Django</em> neste <strong>ambiente isolado</strong>. Ativaremos novamente o <strong><em>virtualenv</em></strong> e usaremos o <strong><em>easy_install</em></strong> para nos ajudar com esta tarefa:</p>
<pre>source ~/projeto_django/bin/activate 
easy_install django</pre>
<p style="text-align: justify;">No final da operação, você irá se deparar com uma saída similar a esta:</p>
<pre>Installed /home/user/projeto_django/lib/python2.6/site-packages/
Django-1.2.5-py2.6.egg 
Processing dependencies for django 
Finished processing dependencies for django</pre>
<p style="text-align: justify;">Isto é a garantia que o <em>Django</em> foi <strong>instalado dentro deste ambiente</strong>, e não está visível para o escopo global da distribuição. Tente importa o <em>django</em> no terminal interativo do <em>Python</em> da sua distro e do <em>Python</em> do seu ambiente isolado e veja o que acontece&#8230;</p>
<p style="text-align: justify;"><a title="Entendendo o Django" href="http://www.profissionaisti.com.br/2009/04/entendendo-o-django/">Entenda o que é o <em>Django </em>e como ele funciona</a>.</p>
<p style="text-align: justify;">Até a próxima&#8230;</p>
<p style="text-align: justify;"><strong>Fonte: </strong><a href="http://www.klauslaube.com.br/2011/03/python-django-virtualenv/" target="_blank">Blog Klaus Laube</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.profissionaisti.com.br/2011/04/python-django-e-virtualenv/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Otimizando projetos em Django com select_related</title>
		<link>http://www.profissionaisti.com.br/2009/11/otimizando-projetos-em-django-com-select_related/</link>
		<comments>http://www.profissionaisti.com.br/2009/11/otimizando-projetos-em-django-com-select_related/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 10:25:38 +0000</pubDate>
		<dc:creator>Francisco Souza</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Desenvolvimento Web]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.profissionaisti.com.br/?p=4690</guid>
		<description><![CDATA[Um dos problemas que vemos na utilização &#8220;padrão&#8221; do Django é a ausência do famigerado join nas consultas geradas pelo ORM do framework. Isto pode ser notado em um exemplo clássico: uma classe de modelo, chamada Pessoa, que tem um relacionamento com outra classe de modelo chamada Carro, bem simples, uma pessoa tem um carro. [...]]]></description>
			<content:encoded><![CDATA[<p>Um dos problemas que vemos na utilização &#8220;padrão&#8221; do Django é a ausência do famigerado <em>join</em> nas consultas geradas pelo ORM do framework. Isto pode ser notado em um exemplo clássico: uma classe de modelo, chamada Pessoa, que tem um relacionamento com outra classe de modelo chamada Carro, bem simples, uma pessoa tem um carro. São executadas duas consultas no banco de dados quando o seguinte código é executado:</p>
<p><code>p = Pessoa.objects.get(id=1)<br />
carro = p.carro</code></p>
<p>Na primeira consulta, o Django busca na tabela de pessoas um registro único no qual o atributo id tem valor 1. Na segunda consulta, o Django busca na tabela de carros o carro que possui o valor da foreign key correspondente ao id do objeto <em>p</em> (instância da classe Pessoa).</p>
<p>Partindo deste pressuposto, é possível ver um número muito grande de problemas. Se for dado um novo modelo de classes, com seis classes: Cliente, Bairro, Cidade, UF, Pais e Continente. Essas classes possuem relacionamentos em cascata: Cliente com Bairro, Bairro com Cidade, e assim sucessivamente, até Continente. Qual seria o comportamento do Django ao tentar acessar o continente de um determinado cliente? O interpretador interativo do Python responde esta questão de maneira bem simples:</p>
<p><code>&gt;&gt;&gt; cliente = Cliente.objects.get(id=1)<br />
&gt;&gt;&gt; continente = cliente.bairro.cidade.uf.pais.continente<br />
&gt;&gt;&gt; from django.db import connection<br />
&gt;&gt;&gt; queries = connection.queries<br />
&gt;&gt;&gt; for query in queries:<br />
...        print query<br />
...<br />
{'time': '0.003', 'sql': u'SELECT "clientes_cliente"."id", "clientes_cliente"."nome", "clientes_cliente"."idade", "clientes_cliente"."bairro_id" FROM "clientes_cliente" WHERE "clientes_cliente"."id" = 1 '}<br />
{'time': '0.000', 'sql': u'SELECT "clientes_bairro"."id", "clientes_bairro"."nome", "clientes_bairro"."cidade_id" FROM "clientes_bairro" WHERE "clientes_bairro"."id" = 1 '}<br />
{'time': '0.000', 'sql': u'SELECT "clientes_cidade"."id", "clientes_cidade"."nome", "clientes_cidade"."uf_id" FROM "clientes_cidade" WHERE "clientes_cidade"."id" = 1 '}<br />
{'time': '0.000', 'sql': u'SELECT "clientes_uf"."id", "clientes_uf"."sigla", "clientes_uf"."pais_id" FROM "clientes_uf" WHERE "clientes_uf"."id" = 1 '}<br />
{'time': '0.000', 'sql': u'SELECT "clientes_pais"."id", "clientes_pais"."nome", "clientes_pais"."continente_id" FROM "clientes_pais" WHERE "clientes_pais"."id" = 1 '}<br />
{'time': '0.000', 'sql': u'SELECT "clientes_continente"."id", "clientes_continente"."nome" FROM "clientes_continente" WHERE "clientes_continente"."id" = 1 '}<br />
&gt;&gt;&gt;</code></p>
<p>Aí está a resposta quanto ao comportamento do Django: duas linhas de código, seis consultas ao banco de dados. Se esta fosse uma informação muito importante em um sistema, é possível notar o quão doloroso seria manter tudo isso num banco de dados relacional. É necessária uma abordagem diferente, com apenas um join seis consultas virariam apenas uma e o programador poderia dormir sem medo do DBA.</p>
<p>A instrução <em>select_related</em> responde à esta necessidade: ao ver esta instrução, o Django sabe que ele tem que fazer os joins, e que ele deve &#8220;passear&#8221; por todos os relacionamentos obtendo os dados. Se o cliente for buscado no banco de dados utilizando <em>select_related</em>, o objeto estará completamente em memória, e não será necessário acessar o banco de dados novamente para obter informações de nenhum dos relacionamentos, o interpretador interativo prova isso:</p>
<p><code>&gt;&gt;&gt; cliente = Cliente.objects.select_related().get(id=1)<br />
&gt;&gt;&gt; continente = cliente.bairro.cidade.uf.pais.continente<br />
&gt;&gt;&gt; from django.db import connection<br />
&gt;&gt;&gt; queries = connection.queries<br />
&gt;&gt;&gt; for query in queries:<br />
...         print query<br />
...<br />
{'time': '0.010', 'sql': u'SELECT "clientes_cliente"."id", "clientes_cliente"."nome", "clientes_cliente"."idade", "clientes_cliente"."bairro_id", "clientes_bairro"."id", "clientes_bairro"."nome", "clientes_bairro"."cidade_id", "clientes_cidade"."id", "clientes_cidade"."nome", "clientes_cidade"."uf_id", "clientes_uf"."id", "clientes_uf"."sigla", "clientes_uf"."pais_id", "clientes_pais"."id", "clientes_pais"."nome", "clientes_pais"."continente_id", "clientes_continente"."id", "clientes_continente"."nome" FROM "clientes_cliente" INNER JOIN "clientes_bairro" ON ("clientes_cliente"."bairro_id" = "clientes_bairro"."id") INNER JOIN "clientes_cidade" ON ("clientes_bairro"."cidade_id" = "clientes_cidade"."id") INNER JOIN "clientes_uf" ON ("clientes_cidade"."uf_id" = "clientes_uf"."id") INNER JOIN "clientes_pais" ON ("clientes_uf"."pais_id" = "clientes_pais"."id") INNER JOIN "clientes_continente" ON ("clientes_pais"."continente_id" = "clientes_continente"."id") WHERE "clientes_cliente"."id" = 1 '}<br />
&gt;&gt;&gt; </code></p>
<p>Problema de consultas resolvido, DBA feliz = programador feliz = cliente feliz! <img src='http://www.profissionaisti.com.br/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.profissionaisti.com.br/2009/11/otimizando-projetos-em-django-com-select_related/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Django 1.1 lançado!</title>
		<link>http://www.profissionaisti.com.br/2009/07/django-11-lancado/</link>
		<comments>http://www.profissionaisti.com.br/2009/07/django-11-lancado/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 20:31:56 +0000</pubDate>
		<dc:creator>Klaus Peter Laube</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[nasa]]></category>
		<category><![CDATA[programação]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.profissionaisti.com.br/?p=3541</guid>
		<description><![CDATA[Olá pessoal&#8230; Depois de meses de desenvolvimento, a versão stable do Django 1.1 finalmente vê a &#8220;luz do dia&#8221;. Com uma série de implementos, correções de bugs e aprimoramentos em segurança, o Django 1.1 já vinha enchendo de orgulho a sua comunidade, ainda mais agora com o anúncio da NASA declarando que utiliza Django em [...]]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal&#8230;</p>
<p>Depois de meses de desenvolvimento, a versão <em>stable</em> do <a title="Django 1.1 Release Notes" href="http://www.djangoproject.com/weblog/2009/jul/29/1-point-1/" target="_blank">Django 1.1</a> finalmente vê a &#8220;luz do dia&#8221;.</p>
<p>Com uma série de implementos, correções de bugs e aprimoramentos em segurança, o Django 1.1 já vinha enchendo de orgulho a sua comunidade, ainda mais agora com o <a title="Conheça melhor o projeto NEBULA" href="http://nebula.nasa.gov/services/framework" target="_blank">anúncio da NASA declarando que utiliza Django em sua plataforma de <em>cloud computing</em></a>.</p>
<p>Nada como acordar pela manhã e saber que fez a escolha certa <img src='http://www.profissionaisti.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Tá esperando o que pra <a title="Get Django ;)" href="http://www.djangoproject.com/download/" target="_blank">baixar</a>?</p>
<p>Até a próxima&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.profissionaisti.com.br/2009/07/django-11-lancado/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

