<?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>Destaqueblog &#187; django</title>
	<atom:link href="http://weblog.destaquenet.com/tag/django/feed/" rel="self" type="application/rss+xml" />
	<link>http://weblog.destaquenet.com</link>
	<description>Blog da equipe Destaquenet.</description>
	<lastBuildDate>Tue, 12 Jan 2010 13:32:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Você gostaria de ver Django-flash incluído no Django como uma Contrib app?</title>
		<link>http://weblog.destaquenet.com/2009/06/19/voce-gostaria-de-ver-django-flash-incluido-no-django-como-uma-contrib-app/</link>
		<comments>http://weblog.destaquenet.com/2009/06/19/voce-gostaria-de-ver-django-flash-incluido-no-django-como-uma-contrib-app/#comments</comments>
		<pubDate>Fri, 19 Jun 2009 15:14:46 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Off Topic]]></category>
		<category><![CDATA[Português]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[contrib]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[django-flash]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[projeto]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=535</guid>
		<description><![CDATA[Django-flash, um despretencioso projeto de software livre desenvolvido pela Destaquenet, tem recebido excelentes críticas por quem o vem utilizando regularmente. Sua adoção vem crescendo vagarosamente, mas consistentemente. Nem preciso dizer o quanto isso é gratificante para nós.
De um tempo para cá, eu fui contactado por alguns desses usuários perguntando sobre a possibilidade de ter o [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://djangoflash.destaquenet.com">Django-flash</a>, um despretencioso projeto de <em>software</em> livre desenvolvido pela <a href="http://www.destaquenet.com">Destaquenet</a>, tem recebido excelentes críticas por quem o vem utilizando regularmente. Sua adoção vem crescendo vagarosamente, mas consistentemente. Nem preciso dizer o quanto isso é gratificante para nós.</p>
<p>De um tempo para cá, eu fui contactado por alguns desses usuários perguntando sobre a possibilidade de ter o nosso projeto incluído na distribuição do <a href="http://www.djangoproject.com/">Django</a>, na forma de uma <a href="http://docs.djangoproject.com/en/dev/ref/contrib/">Contrib app</a>. Eu achei a idéia excelente, pois eu penso que um <em>framework</em> como o Django deveria se preocupar em resolver um <a href="http://weblog.destaquenet.com/2009/02/06/mensagens-flash-a-la-rails-para-django-com-django-flash/">problema tão recorrente</a> quanto este que o Django-flash se propõe a resolver.</p>
<p>Se você utiliza Django-flash em seus projetos, não deixe de acompanhar <a href="http://code.djangoproject.com/ticket/4604">essa discussão</a>. Se possível, nos dê sua opinião sobre o que poderia ser feito para melhorar ainda mais o projeto e, assim, facilitar sua inclusão no Django.</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2009/06/19/voce-gostaria-de-ver-django-flash-incluido-no-django-como-uma-contrib-app/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Django e settings.py: dicas e boas práticas</title>
		<link>http://weblog.destaquenet.com/2009/04/13/django-e-settingspy-dicas-e-boas-praticas/</link>
		<comments>http://weblog.destaquenet.com/2009/04/13/django-e-settingspy-dicas-e-boas-praticas/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 02:32:06 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[configuração]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[testes]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=415</guid>
		<description><![CDATA[Em vez de ficar rasgando elogios ao Django, como de costume, eu tentarei aproveitar o melhor o meu (e o seu) tempo e mostrar algo que é de fato útil. O assunto em questão envolve o módulo settings.py, cuja função é fornecer as configurações necessárias para que o projeto funcione. Apesar deste módulo ser uma [...]]]></description>
			<content:encoded><![CDATA[<p>Em vez de ficar rasgando elogios ao <a href="http://djangoproject.com">Django</a>, como de costume, eu tentarei aproveitar o melhor o meu (e o seu) tempo e mostrar algo que é de fato útil. O assunto em questão envolve o módulo <code>settings.py</code>, cuja função é fornecer as configurações necessárias para que o projeto funcione. Apesar deste módulo ser uma peça importante em qualquer projeto Django, pouco se fala sobre ele, ou sobre boas práticas associadas a ele. Por isso, achei que seria interessante mostrar a minha visão pessoal sobre o assunto.</p>
<h3>O poder do Python</h3>
<p>Quem não está acostumado a trabalhar com Django pode estranhar o fato deste utilizar um script <a href="http://python.org">Python</a> para fazer a configuração do projeto: o famoso <code>settings.py</code>. E essa estranheza é justificada, afinal muitos desenvolvedores &#8212; principalmente os que vêm de outras linguagens &#8212; estão acostumados a trabalhar com ferramentas onde tal tarefa é feita com arquivos XML ou coisa assim.</p>
<p>O fato é que utilizar um script Python para tal é uma excelente idéia, pois você deixa de depender de algum tipo de estrutura estática (e muitas vezes inconveniente) para algo mais flexível e poderoso, que, no caso, é a própria linguagem de programação. Isso faz uma grande diferença em situações onde tal flexibilidade é necessária.</p>
<p>Quer exemplos?<span id="more-415"></span></p>
<h3>Ambientes de desenvolvimento/produção</h3>
<p>Eis como fizemos aqui. Primeiramente, defina a variável de ambiente <code>WORKSPACE</code>. No Linux, isso pode ser feito através do arquivo <code>~/.bashrc</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">WORKSPACE</span>=<span style="color: #000000;">1</span></pre></div></div>

<p>A idéia é possibilitar a criação de perfis de configuração, cada qual correspondente a um ambiente de execução. A existência ou não da variável de ambiente é o que define o ambiente no qual a aplicação roda.</p>
<p>Continuando com o exemplo, no diretório raíz do seu projeto Django, crie o módulo <code>environment.py</code>, com o seguinte conteúdo:</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;">os</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> production_mode<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff7700;font-weight:bold;">not</span> development_mode<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> development_mode<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">'WORKSPACE'</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span></pre></div></div>

<p>Finalmente, modifique o módulo <code>settings.py</code> para que este utilize tais métodos onde for necessário definir configurações diferentes para ambientes de execução diferentes:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> environment <span style="color: #ff7700;font-weight:bold;">import</span> production_mode
&nbsp;
<span style="color: #808080; font-style: italic;"># Configurações padrão</span>
PREPEND_WWW = <span style="color: #008000;">False</span>
DEBUG = <span style="color: #008000;">True</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Configurações para ambiente de produção</span>
<span style="color: #ff7700;font-weight:bold;">if</span> production_mode<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    PREPEND_WWW = <span style="color: #008000;">True</span>
    DEBUG = <span style="color: #008000;">False</span>
&nbsp;
MIDDLEWARE_CLASSES = <span style="color: black;">&#40;</span>
    <span style="color: #483d8b;">'django.middleware.common.CommonMiddleware'</span>,
    <span style="color: #483d8b;">'django.contrib.sessions.middleware.SessionMiddleware'</span>,
    <span style="color: #483d8b;">'django.contrib.auth.middleware.AuthenticationMiddleware'</span>,
    <span style="color: #483d8b;">'django.middleware.doc.XViewMiddleware'</span>,
    <span style="color: #483d8b;">'pages.middleware.PageFallbackMiddleware'</span>,
    <span style="color: #483d8b;">'django.contrib.redirects.middleware.RedirectFallbackMiddleware'</span>,
<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Habilitando caching em modo de produção</span>
<span style="color: #ff7700;font-weight:bold;">if</span> production_mode<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    MIDDLEWARE_CLASSES += <span style="color: black;">&#40;</span>
        <span style="color: #483d8b;">'django.middleware.cache.UpdateCacheMiddleware'</span>,
        <span style="color: #483d8b;">'django.middleware.cache.FetchFromCacheMiddleware'</span>,
    <span style="color: black;">&#41;</span></pre></div></div>

<p>Não tenha medo de utilizar os recursos do Python onde eles se fizerem necessários, apenas tomando cuidado para não exagerar e acabar criando acidentalmente um <a href="http://en.wikipedia.org/wiki/Genetic_algorithm">Algoritmo Genético</a> para configurar seu projeto!</p>
<h3>Informações secretas (IPs, usernames, passwords, etc)</h3>
<p>Praticamente não há quem ignore a importância de um bom sistema de controle de revisões (<a href="http://subversion.tigris.org">Subversion</a>, <a href="http://git-scm.org">Git</a>, etc). O problema é que, muitas vezes, não tomamos o devido cuidado com o que colocamos dentro dos nossos repositórios. Sempre que possível, informações secretas &#8212; como endereços de IP, usernames e passwords &#8212; devem ser mantidas fora dos repositórios.</p>
<p>Em um projeto Django, as informações de acesso a servidores de e-mail e bancos de dados devem estar disponíveis através do módulo  <code>settings.py</code>. Felizmente, existe um jeito simples de manter essas informações separadas das outras configurações.</p>
<p>Primeiramente, abra o arquivo <code>settings.py</code> do seu projeto e remova todas as senhas e outras informações que você considere secretas. Em seguida, cole o seguinte trecho de código no final do arquivo:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">from</span> private <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span></pre></div></div>

<p>Feito isso, crie o módulo <code>private.py</code> no diretório raíz do seu projeto Django. Coloque nele as configurações que você removeu do <code>settings.py</code> no passo anterior. Exemplo:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> environment <span style="color: #ff7700;font-weight:bold;">import</span> production_mode
&nbsp;
SECRET_KEY = <span style="color: #483d8b;">'secret_key_do_seu_projeto'</span>
&nbsp;
EMAIL_HOST = <span style="color: #483d8b;">'localhost'</span>
EMAIL_HOST_PASSWORD = <span style="color: #483d8b;">'senha_email_local'</span>
&nbsp;
DATABASE_HOST = <span style="color: #483d8b;">'localhost'</span>
DATABASE_USER = <span style="color: #483d8b;">'username_db_local'</span>
DATABASE_PASSWORD = <span style="color: #483d8b;">'senha_db_local'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> production_mode<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    EMAIL_HOST = <span style="color: #483d8b;">'ip_email_producao'</span>
    EMAIL_HOST_PASSWORD = <span style="color: #483d8b;">'senha_email_producao'</span>
&nbsp;
    DATABASE_HOST = <span style="color: #483d8b;">'ip_db_producao'</span>
    DATABSE_USER = <span style="color: #483d8b;">'username_db_producao'</span>
    DATABASE_PASSWORD = <span style="color: #483d8b;">'senha_db_producao'</span></pre></div></div>

<p>Certifique-se de adicionar o arquivo <code>private.py</code> no <em>ignore</em> (<code>.cvsignore</code> para <a href="http://www.nongnu.org/cvs/">CVS</a>, <code>.gitignore</code> para Git, etc) correspondente ao sistema de controle de revisões sendo utilizado. Faça o commit e pronto.</p>
<p>Para finalizar, se o seu repositório já contém uma versão &#8220;insegura&#8221; do módulo <code>settings.py</code>, mude as senhas dos seus servidores.</p>
<h3>E você, o que recomenda?</h3>
<p>Tem alguma dica útil para compartilhar conosco? Nós adoraríamos ouvir o que você tem a dizer!</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2009/04/13/django-e-settingspy-dicas-e-boas-praticas/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Mensagens flash a la Rails para Django com django-flash</title>
		<link>http://weblog.destaquenet.com/2009/02/06/mensagens-flash-a-la-rails-para-django-com-django-flash/</link>
		<comments>http://weblog.destaquenet.com/2009/02/06/mensagens-flash-a-la-rails-para-django-com-django-flash/#comments</comments>
		<pubDate>Sat, 07 Feb 2009 01:17:42 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[aplicação]]></category>
		<category><![CDATA[destaquenet]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[projeto]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=328</guid>
		<description><![CDATA[Minha história com o Django começou mais ou  menos em Junho do ano passado, enquanto procurava uma ferramenta adequada a ser utilizada num trabalho que precisava ser feito na época.
Francamente, eu achava que não iria dar certo, talvez por culpa de uma screencast horrível que eu acabara de ver, não sei. Mas o fato é [...]]]></description>
			<content:encoded><![CDATA[<p>Minha história com o <a href="http://www.djangoproject.com/">Django</a> começou mais ou  menos em Junho do ano passado, enquanto procurava uma ferramenta adequada a ser utilizada num trabalho que precisava ser feito na época.</p>
<p>Francamente, eu achava que não iria dar certo, talvez por culpa de uma screencast horrível que eu acabara de ver, não sei. Mas o fato é que, contrariando minhas expectativas, o Django vem se mostrando uma ferramenta muito interessante. Se você ainda não conhece, veja você mesmo o que Django (e <a href="http://www.python.org/">Python</a>, claro!) podem fazer por você.</p>
<p>Mas voltando ao assunto, a primeira vez que precisei usar algo que o Django não oferecia por padrão foi quando tentei utilizar um recurso muito querido  pelo pessoal do <a href="http://rubyonrails.org/">Rails</a>: as <a href="http://api.rubyonrails.org/classes/ActionController/Flash.html">mensagens <em>flash</em></a>.<sup class='footnote'><a href='#fn-328-1' id='fnref-328-1'>1</a></sup> Por esse motivo, eu comecei um projeto <a href="http://www.destaquenet.com/opensource/">open source</a> chamado <a href="http://djangoflash.destaquenet.com/">django-flash</a>, cujo objetivo é (pasmem!) levar as mensagens flash do Rails ao Django. <img src='http://weblog.destaquenet.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>O projeto vem sido desenvolvido no meu tempo livre e hoje chega à <a href="http://pypi.python.org/pypi/django-flash/1.4.1">versão 1.4.1</a>, oferecendo todos os recursos então presentes no seu irmão mais velho. Acredito que o projeto chegou num grau interessante de maturidade: API estável, documentação abundante, código extremamente bem comentado e apoiado por testes (unitários e de integração).</p>
<p>Portanto, se você precisa de algo semelhante às mensagens <em>flash</em> do Rails em seu projeto Django, não deixe de conferir o <a href="http://djangoflash.destaquenet.com/">site do projeto</a>. Conto com a ajuda de vocês para tornar este projeto cada vez melhor!</p>
<p>Um bom fim de semana a todos!
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-328-1'>Na verdade a app <a href="http://docs.djangoproject.com/en/dev/topics/auth/">contrib.auth</a> do Django possui um método <code>user.message_set.create()</code>, que, convenhamos, é um <em>hack</em>. Além do mais, ele só funciona se o usuário estiver logado no site. <span class='footnotereverse'><a href='#fnref-328-1'>&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2009/02/06/mensagens-flash-a-la-rails-para-django-com-django-flash/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Deployment de aplicações Python com Fabric</title>
		<link>http://weblog.destaquenet.com/2008/10/05/deployment-de-aplicacoes-python-com-fabric/</link>
		<comments>http://weblog.destaquenet.com/2008/10/05/deployment-de-aplicacoes-python-com-fabric/#comments</comments>
		<pubDate>Sun, 05 Oct 2008 10:00:05 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[fabric]]></category>
		<category><![CDATA[ferramenta]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=101</guid>
		<description><![CDATA[Uma coisa é fato: subir uma nova versão de uma aplicação é um procedimento que, se feito manualmente, costuma demandar tempo precioso, independente do tamanho da aplicação e dos frameworks utilizados no projeto. Não há o que discutir.
Na verdade, ninguém parecia se importar em automatizar tarefas &#8220;mecânicas&#8221; como o deployment, coisa que mudou de figura [...]]]></description>
			<content:encoded><![CDATA[<p>Uma coisa é fato: subir uma nova versão de uma aplicação é um procedimento que, se feito manualmente, costuma demandar tempo precioso, independente do tamanho da aplicação e dos <em>frameworks</em> utilizados no projeto. Não há o que discutir.</p>
<p>Na verdade, ninguém parecia se importar em automatizar tarefas &#8220;mecânicas&#8221; como o <em>deployment</em>, coisa que mudou de figura ao passo que <a href="http://en.wikipedia.org/wiki/Agile_software_development">metodologias ágeis</a> &#8212; juntamente com técnicas como <a href="http://martinfowler.com/articles/continuousIntegration.html">Integração Contínua</a> &#8212; passaram a se tornar populares. Desde então, algum esforço vem sendo investido para criar ferramentas para automatização de muitas dessas tarefas. <span id="more-101"></span></p>
<h3>Fabric: ferramenta Python para deployment</h3>
<p>Apesar de já ter utilizado algumas dessas <a href="http://maven.apache.org/">ferramentas</a> no desenvolvimento de projetos em <a href="http://java.sun.com/">Java</a>, plataforma na qual eu possuo uma experiência maior, eu ainda não conhecia nenhuma ferramenta em <a href="http://python.org/">Python</a> que me permitisse automatizar o <em>deployment</em> de uma aplicação.</p>
<p>Como eu estava começando a ficar de saco cheio de ter que atualizar os arquivos de uma aplicação <a href="http://djangoproject.org/">Django</a> via SCP, eu resolvi que já era hora de ir atrás de alguma ferramenta que me ajudasse a automatizar esse processo. Finalmente, depois de muita procura, eu encontrei <a href="http://www.nongnu.org/fab/index.html">Fabric</a>, uma ferramenta mais ou menos parecida com um <a href="http://www.capify.org/">Capistrano</a> &#8220;capado&#8221;.</p>
<p>A instalação do Fabric é bem simples para quem costuma usar o <a href="http://peak.telecommunity.com/DevCenter/EasyInstall">easy_install</a>:</p>
<pre>daniel ~ $ sudo easy_install Fabric</pre>
<p>Basta executar esse comando para que os fontes da última versão do Fabric (0.0.9 no momento da publicação deste texto) sejam baixados e instalados.</p>
<p><strong>Atenção</strong>: Quem utiliza máquinas Windows, provavelmente precisará do <a href="http://www.cygwin.com/">Cygwin</a>, já que o Fabric assume o uso de ambientes Unix.</p>
<h3>Fabric a 3.000 pés</h3>
<p>Neste momento você já deve conseguir executar o comando <code>fab</code> no terminal. Se tudo correu bem até aqui, estamos prontos continuar.</p>
<p>Vamos começar criando o arquivo <code>fabfile.py</code> no diretório-raíz da aplicação. Coloque o seguinte conteúdo neste arquivo:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">set</span><span style="color: black;">&#40;</span>
    project = <span style="color: #483d8b;">'project_name'</span>,
&nbsp;
    package     = <span style="color: #483d8b;">'$(project).zip'</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Remote servers</span>
    fab_user    = <span style="color: #483d8b;">'usuario_ssh'</span>,
    fab_hosts   = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'servidor1.com'</span>, <span style="color: #483d8b;">'servidor2.com'</span><span style="color: black;">&#93;</span>,
<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> deploy<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;Deploy the application to the production servers.&quot;</span>
    build<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> build<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;Build the application.&quot;</span>
    prepare<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> prepare<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;Prepare the build directory.&quot;</span>
    clean<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> clean<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;Remove the build directory.&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">pass</span></pre></div></div>

<p>Cada método definido no arquivo é equivalente a uma <em>task</em> do Capistrano. No início temos o método <code>set</code> que nos permite configurar as variáveis necessárias para o <em>script</em>. Veja que, neste método <code>set</code>, indicamos na variável <code>fab_hosts</code> os servidores nos quais os comandos remotos devem ser executados.</p>
<p>Ok, tente executar o comando <code>fab</code> no terminal, no mesmo diretório onde se encontra o arquivo <code>fabfile.py</code>. Se tudo correr bem, você receberá a seguinte saída:</p>
<pre>daniel ~  $  fab
   Fabric v. 0.0.9, Copyright (C) 2008 Christian Vest Hansen.
   Fabric comes with ABSOLUTELY NO WARRANTY; for details type `fab warranty'.
   This is free software, and you are welcome to redistribute it
   under certain conditions; type `fab license' for details.

No commands given.
Available commands are:
   build    : Build the application.
   clean    : Remove the build directory.
   deploy   : Deploy the application to the production servers.
   help     : Display Fabric usage help, or help for a given command.
   license  : Display the Fabric distribution license text.
   list     : Display a list of commands with descriptions.
   prepare  : Prepare the build directory.
   set      : Set a Fabric variable.
   shell    : Start an interactive shell connection to the specified hosts.
   warranty : Display warranty information for the Fabric software.
Done.</pre>
<p>Veja que as <em>tasks</em> que criamos estão disponíveis para serem executadas via linha de comando. Para executar as <em>tasks</em> <code>clean</code> e <code>deploy</code>, por exemplo, utilizaríamos o seguinte comando:</p>
<pre>daniel ~  $  fab clean deploy</pre>
<p>Simples, não é? Antes de vermos um exemplo de script completo, vamos conhecer os três principais métodos utilizados em <em>scripts</em> Fabric: <code>local</code>, <code>run</code> e <code>put</code>:</p>
<ul>
<li><code>local</code>: Serve para executar comandos na máquina local. Ex: <code>local('mkdir build')</code>;</li>
<li><code>run</code>: Igual ao <code>local</code>, mas executa os comandos nas máquinas remotas (indicadas na variável <code>fab_hosts</code>);</li>
<li><code>put</code>: Envia um arquivo para as máquinas remotas. Ex: <code>put('arquivo.zip', '/home/user/app.zip')</code>.</li>
</ul>
<p>Antes de prosseguirmos, vamos voltar a olhar a chamada ao método <code>set</code>, no início do código. Nele, eu usei um recurso do Fabric conhecido como <em>lazy evaluation</em>. No caso, temos a variável <code>package</code> que recebe o valor <code>'$(project).zip'</code>. Esse <code>$(project)</code> indica que queremos que o valor da variável <code>project</code> substitua o <em>placeholder</em>. Isso permite que variáveis sejam interpoladas umas dentro das outras.</p>
<p>Por exemplo, se dentro de uma <em>task</em> executarmos o comando <code>local('rm $(package)')</code>, isso significa que o Fabric irá parsear a string, transformando-a em <code>'rm project_name'</code> para só então executar tal comando na máquina local.</p>
<p>Como veremos a seguir, eu utilizei este recurso exaustivamente no meu <em>script</em>. Em caso de dúvidas, consulte a <a href="http://www.nongnu.org/fab/user_guide.html">documentação</a> do Fabric.</p>
<h3>Finalmente, o script completo!</h3>
<p>Antes de mostrar o <em>script</em> que eu venho utilizando para fazer o deployment <a href="http://www.destaquenet.com/">de uma aplicação</a> Django, veja como seus arquivos e diretórios estão organizados: (isso deve ajudar a entender melhor o <em>script</em>)</p>
<div id="attachment_131" class="wp-caption aligncenter" style="width: 214px"><a href="http://weblog.destaquenet.com/wp-content/uploads/2008/10/destaqueweb_structure.png"><img src="http://weblog.destaquenet.com/wp-content/uploads/2008/10/destaqueweb_structure-204x300.png" alt="Estrutura do projeto" title="Estrutura do projeto" width="204" height="300" class="size-medium wp-image-131" /></a><p class="wp-caption-text">Estrutura do projeto</p></div>
<p>E, finalmente, o <em>script</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">set</span><span style="color: black;">&#40;</span>
    project = <span style="color: #483d8b;">'destaqueweb'</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Build output directory</span>
    build_path  = <span style="color: #483d8b;">'build'</span>,
    package     = <span style="color: #483d8b;">'$(project).zip'</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Media</span>
    media_src   = <span style="color: #483d8b;">'media'</span>,
    media_root  = <span style="color: #483d8b;">'public_html'</span>,
    media_path  = <span style="color: #483d8b;">'$(media_root)/$(project)/$(media_src)'</span>,
    media_build = <span style="color: #483d8b;">'$(build_path)/$(media_path)'</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Application code</span>
    app_root  = <span style="color: #483d8b;">'wsgi_apps'</span>,
    app_path  = <span style="color: #483d8b;">'$(app_root)/$(project)'</span>,
    app_build = <span style="color: #483d8b;">'$(build_path)/$(app_path)'</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Remote servers</span>
    fab_user    = <span style="color: #483d8b;">'destaquenet'</span>,
    fab_hosts   = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'destaquenet.com'</span><span style="color: black;">&#93;</span>,
&nbsp;
    destination = <span style="color: #483d8b;">'/home/destaquenet'</span>,
    touch       = <span style="color: #483d8b;">'$(destination)/$(media_root)/$(project)/index.wsgi'</span>,
<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> deploy<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;Deploy the application to the production server.&quot;</span>
    build<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Upload the zip file</span>
    put<span style="color: black;">&#40;</span><span style="color: #483d8b;">'$(build_path)/$(package)'</span>, <span style="color: #483d8b;">'$(destination)/$(package)'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Extract the zip file</span>
    run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'cd $(destination); unzip -uo $(package); rm $(package)'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Reload the application</span>
    run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'touch $(touch)'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> build<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;Build the application.&quot;</span>
    prepare<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Copy application files to the build directory</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'cp -R $(project)/* $(build_path)/$(app_path)'</span><span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'cp -R $(media_src)/* $(build_path)/$(media_path)'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Remove unecessary files</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'find $(build_path) -name *.pyc -delete'</span><span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'find $(build_path) -path *upload* -delete'</span><span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'find $(build_path) -path *fixtures* -delete'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Create the zip file</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'cd $(build_path);zip -r $(package) $(media_root) $(app_root)'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> prepare<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;Prepare the build directory.&quot;</span>
    clean<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mkdir -p $(media_build)'</span><span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mkdir -p $(app_build)'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> clean<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;Remove the build directory.&quot;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'rm -fR $(build_path)'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Este código deve ser facilmente entendido por quem tem trabalha com uma certa facilidade no terminal.</p>
<p>Basicamente o que o código faz é organizar os arquivos da aplicação para que estes fiquem dispostos da mesma forma utilizada pelo servidor de produção, enviar os arquivos dentro de um pacote ZIP para os servidores e descompactá-los no local correto, além de executar um <code>touch</code> no <em>script</em> <acronym title="Web Server Gateway Interface">WSGI</acronym> para que o <a href="http://apache.org/">Apache</a> recarregue a aplicação.</p>
<p>Tudo pronto. Agora basta executar <code>fab deploy</code> no terminal para subir a aplicação para o(s) servidor(es) desejado(s).</p>
<h3>Fabric e ambiente de homologação</h3>
<p>Uma coisa que vem se tornando comum é o uso de diferentes ambientes onde uma aplicação costuma ser implantada (ex: ambiente de homologação). Se sua empresa costuma trabalhar dessa forma, o Fabric ainda pode te ajudar.</p>
<p>Por exemplo, vamos supor que sua empresa possua um servidor de produção e um servidor de homologação. Podemos, então, adequar o <em>script</em> para que ele possa trabalhar com ambos os ambientes:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">set</span><span style="color: black;">&#40;</span>
    <span style="color: #808080; font-style: italic;"># ...</span>
    fab_user = <span style="color: #483d8b;">'production'</span>,
    fab_hosts = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'app.com'</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> staging<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># deploy to staging servers</span>
    <span style="color: #008000;">set</span><span style="color: black;">&#40;</span>fab_user = <span style="color: #483d8b;">'staging'</span>, fab_hosts = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'staging.app.com'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># other tasks...</span></pre></div></div>

<p>Fazendo as mudanças mostradas acima, para executar o <em>deployment</em> no ambiente de homologação basta rodar o comando <code>fab staging deploy</code>; o deployment em ambiente de produção continua disponível através do comando <code>fab deploy</code>.</p>
<p>Isso é possível pois podemos substituir o valor de uma variável (ou configurar novas variáveis) a qualquer momento, através do método <code>set</code>. Então, quando executamos o comando <code>fab staging deploy</code>, o Fabric executa a <em>task</em> <code>staging</code>, substituindo o valor das variáveis <code>fab_user</code> e <code>fab_hosts</code>, fazendo com que os comandos contidos na <em>task</em> <code>deploy</code> sejam executados nos servidores de homologação em vez de nos servidores de produção.</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2008/10/05/deployment-de-aplicacoes-python-com-fabric/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
