<?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>Sun, 15 Aug 2010 03:14:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1-alpha</generator>
		<item>
		<title>Django Para Dispositivos Móveis</title>
		<link>http://weblog.destaquenet.com/2010/07/12/django-para-dispositivos-moveis/</link>
		<comments>http://weblog.destaquenet.com/2010/07/12/django-para-dispositivos-moveis/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 11:10:21 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[configuração]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[dispositivo]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[móvel]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=944</guid>
		<description><![CDATA[Estamos vivendo o que alguns chamam de &#8220;explosão mobile&#8221;, um tempo onde um número cada vez maior de dispositivos móveis &#8212; como tablets e smartphones &#8212; se tornam parte significante da Web. Esta é a razão pela qual ter seu &#8230; <a href="http://weblog.destaquenet.com/2010/07/12/django-para-dispositivos-moveis/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Estamos vivendo o que alguns chamam de &#8220;explosão mobile&#8221;, um tempo onde um número cada vez maior de dispositivos móveis &#8212; como tablets e smartphones &#8212; se tornam parte significante da Web. Esta é a razão pela qual ter seu website preparado para tais dispositivos é cada vez mais importante.</p>
<p>Felizmente, <a href="http://djangoproject.com/">Django</a> é um dos poucos frameworks web que tornam este um problema simples de solucionar.</p>
<p><span id="more-944"></span></p>
<h3>Como resolvemos este problema</h3>
<p>Um jeito simples é criar um módulo <code>settings.py</code> separado para a versão &#8220;mobile&#8221;. Isso nos permite rodar dois sites diferentes reusando a mesma base de código. Além disso, cada versão pode ter seu próprio diretório de templates, configurações de URL, etc.</p>
<p>Vamos fazer isso. No diretório-raíz do projeto, crie um arquivo <code>m_settings.py</code> com o seguinte conteúdo:</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #808080; font-style: italic;"># Arquivo: myproject/m_settings.py</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Configurações para a versão &quot;mobile&quot; do website.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Carrega as configurações padrão</span>
<span style="color: #ff7700;font-weight:bold;">from</span> settings <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Domínio &quot;m.mydomain.com&quot;</span>
SITE_ID = <span style="color: #ff4500;">2</span>
PREPEND_WWW = <span style="color: #008000;">False</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Usado em outras partes do código para determinar qual versão está rodando</span>
DEFAULT_VERSION = <span style="color: #008000;">False</span>
MOBILE_VERSION  = <span style="color: #008000;">True</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># URLs para a versão mobile</span>
ROOT_URLCONF  = <span style="color: #483d8b;">'myproject.m_urls'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Templates para a versão mobile</span>
TEMPLATE_DIRS = <span style="color: black;">&#40;</span>
    <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">normpath</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span> + <span style="color: #483d8b;">'/template/mobile'</span><span style="color: black;">&#41;</span>,
<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Outras configurações...</span></pre></div></div>

<p>O fato de os dois sites compartilharem a mesma base de código não significa que eles devem ter as mesmas configurações de URL. Aliás, o normal é que versões próprias para dispositivos móveis sejam mais simples, com uma quantidade reduzida de mapeamentos de URLs.</p>
<p>Para definir as configurações de URL da versão mobile, crie um arquivo <code>m_urls.py</code> com o seguinte conteúdo:</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #808080; font-style: italic;"># Arquivo: myproject/m_urls.py</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Mapeamentos de URL para a versão &quot;mobile&quot;.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span>.<span style="color: black;">urls</span>.<span style="color: black;">defaults</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #808080; font-style: italic;"># from django.contrib import admin</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># admin.autodiscover()</span>
&nbsp;
handler404 = <span style="color: #483d8b;">'website.views.error_404_handler'</span>
handler500 = <span style="color: #483d8b;">'website.views.error_500_handler'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># URLs</span>
urlpatterns = patterns<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>,
    <span style="color: #808080; font-style: italic;"># I18N</span>
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^i18n/'</span>, include<span style="color: black;">&#40;</span><span style="color: #483d8b;">'django.conf.urls.i18n'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Apps internas</span>
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^contact/'</span>, include<span style="color: black;">&#40;</span><span style="color: #483d8b;">'contact.urls'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># (r'^admin/doc/', include('django.contrib.admindocs.urls')),</span>
    <span style="color: #808080; font-style: italic;"># (r'^admin/', include(admin.site.urls)),</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Outras configurações...</span>
<span style="color: black;">&#41;</span></pre></div></div>

<p>Perceba que, neste exemplo em particular, a <a href="http://docs.djangoproject.com/en/dev/ref/contrib/admin/">app Admin</a> não é acessível através da versão mobile. Isso apenas serve para mostrar que temos total liberdade para estruturar ambas as versões de diferentes formas, sem muitas dificuldades.</p>
<h3>Desenvolvendo</h3>
<p>Você certamente já sabe como rodar o servidor de desenvolvimento para a versão padrão. O que a maioria dos desenvolvedores desconhece, entretanto, é que é possível escolher qual a porta e/ou módulo <code>settings.py</code> deve ser usado pelo script, o que nos permite rodar um servidor para cada versão do nosso site:</p>

<div class="wp_syntax"><div class="code"><pre class="bash"><span style="color: #666666; font-style: italic;"># Terminal 1: versão padrão</span>
$ python manage.py runserver <span style="color: #000000;">8000</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Terminal 2: versão mobile</span>
$ python manage.py runserver <span style="color: #660033;">--settings</span>=m_settings <span style="color: #000000;">8001</span></pre></div></div>

<p>Pronto, agora é só continuar com o desenvolvimento da forma que você já está acostumado.</p>
<h3>Testando</h3>
<p>Você provavelmente notou que temos duas configurações que podem ser usadas para determinar qual versão do site está rodando, <code>DEFAULT_VERSION</code> e <code>MOBILE_VERSION</code>. </p>
<p>Por isso, é só uma questão de checar tais configurações quando for necessário fazer coisas diferentes em cada uma das versões do site. Isso é particularmente útil quando você tem uma app usada em ambas as versões e quer criar testes para cada uma das versões:</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #808080; font-style: italic;"># Arquivo: myproject/myapp/tests/__init__.py</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Testes para MyApp.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'DEFAULT_VERSION'</span>, <span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Testa a versão padrão</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> default_models_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> default_navigation_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'MOBILE_VERSION'</span>, <span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Testa a versão mobile</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> mobile_models_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> mobile_navigation_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span></pre></div></div>

<p>Você pode rodar os testes para cada versão de uma forma semelhante a que fizemos com o comando <code>runserver</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash"><span style="color: #666666; font-style: italic;"># Versão padrão</span>
$ python manage.py <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>appname...<span style="color: #7a0874; font-weight: bold;">&#93;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Versão mobile</span>
$ python manage.py <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #660033;">--settings</span>=m_settings <span style="color: #7a0874; font-weight: bold;">&#91;</span>appname...<span style="color: #7a0874; font-weight: bold;">&#93;</span></pre></div></div>

<h3>Colocando em produção</h3>
<p>Apesar do que você possa achar, esta é a parte fácil.</p>
<p>Uma vez que a forma recomendada de <a href="http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/">colocar Django em produção</a> é com <a href="http://apache.org">Apache</a> e <a href="http://code.google.com/p/modwsgi/">mod_wsgi</a>, é possível que você já tenha um arquivo WSGI parecido com o seguinte:</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">sys</span>
&nbsp;
APPS_PATH   = <span style="color: #483d8b;">'/home/user/wsgi_apps'</span>
MYPROJECT_PATH = <span style="color: #483d8b;">'%s/myproject'</span> <span style="color: #66cc66;">%</span> APPS_PATH
&nbsp;
<span style="color: #808080; font-style: italic;"># Eggs de terceiros</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">site</span>
<span style="color: #dc143c;">site</span>.<span style="color: black;">addsitedir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/home/user/.python/lib'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span> += <span style="color: black;">&#91;</span>APPS_PATH, MYPROJECT_PATH<span style="color: black;">&#93;</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'myproject.settings'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>
application = django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>.<span style="color: black;">WSGIHandler</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Tudo que precisamos fazer é configurar um outro sub-domínio WSGI no nosso servidor (ex: m.mywebsite.com) que referencia o seguinte arquivo de configurações WSGI:</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">sys</span>
&nbsp;
APPS_PATH   = <span style="color: #483d8b;">'/home/user/wsgi_apps'</span>
MYPROJECT_PATH = <span style="color: #483d8b;">'%s/myproject'</span> <span style="color: #66cc66;">%</span> APPS_PATH
&nbsp;
<span style="color: #808080; font-style: italic;"># Eggs de terceiros</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">site</span>
<span style="color: #dc143c;">site</span>.<span style="color: black;">addsitedir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/home/user/.python/lib'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span> += <span style="color: black;">&#91;</span>APPS_PATH, MYPROJECT_PATH<span style="color: black;">&#93;</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'myproject.m_settings'</span> <span style="color: #808080; font-style: italic;"># Esta linha</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>
application = django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>.<span style="color: black;">WSGIHandler</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>A única diferença entre esses dois arquivos WSGI é que cada um aponta para um módulo <code>settings.py</code> diferente. E não, você não precisa ter uma cópia do site para cada versão, afinal estamos usando a mesma base de código para ambas as versões, lembra? <img src='http://weblog.destaquenet.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h3>Minimizando o tráfego</h3>
<p>Por incrível que pareça, nem todo mundo dispõe de conexões ultra-rápidas. Por isso, é muito importante que você mantenha seus sites tão leves quanto possível.</p>
<p>Existem vários projetos open source que podem ajudar nessa parte. Um deles é o <a href="http://code.google.com/p/django-compress/">django-compress</a>, uma app Django que fornece um sistema automatizado para compressão de arquivos CSS e JavaScript.</p>
<p>Aliás, não importa se seus websites são para dispositivos móveis ou não; você deve <em>sempre</em> tentar minimizar o tráfego.</p>
<h3>O que falta?</h3>
<p>Ainda temos um pequeno problema: quando alguém visita a versão padrão do site através de um dispositivo móvel, ou vice-versa, eles não são redirecionados para a versão apropriada. Mas isso é assunto para um próximo artigo!</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/07/12/django-para-dispositivos-moveis/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Django For Mobile Devices</title>
		<link>http://weblog.destaquenet.com/2010/07/12/django-for-mobile-devices/</link>
		<comments>http://weblog.destaquenet.com/2010/07/12/django-for-mobile-devices/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 11:00:00 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[device]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=932</guid>
		<description><![CDATA[We are living what some people call the &#8220;mobile explosion&#8221;, a time where an increasing number of portable devices &#8212; like tablets and smartphones &#8212; are becoming a significant part of the Web. This is the reason why having your &#8230; <a href="http://weblog.destaquenet.com/2010/07/12/django-for-mobile-devices/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>We are living what some people call the &#8220;mobile explosion&#8221;, a time where an increasing number of portable devices &#8212; like tablets and smartphones &#8212; are becoming a significant part of the Web. This is the reason why having your website tailored for these devices is becoming increasingly important.</p>
<p>Fortunately, <a href="http://djangoproject.com/">Django</a> is one of the few web frameworks that makes this an easy problem to solve.</p>
<p><span id="more-932"></span></p>
<h3>How we solved it</h3>
<p>A simple way is to create a separate settings module for the mobile version. Doing this, we&#8217;re able to run two different webapps while reusing the existing codebase. Also, each version can have its own template directory, URL root configuration, etc.</p>
<p>Let&#8217;s do this. In the project root directory, create a file <code>m_settings.py</code> with the following content:</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #808080; font-style: italic;"># File: myproject/m_settings.py</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Django settings for the mobile-specific website.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Load the default settings</span>
<span style="color: #ff7700;font-weight:bold;">from</span> settings <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Domain &quot;m.mydomain.com&quot;</span>
SITE_ID = <span style="color: #ff4500;">2</span>
PREPEND_WWW = <span style="color: #008000;">False</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Used elsewhere to determine which version is running</span>
DEFAULT_VERSION = <span style="color: #008000;">False</span>
MOBILE_VERSION  = <span style="color: #008000;">True</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># URLs for the mobile version</span>
ROOT_URLCONF  = <span style="color: #483d8b;">'myproject.m_urls'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Templates for the mobile version</span>
TEMPLATE_DIRS = <span style="color: black;">&#40;</span>
    <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">normpath</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span> + <span style="color: #483d8b;">'/template/mobile'</span><span style="color: black;">&#41;</span>,
<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Other settings...</span></pre></div></div>

<p>These two webapps share the same codebase, but that doesn&#8217;t mean they have to use the same URL root configuration. In fact, websites suitable for mobile devices are usually simpler, with fewer URL mappings.</p>
<p>To define separate URL root configuration for the mobile version, create a file <code>m_urls.py</code> with the following content:</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #808080; font-style: italic;"># File: myproject/m_urls.py</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Mobile-specific URL definition.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span>.<span style="color: black;">urls</span>.<span style="color: black;">defaults</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #808080; font-style: italic;"># from django.contrib import admin</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># admin.autodiscover()</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Error page handlers</span>
handler404 = <span style="color: #483d8b;">'website.views.error_404_handler'</span>
handler500 = <span style="color: #483d8b;">'website.views.error_500_handler'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Root URL patterns</span>
urlpatterns = patterns<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>,
    <span style="color: #808080; font-style: italic;"># I18N</span>
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^i18n/'</span>, include<span style="color: black;">&#40;</span><span style="color: #483d8b;">'django.conf.urls.i18n'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Internal apps</span>
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^contact/'</span>, include<span style="color: black;">&#40;</span><span style="color: #483d8b;">'contact.urls'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># (r'^admin/doc/', include('django.contrib.admindocs.urls')),</span>
    <span style="color: #808080; font-style: italic;"># (r'^admin/', include(admin.site.urls)),</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Other settings...</span>
<span style="color: black;">&#41;</span></pre></div></div>

<p>Note that, in this particular example, the <a href="http://docs.djangoproject.com/en/dev/ref/contrib/admin/">Admin app</a> isn&#8217;t accessible from mobile version. This just shows that we can structure each webapp differently without too much trouble.</p>
<h3>Developing</h3>
<p>You already know how to run the development server for the default version. Most people don&#8217;t know, however, that it&#8217;s possible to choose a different port number and settings module, which allows us to launch one development server for each webapp version:</p>

<div class="wp_syntax"><div class="code"><pre class="bash"><span style="color: #666666; font-style: italic;"># Terminal window 1: default version</span>
$ python manage.py runserver <span style="color: #000000;">8000</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Terminal window 2: mobile version</span>
$ python manage.py runserver <span style="color: #660033;">--settings</span>=m_settings <span style="color: #000000;">8001</span></pre></div></div>

<p>Just develop your stuff and see the results in both versions right away. Easy peasy.</p>
<h3>Testing</h3>
<p>You probably noticed that we have two settings that can be used to identify what webapp version is being run, <code>DEFAULT_VERSION</code> and <code>MOBILE_VERSION</code>. </p>
<p>So it&#8217;s just a matter of checking those settings when you need to do different things in each webapp version. This is particularly useful when you use an app in both versions and want to create separate tests for each version:</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #808080; font-style: italic;"># File: myproject/myapp/tests/__init__.py</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Unit tests module for MyApp.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'DEFAULT_VERSION'</span>, <span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Tests the default version</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> default_models_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> default_navigation_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'MOBILE_VERSION'</span>, <span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Tests the mobile version</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> mobile_models_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> mobile_navigation_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span></pre></div></div>

<p>We can run the tests for each version in a similar way we did before with the <code>runserver</code> command:</p>

<div class="wp_syntax"><div class="code"><pre class="bash"><span style="color: #666666; font-style: italic;"># Default version</span>
$ python manage.py <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>appname...<span style="color: #7a0874; font-weight: bold;">&#93;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Mobile version</span>
$ python manage.py <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #660033;">--settings</span>=m_settings <span style="color: #7a0874; font-weight: bold;">&#91;</span>appname...<span style="color: #7a0874; font-weight: bold;">&#93;</span></pre></div></div>

<h3>Deploying</h3>
<p>Despite what you may think, this is the easy part.</p>
<p>Since <a href="http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/">deploying Django</a> with <a href="http://apache.org/">Apache</a> and <a href="http://code.google.com/p/modwsgi/">mod_wsgi</a> is the recommended way to get Django into production, it&#8217;s likely that you already have a WSGI file like this:</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">sys</span>
&nbsp;
APPS_PATH   = <span style="color: #483d8b;">'/home/user/wsgi_apps'</span>
MYPROJECT_PATH = <span style="color: #483d8b;">'%s/myproject'</span> <span style="color: #66cc66;">%</span> APPS_PATH
&nbsp;
<span style="color: #808080; font-style: italic;"># Third-party eggs</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">site</span>
<span style="color: #dc143c;">site</span>.<span style="color: black;">addsitedir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/home/user/.python/lib'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span> += <span style="color: black;">&#91;</span>APPS_PATH, MYPROJECT_PATH<span style="color: black;">&#93;</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'myproject.settings'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>
application = django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>.<span style="color: black;">WSGIHandler</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>All we need to do is configure another WSGI-enabled subdomain on our server, e.g. m.mywebsite.com, that refers to another WSGI file like this one:</p>

<div class="wp_syntax"><div class="code"><pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">sys</span>
&nbsp;
APPS_PATH   = <span style="color: #483d8b;">'/home/user/wsgi_apps'</span>
MYPROJECT_PATH = <span style="color: #483d8b;">'%s/myproject'</span> <span style="color: #66cc66;">%</span> APPS_PATH
&nbsp;
<span style="color: #808080; font-style: italic;"># Third-party eggs</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">site</span>
<span style="color: #dc143c;">site</span>.<span style="color: black;">addsitedir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/home/user/.python/lib'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span> += <span style="color: black;">&#91;</span>APPS_PATH, MYPROJECT_PATH<span style="color: black;">&#93;</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'myproject.m_settings'</span> <span style="color: #808080; font-style: italic;"># This line</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>
application = django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>.<span style="color: black;">WSGIHandler</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>The only difference between these two WSGI files is that each one points to a different settings module. And no, you don&#8217;t need to have a separate copy for each version. We are using the same codebase for both versions, remember? <img src='http://weblog.destaquenet.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h3>Minimizing the traffic</h3>
<p>Amazingly, not everyone has access ultra-fast internet connections on their devices, so it&#8217;s very important to keep your sites as lightweight as possible.</p>
<p>There are several open source projects that try to address this problem. One of them is <a href="http://code.google.com/p/django-compress/">django-compress</a>, a Django app that provides an automated system for compressing CSS and JavaScript files.</p>
<p>In fact, doesn&#8217;t matter if your websites target mobile devices or not; you should <em>always</em> try to minimize the amount of traffic.</p>
<h3>What&#8217;s left?</h3>
<p>There&#8217;s one small problem though: when someone visit the regular website from a mobile device, or vice-versa, they are not redirected to the appropriate version. But this is a topic for another article!</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/07/12/django-for-mobile-devices/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Django-Flash e o Novo Framework de Mensagens</title>
		<link>http://weblog.destaquenet.com/2010/05/21/django-flash-e-o-novo-framework-de-mensagens/</link>
		<comments>http://weblog.destaquenet.com/2010/05/21/django-flash-e-o-novo-framework-de-mensagens/#comments</comments>
		<pubDate>Fri, 21 May 2010 02:36:14 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[django-flash]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=890</guid>
		<description><![CDATA[No começo da semana, depois de vários meses de trabalho duro e algum atraso, a versão 1.2 do Django foi finalmente lançada. Este talvez seja o lançamento mais aguardado do framework desde seu surgimento, e inclui recursos há muito aguardados, &#8230; <a href="http://weblog.destaquenet.com/2010/05/21/django-flash-e-o-novo-framework-de-mensagens/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>No começo da semana, depois de vários meses de trabalho duro e algum atraso, a versão 1.2 do Django <a href="http://www.djangoproject.com/download/">foi finalmente lançada</a>. Este talvez seja o lançamento mais aguardado do framework desde seu surgimento, e inclui recursos há muito aguardados, como <a href="http://docs.djangoproject.com/en/dev/releases/1.2/#support-for-multiple-databases">suporte a múltiplos bancos de dados</a> e um <a href="http://docs.djangoproject.com/en/dev/releases/1.2/#messages-framework">framework de &#8220;mensagens&#8221;</a>.</p>
<p>Sim, eu disse que o Django 1.2 traz incluso um framework de &#8220;mensagens&#8221;. Bom, né? Django realmente precisava vir acompanhado de uma app para resolver essa questão. Isso não significa, no entanto, que <a href="http://djangoflash.destaquenet.com/">Django-Flash</a> será descontinuado ou abandonado.</p>
<p>Então, se você usa Django-Flash em seus projetos, não se preocupe! Nada mudará. Django-Flash já é compatível com Django 1.2, e nós ocontinuaremos a mantê-lo por algumas razões.</p>
<p>A primeira delas é que nos importamos com quem usa nosso software. Nós não quebraremos seus projetos se você decidir fazer o upgrade para uma versão mais recente do Django &#8211; ou se decidir continuar usando uma versão anterior.</p>
<p>A outra é a liberdade de escolha. Você sabe, não existe uma única forma de se resolver todos os problemas. As pessoas devem ser livres para escolher a ferramenta apropriada a uma determinada situação.</p>
<p>Por exemplo, baseado nas minhas primeiras impressões, existem algumas coisas que eu realmente não gostei no novo framework de &#8220;mensagens&#8221;:</p>
<ol>
<li>Ele é <em>verboso</em> mesmo nos casos de uso mais simples</li>
<li>Ele associa mensagens a números de prioridade, encorajando os usuários a usá-lo como um framework de logging/debugging. Quero dizer, um framework de &#8220;mensagens&#8221; não é um framework de logging/debugging, certo?</li>
</ol>
<p>Mas essa é apenas a minha opinião. Talvez seja isso que faz do open source algo tão formidável!</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/05/21/django-flash-e-o-novo-framework-de-mensagens/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django-Flash and Django&#8217;s New Messages Framework</title>
		<link>http://weblog.destaquenet.com/2010/05/21/django-flash-and-djangos-new-messages-framework/</link>
		<comments>http://weblog.destaquenet.com/2010/05/21/django-flash-and-djangos-new-messages-framework/#comments</comments>
		<pubDate>Fri, 21 May 2010 02:31:59 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[django-flash]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=881</guid>
		<description><![CDATA[Earlier this week, after several months of hard work and some delay, Django 1.2 was finally released. This is probably the most exciting release since Django&#8217;s debut, and brings long waited features, like multi-db support and a user &#8220;messages&#8221; framework. &#8230; <a href="http://weblog.destaquenet.com/2010/05/21/django-flash-and-djangos-new-messages-framework/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Earlier this week, after several months of hard work and some delay, <a href="http://www.djangoproject.com/download/">Django 1.2 was finally released</a>. This is probably the most exciting release since Django&#8217;s debut, and brings long waited features, like <a href="http://docs.djangoproject.com/en/dev/releases/1.2/#support-for-multiple-databases">multi-db support</a> and a <a href="http://docs.djangoproject.com/en/dev/releases/1.2/#messages-framework">user &#8220;messages&#8221; framework</a>.</p>
<p>Yes, I said Django 1.2 comes with built-in user &#8220;messages&#8221; framework. Great, isn&#8217;t it? Django really needed a built-in contrib app to solve this problem. This doesn&#8217;t mean, however, that <a href="http://djangoflash.destaquenet.com/">Django-Flash</a> will be discontinued or abandoned.</p>
<p>So, if you use Django-Flash in your projects, don&#8217;t worry! Nothing will change. Django-Flash is already compatible with Django 1.2, and we&#8217;ll keep improving Django-Flash for a number of reasons.</p>
<p>First of all, we care about the people who use our software. We won&#8217;t break your stuff if you decide to upgrade to a newer version of Django &#8211; or if you decide to keep using the previous version.</p>
<p>Also, freedom of choice is a good thing. You know, there&#8217;s not only one true way to solve every problem. People should be free to choose whatever tool they think is right in a given situation.</p>
<p>For example, based on my first impressions, there are a couple of things I didn&#8217;t like at all about the new user &#8220;messages&#8221; framework:</p>
<ol>
<li>It&#8217;s verbose even for the simple cases</li>
<li>It ties messages to priority numbers, encouraging you to use it like a logging/debugging framework. I mean, a user &#8220;messages&#8221; framework is not a logging/debugging framework, right?</li>
</ol>
<p>But that&#8217;s just my opinion. I guess this is what makes open source so great!</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/05/21/django-flash-and-djangos-new-messages-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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 &#8230; <a href="http://weblog.destaquenet.com/2009/06/19/voce-gostaria-de-ver-django-flash-incluido-no-django-como-uma-contrib-app/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></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 01: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 &#8230; <a href="http://weblog.destaquenet.com/2009/04/13/django-e-settingspy-dicas-e-boas-praticas/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></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"><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"><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"><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"><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"><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 &#8230; <a href="http://weblog.destaquenet.com/2009/02/06/mensagens-flash-a-la-rails-para-django-com-django-flash/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></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, &#8230; <a href="http://weblog.destaquenet.com/2008/10/05/deployment-de-aplicacoes-python-com-fabric/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></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.</p>
<p><strong>Atualização:</strong> Trechos de código adaptados para as versões mais recentes do Fabric (22/06/2010).</p>
<p><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>$ 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"><span style="color: #ff7700;font-weight:bold;">from</span> fabric.<span style="color: black;">api</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
env.<span style="color: black;">project</span> = <span style="color: #483d8b;">'project_name'</span>,
env.<span style="color: black;">package</span> = <span style="color: #483d8b;">'$(project).zip'</span>,
&nbsp;
<span style="color: #808080; font-style: italic;"># Remote servers</span>
env.<span style="color: #dc143c;">user</span>  = <span style="color: #483d8b;">'usuario_ssh'</span>,
env.<span style="color: black;">hosts</span> = <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>,
&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;Deploys 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;Builds 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;Prepares 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;Removes 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 as variáveis <code>env.*</code> necessárias para o <em>script</em>. Destaque para a variável <code>env.hosts</code>, que indica os servidores nos quais os comandos remotos devem ser executados.</p>
<p>Ok, tente executar o comando <code>fab -l</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>
$  fab -l
Available commands:
   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.
</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>$  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>env.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>
<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"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Build script.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> fabric.<span style="color: black;">api</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
&nbsp;
env.<span style="color: black;">project</span> = <span style="color: #483d8b;">'destaqueweb'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Build output directory</span>
env.<span style="color: black;">build_path</span> = <span style="color: #483d8b;">'build'</span>
env.<span style="color: black;">package</span>    = <span style="color: #483d8b;">'%s.zip'</span> <span style="color: #66cc66;">%</span> env.<span style="color: black;">project</span>
env.<span style="color: black;">local_path</span> = <span style="color: #483d8b;">'%s/%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>env.<span style="color: black;">build_path</span>, env.<span style="color: black;">package</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Media</span>
env.<span style="color: black;">media_src</span>   = <span style="color: #483d8b;">'media'</span>
env.<span style="color: black;">media_root</span>  = <span style="color: #483d8b;">'public_html'</span>
env.<span style="color: black;">media_path</span>  = <span style="color: #483d8b;">'%s/%s/%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>env.<span style="color: black;">media_root</span>, env.<span style="color: black;">project</span>, env.<span style="color: black;">media_src</span><span style="color: black;">&#41;</span>
env.<span style="color: black;">media_build</span> = <span style="color: #483d8b;">'%s/%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>env.<span style="color: black;">build_path</span>, env.<span style="color: black;">media_path</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Application code</span>
env.<span style="color: black;">app_root</span>  = <span style="color: #483d8b;">'wsgi_apps'</span>
env.<span style="color: black;">app_path</span>  = <span style="color: #483d8b;">'%s/%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>env.<span style="color: black;">app_root</span>, env.<span style="color: black;">project</span><span style="color: black;">&#41;</span>
env.<span style="color: black;">app_build</span> = <span style="color: #483d8b;">'%s/%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>env.<span style="color: black;">build_path</span>, env.<span style="color: black;">app_path</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Remote servers</span>
env.<span style="color: black;">hosts</span>       = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'destaquenet.com'</span><span style="color: black;">&#93;</span>
env.<span style="color: black;">destination</span> = <span style="color: #483d8b;">'/home/destaquenet'</span>
&nbsp;
&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;&quot;&quot;Removes the build directory.
    &quot;&quot;&quot;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'rm -fR %s'</span> <span style="color: #66cc66;">%</span> env.<span style="color: black;">build_path</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;&quot;&quot;Prepares the build directory.
    &quot;&quot;&quot;</span>
    clean<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mkdir -p %s'</span> <span style="color: #66cc66;">%</span> env.<span style="color: black;">media_build</span><span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mkdir -p %s'</span> <span style="color: #66cc66;">%</span> env.<span style="color: black;">app_build</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;&quot;&quot;Builds the application.
    &quot;&quot;&quot;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'cp -R %s/* %s/%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>env.<span style="color: black;">project</span>, env.<span style="color: black;">build_path</span>, env.<span style="color: black;">app_path</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'cp -R %s/* %s/%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>env.<span style="color: black;">media_src</span>, env.<span style="color: black;">build_path</span>, env.<span style="color: black;">media_path</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'find %s -name *.pyc -delete'</span> <span style="color: #66cc66;">%</span> env.<span style="color: black;">build_path</span><span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'find %s -path *upload* -delete'</span> <span style="color: #66cc66;">%</span> env.<span style="color: black;">build_path</span><span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'find %s -path *fixtures* -delete'</span> <span style="color: #66cc66;">%</span> env.<span style="color: black;">build_path</span><span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'cd %s;zip -r %s %s %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>env.<span style="color: black;">build_path</span>, env.<span style="color: black;">package</span>, env.<span style="color: black;">media_root</span>, env.<span style="color: black;">app_root</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> reload_app<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Reloads the app.
    &quot;&quot;&quot;</span>
    run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'touch %s/%s/%s/index.wsgi'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>env.<span style="color: black;">destination</span>, env.<span style="color: black;">media_root</span>, env.<span style="color: black;">project</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'python %s/%s/manage.py ping_google /sitemap.xml'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>env.<span style="color: black;">destination</span>, env.<span style="color: black;">app_path</span><span style="color: black;">&#41;</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;&quot;&quot;Deploys the application to the production server.
    &quot;&quot;&quot;</span>
    build<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    put<span style="color: black;">&#40;</span>env.<span style="color: black;">local_path</span>, env.<span style="color: black;">destination</span><span style="color: black;">&#41;</span>
    run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'cd %s; unzip -uo %s; rm %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>env.<span style="color: black;">destination</span>, env.<span style="color: black;">package</span>, env.<span style="color: black;">package</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    reload_app<span style="color: black;">&#40;</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"><span style="color: #808080; font-style: italic;"># ...</span>
env.<span style="color: #dc143c;">user</span>  = <span style="color: #483d8b;">'production'</span>,
env.<span style="color: black;">hosts</span> = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'app.com'</span><span style="color: black;">&#93;</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>
    env.<span style="color: #dc143c;">user</span>  = <span style="color: #483d8b;">'staging'</span>
    env.<span style="color: black;">hosts</span> = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'staging.app.com'</span><span style="color: black;">&#93;</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. 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>env.user</code> e <code>env.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>6</slash:comments>
		</item>
	</channel>
</rss>
