<?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>Welcome to Django</title>
	<atom:link href="http://pyblog.foxandxss.net/feed" rel="self" type="application/rss+xml" />
	<link>http://pyblog.foxandxss.net</link>
	<description>Django nunca fue tan fácil</description>
	<lastBuildDate>Tue, 10 Jan 2012 12:37:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Localizando nuestras aplicaciones Django</title>
		<link>http://pyblog.foxandxss.net/localizando-nuestras-aplicaciones-django</link>
		<comments>http://pyblog.foxandxss.net/localizando-nuestras-aplicaciones-django#comments</comments>
		<pubDate>Tue, 10 Jan 2012 12:37:19 +0000</pubDate>
		<dc:creator>Fox</dc:creator>
				<category><![CDATA[Articulos]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Localización]]></category>

		<guid isPermaLink="false">http://pyblog.foxandxss.net/?p=85</guid>
		<description><![CDATA[Como es lógico, una aplicación web localizada tendrá mas visitantes que una que no lo está. Localizar un proyecto Django es lo más fácil que he visto nunca. No lo digo porque este blog sea de Django, si no porque &#8230; <a href="http://pyblog.foxandxss.net/localizando-nuestras-aplicaciones-django">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Como es lógico, una aplicación web localizada tendrá mas visitantes que una que no lo está.</p>
<p>Localizar un proyecto <strong>Django</strong> es lo más fácil que he visto nunca. No lo digo porque este blog sea de <strong>Django</strong>, si no porque personalmente me gusta bastante localizar aplicaciones y las alternativas son más complejas de localizar. Sin ir más lejos en <strong>.NET</strong> aunque no complejo, es mucho más cansino de hacer.</p>
<p>Bueno, mejor verlo en funcionamiento pues hablar es fácil.<br />
<span id="more-85"></span><br />
Creamos un nuevo proyecto llamado <i>localizacion</i> y una aplicación llamada <i>app</i>.</p>
<p>Hay que configurar un poco el <i>settings.py</i> como hacemos con todos los proyectos nuevos. Me encanta explicar las cosas muy paso por paso, pero la configuración es siempre igual y ya está explicado en mis artículos anteriores, así que por última vez daré un resumen de lo que hay que configurar:</p>
<ul>
<li>Un parámetro con la ruta del proyecto</li>
<li>Configurar un directorio para ficheros estáticos (aunque no es necesario para este ejemplo)</li>
<li>Configurar un directorio para templates</li>
<li>Configurar una base de datos sqlite3 (Y ejecutar <i>syncdb</i>)</li>
<li>Añadir la aplicación <i>app</i> a la lista de aplicaciones</li>
</ul>
<p>Si os dais cuenta, en el <i>settings.py</i> hay dos parámetros sobre localización:</p>
<pre class="brush: python;">
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True

# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale
USE_L10N = True
</pre>
<p><i>USE_I18N</i> sirve para activar todo el tema de localización. Sin esto no podremos localizar nada.<br />
<i>USE_L10N</i> nos localiza también las fechas ya que para python las fechas son YYYY/MM/DD y por ejemplo para los alemanes es dd.mm.yyy</p>
<p>Bueno, ya tenemos todo listo para empezar a picar código.</p>
<p>Vamos a crear una vista (<i>/app/views.py</i>):</p>
<pre class="brush: python;">
import datetime
from django.shortcuts import render_to_response
from django.template.context import RequestContext

def home(request):
    message = &quot;This is a message from the views.py&quot;
    date = datetime.date.today()
    return render_to_response(&quot;app/home.html&quot;, locals(), context_instance=RequestContext(request))
</pre>
<p>Una vista con tres variables (para las distintas pruebas de localización).</p>
<p>La idea es programar usando variables en inglés, comentarios en inglés y vaya, todo en inglés. Ya luego lo localizais en castellano si queréis.</p>
<p>Vamos a añadir una nueva <i>url</i> al <i>urls.py</i>:</p>
<pre class="brush: python;">
url(r'^$', 'app.views.home'),
</pre>
<p>Ahora creamos un directorio llamado <i>app</i> dentro del directorio <i>templates</i> que habíamos creado anteriormente y añadimos un fichero llamado <i>home.html</i>:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta charset=&quot;utf-8&quot;/&gt;
        &lt;title&gt;Localization example&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;p&gt;Message from the template!&lt;/p&gt;
        &lt;p&gt;{{ message }}&lt;/p&gt;
        &lt;p&gt;Today is {{ date }}&lt;/p&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Si ahora ejecutamos la aplicación veremos lo siguiente:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/localizacion/1.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/localizacion/1.png" class="alignnone" width="262" height="115" /></a></p>
<p>Ok, chachi piruli.</p>
<p>¿Cómo localizamos? Vamos a empezar por la vista.</p>
<p>Todas las cadenas que querramos traducir en los ficheros <i>.py</i> tendrán que pasar por <i>ugettext</i> así que nuestro método <i>home</i> pasará a estar así:</p>
<pre class="brush: python;">
from django.utils.translation import ugettext as _

def home(request):
    message = _(&quot;This is a message from the views.py&quot;)
    date = datetime.date.today()
    return render_to_response(&quot;app/home.html&quot;, locals(), context_instance=RequestContext(request))
</pre>
<p>Hemos cargado <i>ugettext</i> con el nombre de <i>_</i> (así es más comodo de usar, además creo que es una convención de otros lenguajes).</p>
<p>Ahora simplemente cada cadena la convertimos a una llamada a la función <i>_</i>. Nada más. ¿Fácil eh?</p>
<p>¿Y ahora el template? Pues vamos a modificarlo:</p>
<pre class="brush: xml;">
{% load i18n %}
&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta charset=&quot;utf-8&quot;/&gt;
        &lt;title&gt;{% trans &quot;Localization example&quot; %}&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;p&gt;{% trans &quot;Message from the template!&quot; %}&lt;/p&gt;
        &lt;p&gt;{{ message }}&lt;/p&gt;
        &lt;p&gt;{% blocktrans %}Today is {{ date }}{% endblocktrans %}&lt;/p&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Cargamos los tags de <i>i18n</i>.</p>
<p>Tenemos el tag <i>trans</i> para traducir cadenas.Luego tenemos <i>blocktrans</i> para traducir bloques, como por ejemplo un bloque que contenga a mitad una variable, así podemos traducir de una vez un bloque con &#8220;cadena &#8211; variable &#8211; cadena&#8221; en vez de tener dos <i>trans</i> por separado.</p>
<p>Como es lógico, las variables ya vienen localizadas desde la vista.</p>
<p>Bueno, ¿Cómo sabe <strong>Django</strong> a que lenguajes quiero localizar?</p>
<p>Abrimos el <i>settings.py</i> y añadimos lo siguiente:</p>
<pre class="brush: python; highlight: [3,4,5,6];">
LANGUAGE_CODE = 'en-us'

LANGUAGES = (
    ('en', 'English'),
    ('es', 'Spanish'),
)
</pre>
<p>Con esto le decimos a <strong>Django</strong> los lenguajes que queremos.</p>
<p>Bueno, ya solo nos queda ejecutar el siguiente comando en el directorio principal del proyecto, aunque antes tenéis que crear un directorio llamado <i>locale</i> en dicho directorio principal o fallará:</p>
<pre class="brush: plain;">
django-admin.py makemessages -l es
</pre>
<p>Con esto nos crea los directorios y ficheros necesarios para la localización en español.</p>
<p>Tendremos que ejecutar ese comando por cada idioma extra.</p>
<p>Bueno, abrimos el fichero <i>/locale/es/LC_MESSAGES/django.po</i></p>
<p>Esto es sencillo, por cada <i>msgid</i> hay un <i>msgstr</i>. Así que hay que colocar la traducción de cada <i>msgid</i> en su respectivo <i>msgstr</i>:</p>
<pre class="brush: plain;">
#: .\app\views.py:8
msgid &quot;This is a message from the views.py&quot;
msgstr &quot;Esto es un mensaje desde el views.py&quot;

#: .\templates\app\home.html.py:6
msgid &quot;Localization example&quot;
msgstr &quot;Ejemplo de localizacion&quot;

#: .\templates\app\home.html.py:9
msgid &quot;Message from the template!&quot;
msgstr &quot;Mensaje desde el template!&quot;

#: .\templates\app\home.html.py:11
#, python-format
msgid &quot;Today is %(date)s&quot;
msgstr &quot;Hoy es %(date)s&quot;
</pre>
<p>Vale, ahora solo nos queda compilar el <i>.po</i> para que <strong>Django</strong> lo entienda.</p>
<pre class="brush: plain;">
django-admin.py compilemessages
</pre>
<p>Vale, si ejecutamos la aplicación ahora pues no vemos ningún cambio. ¿No molaría que usara el idioma del navegador para poner ese idioma por defecto?</p>
<p>Es fácil, solo tenemos que añadir un <i>middleware</i>:</p>
<pre class="brush: python; highlight: [3];">
MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)
</pre>
<p>Aunque parezca el <i>middleware</i> añadido ahi al azar, necesita cumplir 3 cosas:</p>
<ul>
<li>Tiene que ser de los primeros <i>middleware</i> a añadir.</li>
<li>Pero tiene que aparecer <i>DESPUES</i> de <i>SessionMiddleware</i> y a la vez <i>ANTES</i> de <i>CommonMiddleware</i>.</li>
<li>Si usaramos <i>CacheMiddleware</i>, tendríamos que ponerlo despues de este.</li>
</ul>
<p>Vale, ahora ejecutamos la aplicación y&#8230;</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/localizacion/2.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/localizacion/2.png" class="alignnone" width="255" height="116" /></a></p>
<p>¡Ya está localizada!</p>
<p>Molaría un selector de idioma, ¿no?</p>
<p>Bueno, pues vamos a añadir una url más al <i>views.py</i>:</p>
<pre class="brush: python;">
url(r'^i18n/', include('django.conf.urls.i18n')),
</pre>
<p>Ahora vamos a añadir un pequeño formulario a <i>app/home.html</i>:</p>
<pre class="brush: xml;">
&lt;form action=&quot;/i18n/setlang/&quot; method=&quot;post&quot;&gt;
	{% csrf_token %}
	&lt;input name=&quot;next&quot; type=&quot;hidden&quot; value=&quot;/&quot; /&gt;
	&lt;select name=&quot;language&quot;&gt;
		{% get_language_info_list for LANGUAGES as languages %}
		{% for language in languages %}
			&lt;option value=&quot;{{ language.code }}&quot;&gt;{{ language.name_local }} ({{ language.code }})&lt;/option&gt;
		{% endfor %}
	&lt;/select&gt;
	&lt;input type=&quot;submit&quot; value=&quot;Go&quot; /&gt;
&lt;/form&gt;
</pre>
<p>Es muy sencillito. Hace un <i>POST</i> enviando como parámetro la url de la página que cargará cuando se cambie el idioma y el idioma en si.</p>
<p>La lista de idiomas que cargará en el <i>select</i> viene del parámetro <i>LANGUAGES</i> del <i>settings.py</i><br />
<a href="http://pyblog.foxandxss.net/cosasblog/localizacion/3.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/localizacion/3.png" class="alignnone" width="266" height="151" /></a></p>
<p>Bueno, esto es lo básico en cuanto a localización. Por supuesto hay más chicha, pero con esto podremos empezar a localizar nuestros trabajos.</p>
<p>Os dejo el <a href="http://pyblog.foxandxss.net/cosasblog/localizacion/localizacion.zip">.zip</a> con el proyecto.</p>
]]></content:encoded>
			<wfw:commentRss>http://pyblog.foxandxss.net/localizando-nuestras-aplicaciones-django/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Jugando con django-registration</title>
		<link>http://pyblog.foxandxss.net/jugando-con-django-registration</link>
		<comments>http://pyblog.foxandxss.net/jugando-con-django-registration#comments</comments>
		<pubDate>Tue, 20 Dec 2011 19:55:00 +0000</pubDate>
		<dc:creator>Fox</dc:creator>
				<category><![CDATA[Articulos]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[django-registration]]></category>

		<guid isPermaLink="false">http://pyblog.foxandxss.net/?p=79</guid>
		<description><![CDATA[Hola, aquí estoy de nuevo con un artículo, y ya vamos a empezar metiendo código y todas esas cosas que nos gustan. En este artículo vamos a hablar de django-registration. django-registration es una librería para manejar el registro de usuarios &#8230; <a href="http://pyblog.foxandxss.net/jugando-con-django-registration">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Hola, aquí estoy de nuevo con un artículo, y ya vamos a empezar metiendo código y todas esas cosas que nos gustan.</p>
<p>En este artículo vamos a hablar de <a href="https://bitbucket.org/ubernostrum/django-registration/wiki/Home">django-registration</a>. <strong>django-registration</strong> es una librería para manejar el registro de usuarios (registro, entrar al sistema, salir, cambiar la contraseña&#8230;).</p>
<p><strong>Django</strong> de por si no tiene ningún sistema de registro de usuarios (aunque implementarlo es trivial), así que se creó esta librería para proporcionar un pequeño sistema de registro bastante sencillo pero a la vez bastante potente.</p>
<p>¿Vamos a ello?<br />
<span id="more-79"></span><br />
Yo para cada nueva aplicación, aunque sea pequeñita, suelo crear un nuevo <a href="http://pyblog.foxandxss.net/entendiendo-virtualenv-y-pip">virtualenv</a>. Vamos a darle caña:</p>
<p>En mi caso (Windows):</p>
<pre class="brush: plain;">
virtualenv --no-site-packages --distribute register
env.py register
pip install django
pip install https://bitbucket.org/ubernostrum/django-registration/get/tip.zip
</pre>
<p>Tenemos que instalar así <strong>django-registration</strong> porque la versión que hay en pip es la <i>0.7</i> y hay los suficientes cambios en la <i>tip</i> como para usar esa.</p>
<p>Vamos a crear una aplicación de ejemplo:</p>
<pre class="brush: plain;">
django-admin.py startproject register
cd register
python manage.py startapp app
</pre>
<p>Bueno, ya tenemos nuestra aplicación.</p>
<p>En cada nuevo proyecto tenemos que hacer una serie de ajustes. Vamos a empezar creando un directorio llamado <i>templates</i> en el directorio raiz.</p>
<p>Ahora abrimos el <i>settings.py</i> y configuramos la ruta de nuestra aplicación y la base de datos:</p>
<pre class="brush: python;">
CURRENT_PATH = os.path.dirname(__file__)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'data.db',
    }
}
</pre>
<p>No os olvideis de importar el módulo <i>os</i>.</p>
<p>Agregamos nuestro directorio de templates:</p>
<pre class="brush: python;">
TEMPLATE_DIRS = (
    os.path.join(CURRENT_PATH, 'templates'),
)
</pre>
<p>Y por último agregamos nuestra aplicación y la de <strong>django-registration</strong>:</p>
<pre class="brush: python; highlight: [8,9];">
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app',
    'registration',
)
</pre>
<p>Bueno, realmente quedan dos ajustes más. Aunque antes de eso explicaré un poco más.</p>
<p><strong>django-registration</strong> tiene por defecto un par de <i>back-end</i>. Tiene uno por defecto, el cual no activa la cuenta al registrarnos por lo que nos envía un correo con una url de activación que al hacerle click pues nos activa la cuenta.</p>
<p>Si vamos a usar este <i>back-end</i> necesitamos configurar un par de cosas (settings.py):</p>
<pre class="brush: python;">
ACCOUNT_ACTIVATION_DAYS = 7

EMAIL_HOST = 'servidorsmtp'
EMAIL_HOST_USER = 'usuario'
EMAIL_HOST_PASSWORD = 'contraseña'
EMAIL_USE_TLS = True
EMAIL_PORT = 123
</pre>
<p>Con lo primero establecemos un periodo de tiempo antes de que nuestra cuenta caduque si no se activa, por ejemplo 7 días. Lo siguiente es la configuración para enviar correos electrónicos.</p>
<p>Si no tenéis ningún servidor de correo a mano, podéis usar un correo de gmail así:</p>
<pre class="brush: python;">
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'usuario@gmail.com'
EMAIL_HOST_PASSWORD = 'contraseña'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
</pre>
<p>Si no queréis todo el tema de activación y que al registrarnos nos active la cuenta directamente, podéis usar el <i>back-end</i> llamado <i>simple</i>.</p>
<p>El siguiente paso es configurar el fichero <i>urls.py</i> añadiendo:</p>
<pre class="brush: python;">
(r'^accounts/', include('registration.backends.default.urls')),
</pre>
<p>Podéis ver que hemos usado el <i>back-end</i> <i>default</i> el cual lleva todo el tema de activación. Es el más complejo de los dos, pero entendiendo este, entiendes el otro.</p>
<p>Antes de empezar a registrar usuarios, <strong>django-registration</strong> necesita varios templates, vamos a pasar a describirlos:</p>
<ul>
<li><strong>registration/registration_form.html</strong> &#8211; Es el template con el formulario de registro.</li>
<li><strong>registration/registration_complete.html</strong> &#8211; Es el template que aparecerá cuando completemos el registro.</li>
<li><strong>registration/activate.html</strong> &#8211; Se muestra si la activación falla.</li>
<li><strong>registration/activation_complete.html</strong> &#8211; Se muestra cuando la cuenta se activa correctamente.</li>
</ul>
<p>Esos son los templates necesarios para <strong>django-registration</strong>, aunque necesitamos uno más para poder hacer uso del login:</p>
<ul>
<li><strong>registration/login.html</strong> &#8211; Template para la página de login.</li>
</ul>
<p>Vale, ¿pero qué pasa con <i>logout</i>?</p>
<p>Tenemos dos opciones, o bien creamos un template en:</p>
<p><i>registration/logout.html</i> o bien nos saltamos el template y hacemos el logout directamente. Para esto tenemos que ir a <i>urls.py</i> y añadir (por encima de la entrada de <i>accounts</i>):</p>
<pre class="brush: python;">
url(r'^accounts/logout/$', 'django.contrib.auth.views.logout', {'next_page': '/'}),
</pre>
<p>donde <i>next_page</i> es la página que se cargará al hacer logout.</p>
<p>Aparte de esto, necesitamos crear dos ficheros <i>.txt</i> para el correo:</p>
<ul>
<li><strong>registration/activation_email_subject.txt</strong> &#8211; Es el asunto del correo.</li>
<li><strong>registration/activation_email.txt</strong> &#8211; Es el cuerpo del correo.</li>
</ul>
<p>Bueno, vamos a poner un pequeño ejemplo de cada fichero para que lo veáis:</p>
<p><strong>registration/registration_form.html</strong>:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;/&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action=&quot;.&quot; method=&quot;post&quot;&gt;
        {% csrf_token %}
        {{ form.as_p }}
        &lt;input type=&quot;submit&quot; value=&quot;Registrar&quot; /&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Lo suyo sería que los templates heredaran de otro para que todos compartieran el mismo diseño, pero por simplicidad vamos a dejarlo así (de hecho, no vamos ni a usar CSS).</p>
<p>Como véis, este template tiene acceso a un form, que como habéis deducido, es el formulario de registro <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p><strong>registration/registration_complete.html</strong>:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;/&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;p&gt;Se ha registrado correctamente,
       se le ha enviado un correo con una url para activar su cuenta.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p><strong>registration/activate.html</strong>:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;/&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;p&gt;No se ha podido activar su cuenta,
    el código de activación es: {{ activation_key }}&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Este template tiene acceso al código de activación.</p>
<p><strong>registration/activation_complete.html</strong>:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;/&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;p&gt;Gracias, su cuenta se ha activado correctamente.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p><strong>registration/login.html</strong>:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;/&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action=&quot;.&quot; method=&quot;post&quot;&gt;
        {% csrf_token %}
        {{ form.as_p }}
        &lt;input type=&quot;submit&quot; value=&quot;Entrar&quot; /&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Como en el formulario de registro, aqui usamos el formulario de <i>login</i>.</p>
<p><strong>registration/activation_email_subject.txt</strong>:</p>
<pre class="brush: plain;">
Bienvenido a {{ site }}, por favor active su cuenta antes de {{ expiration_days }} días.
</pre>
<p>El asunto del correo tiene que ser una sola linea.</p>
<p><strong>registration/activation_email.txt</strong>:</p>
<pre class="brush: plain;">
Hola, bienvenido a {{ site }}.

Por favor, active su cuenta en: {{ site }}/accounts/activate/{{ activation_key }}

¡Gracias!
</pre>
<p>Tanto el asunto como el correo en si, tienen acceso a tres variables:</p>
<ul>
<li><strong>site</strong> &#8211; El nombre del sitio (se cambia en el panel de administrador, en el apartado <i>Sites</i>).</li>
<li><strong>activation_key</strong> &#8211; La clave generada automaticamente para activar la cuenta.</li>
<li><strong>expiration_days</strong> &#8211; Los días que tienes para activar la cuenta antes de que caduque.</li>
</ul>
<p>Bueno, si tenemos el correo configurado y nos registramos, deberíamos recibir un correo de este tipo:</p>
<pre class="brush: plain;">
Hola, bienvenido a example.com.

Por favor, active su cuenta en: example.com/accounts/activate/1cac5be0c509589eed31cef8a4697a0aa329b709

¡Gracias!
</pre>
<p>Como no he modificado lo de <i>example.com</i> en el panel de administrador pues sale eso como <i>site</i>. Lo normal es cambiarlo al hacer deploy.</p>
<p>Si hacemos un poco de corta pega pues activaremos nuestra cuenta y ya podremos loguearnos.</p>
<p>Al loguearnos recibiremos un hermoso error pues no tenemos ningún contenido en la web.</p>
<p>Para probar vamos a hacer dos cosas:</p>
<p>1º Vamos a ir a <i>settings.py</i> y vamos a colocar el siguiente parámetro:</p>
<pre class="brush: python;">
LOGIN_REDIRECT_URL = &quot;/&quot;
</pre>
<p>Eso hará que cuando nos logueemos, nos redirija a la página principal.</p>
<p>2º Vamos a crear una página principal.</p>
<p>Empezamos creando un fichero llamado <i>index.html</i> dentro de <i>registration/app</i>:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;/&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    Ha entrado como {{ user.username }}
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Creamos una vista en <i>views.py</i>:</p>
<pre class="brush: python;">
from django.shortcuts import render_to_response
from django.template.context import RequestContext

def index(request):
    return render_to_response(&quot;app/index.html&quot;, locals(), context_instance=RequestContext(request))
</pre>
<p>y finalmente modificamos el <i>urls.py</i>:</p>
<pre class="brush: python;">
url(r'^$', 'app.views.index'),
</pre>
<p>Ya está. Ya podemos registrarnos, loguearnos, salirnos, y activar nuestras cuentas.</p>
<p>Aunque no quiero dejarlo aquí. Ahora vamos a explicar como extender esta librería para crear un formulario que tenga campos extras, lo cual es algo muy común.</p>
<p>Entonces, ¿Qué pasa si quiero por ejemplo almacenar ciertos datos con cada usuario?</p>
<p>Empezamos creando un modelo para esos datos, por ejemplo vamos a almacenar la edad y el sexo del usuario.</p>
<p>Pues nos vamos a <i>models.py</i> y creamos un modelo:</p>
<pre class="brush: python;">
from django.contrib.auth.models import User
from django.db import models

class DatosExtra(models.Model):
    user = models.OneToOneField(User)
    edad = models.IntegerField()
    sexo = models.CharField(max_length=9)
</pre>
<p>Hacemos un <i>syncdb</i> para añadir la nueva tabla.</p>
<p>Ahora necesitamos crear el formulario de registro el cual heredará del ya existente. Para ello creamos un fichero llamado <i>forms.py</i>:</p>
<pre class="brush: python;">
from django import forms
from registration.forms import RegistrationForm

class DatosExtraForm(RegistrationForm):
    edad = forms.IntegerField()
    sexo = forms.ChoiceField(choices=[('masculino', 'masculino'), ('femenino', 'femenino')])
</pre>
<p>Un formulario sencillito, simplemente le añadimos los dos campos extras y el de sexo como un <i>select</i> lo cual lo hace más cómodo. Como extra, decir que <i>choices</i> acepta una lista de tuplas, cada tupla tiene dos valores, el valor que guardará y el valor que mostrará en el <i>select</i>. En este caso el mismo para ambos.</p>
<p>¿Cómo hacemos que la página de registro lo muestre?</p>
<p>Fácil, la vista de registro acepta un formulario personalizado como parámetro, así que solo tenemos que añadir una nueva <i>url</i> en <i>urls.py</i> (por encima de la de <i>accounts</i>):</p>
<pre class="brush: python;">
url(r'^accounts/register/$', 'registration.views.register',
                {'backend': 'registration.backends.default.DefaultBackend', 'form_class': DatosExtraForm}),
</pre>
<p>¡Ya sale! Si, pero no lo guarda.</p>
<p>La mejor forma para guardar los cambios es crear nuestro propio <i>back-end</i>. Existe un <i>signal</i> que se lanza cuando se crea el usuario, pero no está preparado para estos casos pues no envia los datos con el para guardar las cosas extras y tirar de <i>request.POST</i> no mola pues no tendríamos acceso a variables del tipo <i>cleaned_data</i>.</p>
<p>Bueno, ¿Cómo lo hacemos?</p>
<p>La forma más facil es copiar el <i>default backend</i> en nuestro proyecto y modificarlo.</p>
<p>Para ello vamos a copiar el directorio <i>default</i> que se encuentra en <i>python/lib/site-packages/registration/backends/</i>. Lo copiamos al directorio principal del proyecto y lo renombramos, no sé, a <i>custom_backend</i> por ejemplo.</p>
<p>Una vez copiado abrimos el <i>__init__.py</i> y le metemos los cambios marcados en negrita:</p>
<pre class="brush: python; highlight: [4,5,6,7];">
new_user = RegistrationProfile.objects.create_inactive_user(username, email,
                                                                    password, site)

extra = DatosExtra(user=new_user)
extra.sexo = kwargs['sexo']
extra.edad = kwargs['edad']
extra.save()

signals.user_registered.send(sender=self.__class__,
							 user=new_user,
							 request=request)
return new_user
</pre>
<p>Recordad importar la clase, además le vamos a cambiar el nombre a la clase de <i>DefaultBackend</i> a <i>CustomBackend</i>.</p>
<p>Esto no hace nada impresionante. Simplemente crea una instancia del modelo con los datos extras los cuales cogemos del diccionario <i>kwargs</i> (El cual viene de la vista y pasa todos los campos del formulario) y guardamos el modelo.</p>
<p>Ahora tenemos que modificar la <i>url</i> que pusimos antes para que use el nuevo <i>back-end</i> quedando así:</p>
<pre class="brush: python;">
url(r'^accounts/register/$', 'registration.views.register',
                {'backend': 'register.custom_backend.CustomBackend', 'form_class': DatosExtraForm}),
</pre>
<p>Ya está, nuestros nuevos usuarios se registrarán usando datos extras.</p>
<p>Vamos a modificar la vista para que use también los nuevos datos, ¿no?</p>
<p>Abrimos <i>views.py</i> y modificamos el <i>index</i> así:</p>
<pre class="brush: python;">
# Create your views here.
from django.shortcuts import render_to_response
from django.template.context import RequestContext
from app.models import DatosExtra

def index(request):
    if request.user.is_authenticated():
        extra = DatosExtra.objects.get(user=request.user)
    return render_to_response(&quot;app/index.html&quot;, locals(), context_instance=RequestContext(request))
</pre>
<p>Ahora vamos a <i>app/index.html</i>:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;/&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    Ha entrado como {{ user.username }}. Tiene {{ extra.edad }} y es de sexo {{ extra.sexo }}
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Ya está. Ya podemos registrar usuarios con todos los campos extras que nos hagan falta.</p>
<p>Si queréis más información, siempre os quedará la <a href="https://bitbucket.org/ubernostrum/django-registration/src/fad7080fe769/docs/">documentación oficial</a>.</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/register/register.zip">Aquí</a> os subo el proyecto, simplemente tenéis que hacer un <i>syncdb</i> para crear una base de datos y probar. Aunque os recomiendo que lo hagais todo a mano para aprender mejor.</p>
<p>Y nada más, dejad algo de feedback que viene bien para la motivación.</p>
]]></content:encoded>
			<wfw:commentRss>http://pyblog.foxandxss.net/jugando-con-django-registration/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Análisis: PyCharm</title>
		<link>http://pyblog.foxandxss.net/analisis-pycharm</link>
		<comments>http://pyblog.foxandxss.net/analisis-pycharm#comments</comments>
		<pubDate>Sun, 27 Nov 2011 19:58:51 +0000</pubDate>
		<dc:creator>Fox</dc:creator>
				<category><![CDATA[Reseña]]></category>
		<category><![CDATA[PyCharm]]></category>

		<guid isPermaLink="false">http://pyblog.foxandxss.net/?p=70</guid>
		<description><![CDATA[Voy a analizar el IDE PyCharm de Jetbrains. Jetbrains son los creadores del IntelliJ IDEA, el cual es un IDE de Java y también del maravilloso ReSharper. Con IntelliJ IDEA han hecho como un conocido autor español hace con sus &#8230; <a href="http://pyblog.foxandxss.net/analisis-pycharm">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Voy a analizar el <i>IDE</i> <strong>PyCharm</strong> de <a href="http://www.jetbrains.com/">Jetbrains</a>.</p>
<p><strong>Jetbrains</strong> son los creadores del <strong>IntelliJ IDEA</strong>, el cual es un <i>IDE</i> de Java y también del maravilloso <a href="http://blog.foxandxss.net/analizando-resharper">ReSharper</a>.</p>
<p>Con <strong>IntelliJ IDEA</strong> han hecho como un conocido autor español hace con sus libros, le ha cambiado tres cosas y con eso han creado 20 <i>IDEs</i> más. Fuera bromas, han creado varios <i>IDEs</i> basados en <strong>IntelliJ IDEA</strong> y entre ellos está <strong>PyCharm</strong>.</p>
<p><strong>PyCharm</strong> como habéis podido deducir, es un IDE de <strong>Python</strong> con soporte de <strong>Django</strong>.</p>
<p>Paso a comentarios muchas de sus features, aunque seguro que olvidaré algunas y otras que todavía no he descubierto.<br />
<span id="more-70"></span><br />
Antes que nada os dejo una captura del <strong>IDE</strong> con <a href="http://pyblog.foxandxss.net/bcal-el-calendario-de-menstruacion">BCal</a> abierto.<br />
<a href="http://pyblog.foxandxss.net/cosasblog/pycharm/1.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/1.png" class="alignnone" width="600" height="363" /></a></p>
<h1>EDITOR</h1>
<p>Vamos a empezar con las features del editor de <strong>PyCharm</strong>:</p>
<p><strong>Coloreado de sintaxis:</strong></p>
<p>El editor ofrece coloreado de sintaxis (personalizable por supuesto) para cualquier lenguaje, ejemplos:</p>
<p>Python:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/2.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/2.png" class="alignnone" width="494" height="182" /></a></p>
<p>Para mi gusto, podría ser más completo.</p>
<p>Django Templates:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/3.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/3.png" class="alignnone" width="430" height="329" /></a></p>
<p>Javascript:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/4.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/4.png" class="alignnone" width="560" height="234" /></a></p>
<p>Para mi gusto, más conseguido que el de Visual Studio.</p>
<p>CSS:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/5.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/5.png" class="alignnone" width="227" height="234" /></a></p>
<p>Como véis tiene un coloreado bastante majete. (Aunque claro, también depende del tema que llevéis puesto, ese en concreto se llama <a href="http://pyblog.foxandxss.net/cosasblog/pycharm/Solarized%20Light.xml">Solarized Light</a>)</p>
<p><strong>Zen Coding:</strong></p>
<p><a href="https://code.google.com/p/zen-coding/">Zen Coding</a> no es algo especial de <strong>PyCharm</strong>, pero viene incluido de serie y es una maravilla.</p>
<p>¿Para qué sirve? Nos ayuda a escribir código <i>HTML</i> y <i>CSS</i> a la velocidad de la luz&#8230;</p>
<p>Vamos a poner un ejemplo&#8230; Necesitamos crear un <i>div</i> con un <i>ul</i> que tenga un <i>id=&#8221;lista&#8221;</i> y 3 <i>li</i> con <i>class=&#8221;elemento&#8221;</i> que a su vez contengan un <i>div</i> y no sé, un <i>span</i>.</p>
<p>Algo muy típico, pero en vez de escribirlo manualmente, escribimos:</p>
<pre class="brush: plain;">
div&gt;ul#lista&gt;li.elemento*3&gt;div+span
</pre>
<p>pulsamos <i>TAB</i> y se nos convierte en:</p>
<pre class="brush: xml;">
&lt;div&gt;
	&lt;ul id=&quot;lista&quot;&gt;
		&lt;li class=&quot;elemento&quot;&gt;
			&lt;div&gt;&lt;/div&gt;
			&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
		&lt;li class=&quot;elemento&quot;&gt;
			&lt;div&gt;&lt;/div&gt;
			&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
		&lt;li class=&quot;elemento&quot;&gt;
			&lt;div&gt;&lt;/div&gt;
			&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
	&lt;/ul&gt;
&lt;/div&gt;
</pre>
<p>Mucho más fácil, ¿no?</p>
<p>En <i>CSS</i> nos simplifica un poco la vida, vamos a ver algunos ejemplos:</p>
<pre class="brush: plain;">
bdt:n
bxsh:m
v:h
</pre>
<pre class="brush: css;">
border-top: none;
-moz-box-shadow: 0 0 0 0 #000;
visibility: hidden;
</pre>
<p>respectivamente.</p>
<p>En la página de <i>Zen Coding</i> o en las opciones de <strong>PyCharm</strong> puedes ver la lista de todos los atajos.</p>
<p><strong>Código no usado:</strong></p>
<p>Hay veces que tenemos <i>import</i> sin usar o variables que nunca se han usado. <strong>PyCharm</strong> nos la muestra en pantalla:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/6.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/6.png" class="alignnone" width="346" height="56" /></a></p>
<p>Tenía un <i>import</i> sin usar y ahi me lo ha puesto en gris. También pasa igual con variables:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/7.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/7.png" class="alignnone" width="301" height="45" /></a></p>
<p><strong>Diccionarios incluidos:</strong></p>
<p>Yo soy el primero que cuando instalo una aplicación que tiene un diccionario, se lo quito sin pensar. Escribo bastante bien y no suelo tener faltas de ortografía. Por pereza no quité el corrector (es de inglés, aunque parece que se pueden añadir más diccionarios) que trae, pero oye, es de lo más útil.</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/8.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/8.png" class="alignnone" width="273" height="69" /></a></p>
<p>sin querer puse <i>calendr.html</i> en vez de <i>calendar.html</i> y esto me avisa de que tengo un typo en la palabra. Obviamente se como escribir <i>calendar</i> pero en un lapsus lo puse mal y oye, me ayudó a tener que hacer debug como un tonto.</p>
<p><strong>Soporte i18n por defecto (PyCharm 2+):</strong></p>
<p>Ahora tenemos soporte para <i>i18n</i> por defecto en el IDE:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/9.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/9.png" class="alignnone" width="448" height="22" /></a></p>
<p>Si hacemos click en el cuadradito azul nos pregunta el idioma a editar:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/10.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/10.png" class="alignnone" width="298" height="97" /></a></p>
<p>Y si le damos al de <i>Aleman</i>:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/11.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/11.png" class="alignnone" width="189" height="77" /></a></p>
<p>Nos lleva directamente al <i>.po</i> y a la cadena elegida.</p>
<p><strong>Navegación entre objetos:</strong></p>
<p>Si quieres por ejemplo ir a la definición del formulario que estás usando, puedes hacer <i>CTRL+CLICK</i>:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/12.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/12.png" class="alignnone" width="357" height="87" /></a></p>
<p>Lo cual nos llevará directamente a la definición de <i>UserInfoForm</i>.</p>
<p>Podemos ir más allá, por ejemplo:<br />
<a href="http://pyblog.foxandxss.net/cosasblog/pycharm/13.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/13.png" class="alignnone" width="318" height="73" /></a></p>
<p>Si hacemos eso, nos llevará a la definición de la clase <i>Form</i> que está en el código fuente de <strong>Django</strong>:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/14.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/14.png" class="alignnone" width="231" height="59" /></a></p>
<p>Está fenomenal eso.</p>
<p><strong>Avisos varios:</strong></p>
<p>Por ejemplo, si colocamos un <i>anchor tag</i> y lo cerramos sin colocar su correspondiente </a>, el editor nos avisará de que eso puede no ser bueno:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/15.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/15.png" class="alignnone" width="455" height="77" /></a></p>
<h1>Soporte Python</h1>
<p>El soporte de <strong>Python</strong> es muy bueno, podemos destacar:</p>
<p><strong>Auto completado de código:</strong></p>
<p>El auto completado de código de <strong>PyCharm</strong> es bastante bueno, ahí van algunos ejemplos:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/16.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/16.png" class="alignnone" width="578" height="332" /></a></p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/17.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/17.png" class="alignnone" width="522" height="228" /></a></p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/18.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/18.png" class="alignnone" width="424" height="63" /></a></p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/19.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/19.png" class="alignnone" width="440" height="297" /></a></p>
<p><strong>Auto-import de librerías:</strong></p>
<p>Ya no necesitamos recordar dónde estaban las clases o métodos que queremos usar:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/20.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/20.png" class="alignnone" width="350" height="70" /></a></p>
<p>Si en ese caso pulsamos ALT + ENTER (no sé por qué pone &#8216;Introduzca&#8217;) importará directamente el método <i>render_to_response</i>.</p>
<p><strong>Refactorización de código:</strong></p>
<p>Muchas veces nos da consejos de si algún código que tenemos puede escribirse de mejor forma, por ejemplo:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/21.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/21.png" class="alignnone" width="301" height="87" /></a></p>
<p>Y si le das a la zona amarilla saldrá un recuadro con distintas opciones, entre ellas la de cambiar el código por otro:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/22.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/22.png" class="alignnone" width="269" height="165" /></a></p>
<h1>Soporte Django</h1>
<p>Para <strong>Django</strong> también hay cosas chulas, ejemplos:</p>
<p><strong>Atajos para &#8216;template tags&#8217;:</strong></p>
<p>Hay que admitirlo, es un coñazo tener que escribir código como:</p>
<pre class="brush: xml;">
{% for palabra in palabras %}

{% endfor %}
</pre>
<p><strong>PyCharm</strong> te ofrece la posibilidad de simplificarlo, sólo tienes que hacer:</p>
<pre class="brush: plain;">
for[TAB]
</pre>
<p>O sea, escribes <i>for</i> pulsas TAB, te situa el cursor a la derecha del <i>in</i>, escribes la colección, pulsas ENTER, te situa para colocar el nombre del elemento, pulsas ENTER y ya te coloca dentro del TAG para escribir el código. Es más fácil probarlo que explicarlo <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>También hay atajos para <i>block</i>, <i>if</i>, etc. Puedes ver la lista completa en las opciones de <strong>PyCharm</strong>.</p>
<p><strong>Soporte para diferentes templates (Jinja2, mako y Django) (PyCharm 2+):</strong>:</p>
<p>Si no nos gusta el motor de templates que trae <strong>Django</strong> por defecto, podemos optar por <a href="http://jinja.pocoo.org/">Jinja</a> o bien por <a href="http://www.makotemplates.org/">Mako</a>.</p>
<p><strong>PyCharm 2</strong> ofrece soporte para estos dos motores, con su coloreado, su auto completado de código&#8230;</p>
<h1>IDE</h1>
<p>Y vamos con la última sección, el IDE.</p>
<p><strong>Poder usar el <i>manage.py</i> desde PyCharm:</strong></p>
<p>Tecnicamente podemos hacer cualquier cosa desde el <i>IDE</i> sin tener que recurrir a la consola. El usar el <i>manage.py</i> es una de ellas.</p>
<p>Desde el menú vamos a <i>Tools > Run manage.py task&#8230;</i></p>
<p>Te saldrá una listas de cosas que puedes hacer:<br />
<a href="http://pyblog.foxandxss.net/cosasblog/pycharm/23.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/23.png" class="alignnone" width="525" height="416" /></a></p>
<p>Si lo que quieres hacer acepta parámetros como <i>startapp</i> nos saldrá un dialogo para introducir los parámetros:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/24.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/24.png" class="alignnone" width="402" height="151" /></a></p>
<p><strong>Múltiples intérpretes:</strong></p>
<p>¿Que estamos usando <a href="http://pyblog.foxandxss.net/entendiendo-virtualenv-y-pip">virtualenv</a>? No pasa nada, podemos configurar en <strong>PyCharm</strong> todos los intérpretes que queramos:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/25.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/25.png" class="alignnone" width="567" height="336" /></a></p>
<p>Ahí configuramos los interpretes que tenemos y seleccionamos uno para el IDE (que no para el proyecto), con esto quiero decir que si tenemos un <strong>virtualenv</strong> que tiene instalado, no sé, <strong>django-registration</strong>, <strong>PyCharm</strong> lo verá y podrá ofrecernos su auto completado y todas esas cosas.</p>
<p>Luego para el proyecto en concreto puedes decirle que virtualenv usar para ejecutarse.</p>
<p><strong>Plugins</strong></p>
<p>El sistema de plugins que tiene es muy bueno, y tiene una cantidad bastante maja de plugins. Por defecto tiene muchos puestos:<br />
<a href="http://pyblog.foxandxss.net/cosasblog/pycharm/26.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/26.png" class="alignnone" width="413" height="490" /></a><br />
Puedes ver que la lista de plugins instalada por defecto (a excepción de los dos que puse yo) es bastante grande. <i>Less</i>, <i>Coffescript</i>, <i>Git</i>, etc.</p>
<p><strong>Soporte para sistemas de control de versiones</strong></p>
<p>¿Tenemos un repo en <strong>Github</strong>? ¿O en <strong>Bitbucket</strong>? Pues agregamos el plugins si fuera necesario, y en el caso de <strong>Bitbucket</strong> por ejemplo nos vamos a <i>VCS > Checkout from version control > Bitbucket</i>, metemos nuestros credenciales y nos aparecerá una lista con nuestros repositorios:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/27.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/27.png" class="alignnone" width="480" height="242" /></a></p>
<p>Al importar el proyecto no solo lo importaremos, también estará sincronizado con el repositorio y eso nos da mil cosas.</p>
<p>Podemos ver si un fichero ha sido modificado con respecto al repositorio, añadido al proyecto pero no al repositorio, o añadido a ambos pero no sincronizado.</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/28.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/28.png" class="alignnone" width="129" height="66" /></a></p>
<p>Los colores son:</p>
<ul>
<li>Negro: Fichero en ambos sitios (repo y proyecto) y sin cambios.</li>
<li>Rojo: Añadido al proyecto pero no al repositorio.</li>
<li>Verde: Añadido a ambos sitios.</li>
<li>Azul: Modificado con respecto al repositorio.</li>
</ul>
<p>Además podemos ver las diferencias entre ficheros, hacer un <i>pull</i> para traernos los cambios, o casi cualquier cosa que podamos hacer con <i>Tortoise</i>.</p>
<p><strong>Shell Python y Django integradas</strong></p>
<p>En el mismo menú <i>Tools</i> tenemos una <i>shell</i> de <strong>Python</strong> y una de <strong>Django</strong> (lo que nos abriría <i>python manage.py shell</i>).</p>
<p>Es otra de las opciones que nos hace no tener que recurrir a una consola si no queremos.</p>
<p><strong>Visor de bases de datos incluido</strong></p>
<p>¿Queremos ver qué tenemos en nuestra base de datos <strong>Sqlite</strong>?</p>
<p>Fácil, <strong>PyCharm</strong> al ver que usamos dichas bases de datos, nos ofrecerá la posibilidad de instalar un plugin para tratar con ellas.</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/29.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/29.png" class="alignnone" width="374" height="363" /></a></p>
<p>Ahí un extracto de lo que sería mi base de datos. También nos deja ver los datos que hay dentro y eso.</p>
<p><strong>Multiples esquemas de atajos</strong></p>
<p>Al instalar <strong>PyCharm</strong> nos da la posibilidad de seleccionar un esquema de atajos que se adapte más a nuestros gustos. Yo personalmente escojí el de <strong>Visual Studio</strong> que ya me lo conozco bien <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Ejecución y Debug</strong></p>
<p>Y por último, ejecución y debug.<br />
<a href="http://pyblog.foxandxss.net/cosasblog/pycharm/30.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/30.png" class="alignnone" width="119" height="28" /></a></p>
<p>Si le damos a ejecutar, <strong>PyCharm</strong> lanzará el servidor integrado de <strong>Django</strong> y bueno, no hace nada especial, nos muestra todas las peticiones que hacemos al servidor y nos muestra las excepciones que se produzcan.</p>
<p>Por otro lado, el debugger es más interesante.</p>
<p>Tiene todo lo que podemos esperar de un debugger, ni más ni menos. La versión 2.0 de <strong>PyCharm</strong> trae hasta debugger de <strong>Javascript</strong>.</p>
<p>Lo de siempre, marcamos puntos donde queramos que el código se pare y a analizar los datos:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/pycharm/31.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/pycharm/31.png" class="alignnone" width="556" height="231" /></a></p>
<h1>Conclusión</h1>
<p>Pensé que nunca llegaría <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p><strong>PyCharm</strong> sin llegar al nivel de <strong>Visual Studio</strong>, ha hecho que pueda programar en <strong>Django</strong> sin preocuparme por nada y de hecho tiene cosas que no he visto en <strong>Visual Studio</strong>, al menos no de forma tan cómoda, como por ejemplo el tema de localización y hasta el coloreado de <strong>Javascript</strong> es mejor (aunque el autocompletado es algo más simple).</p>
<p>Lo recomiendo 200% y es baratito <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Hasta otra.</p>
]]></content:encoded>
			<wfw:commentRss>http://pyblog.foxandxss.net/analisis-pycharm/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>BCal, el calendario de menstruación</title>
		<link>http://pyblog.foxandxss.net/bcal-el-calendario-de-menstruacion</link>
		<comments>http://pyblog.foxandxss.net/bcal-el-calendario-de-menstruacion#comments</comments>
		<pubDate>Sat, 26 Nov 2011 17:31:47 +0000</pubDate>
		<dc:creator>Fox</dc:creator>
				<category><![CDATA[Mis programas]]></category>
		<category><![CDATA[BCal]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[django-registration]]></category>
		<category><![CDATA[Localización]]></category>

		<guid isPermaLink="false">http://pyblog.foxandxss.net/?p=60</guid>
		<description><![CDATA[Hola! Despues de muchas horas de trabajo he conseguido terminar una primera versión de BCal. ¿Qué es BCal? BCal es un calendario de menstruación escrito por supuesto en Django. Está en inglés, alemán y por supuesto en español. Si queréis &#8230; <a href="http://pyblog.foxandxss.net/bcal-el-calendario-de-menstruacion">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Hola! Despues de muchas horas de trabajo he conseguido terminar una primera versión de <strong>BCal</strong>.</p>
<p>¿Qué es <strong>BCal</strong>? <strong>BCal</strong> es un calendario de menstruación escrito por supuesto en <strong>Django</strong>.</p>
<p>Está en inglés, alemán y por supuesto en español.</p>
<p>Si queréis probarlo, id a: <a href="http://bcal.foxandxss.net">http://bcal.foxandxss.net</a></p>
<p>Si queréis ver su código, id a: <a href="https://bitbucket.org/Foxandxss/bcal/wiki/Home">https://bitbucket.org/Foxandxss/bcal/wiki/Home</a></p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/bcal/bcalscreen.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/bcal/bcalscreen.png" class="alignnone" width="600" height="445" /></a></p>
<p>Un saludo.</p>
]]></content:encoded>
			<wfw:commentRss>http://pyblog.foxandxss.net/bcal-el-calendario-de-menstruacion/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Organizando ficheros estáticos</title>
		<link>http://pyblog.foxandxss.net/organizando-ficheros-estaticos</link>
		<comments>http://pyblog.foxandxss.net/organizando-ficheros-estaticos#comments</comments>
		<pubDate>Fri, 18 Nov 2011 18:33:59 +0000</pubDate>
		<dc:creator>Fox</dc:creator>
				<category><![CDATA[Articulos]]></category>
		<category><![CDATA[Despliegue]]></category>
		<category><![CDATA[static]]></category>

		<guid isPermaLink="false">http://pyblog.foxandxss.net/?p=57</guid>
		<description><![CDATA[Vamos a hablar un poco de los ficheros estáticos de Django y ver cómo podríamos organizarlos. Como ya expliqué en el artículo sobre despliegue, tenemos un directorio static en el directorio principal donde colocamos nuestros ficheros estáticos, o sea, los &#8230; <a href="http://pyblog.foxandxss.net/organizando-ficheros-estaticos">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Vamos a hablar un poco de los ficheros estáticos de <strong>Django</strong> y ver cómo podríamos organizarlos.</p>
<p>Como ya expliqué en el artículo sobre <a href="http://pyblog.foxandxss.net/desplegando-django-en-cherokee">despliegue</a>, tenemos un directorio <i>static</i> en el directorio principal donde colocamos nuestros ficheros estáticos, o sea, los <i>css</i>, <i>javascript</i>, <i>imagenes</i>, etc.</p>
<p>Para las aplicaciones pequeñas esto va de fábula, pero en cuanto la cosa empieza a complicarse un poco, viene bien que nos organicemos un poco.</p>
<p>Como de costumbre, vamos a crear una aplicación de ejemplo para probar.<br />
<span id="more-57"></span></p>
<pre class="brush: plain;">
$ django-admin.py startproject estaticos
$ cd estaticos/
$ python manage.py startapp ejemplo
</pre>
<p>Ahora bien, en vez de crear un directorio <i>static</i> y otro <i>templates</i> en el directorio principal, vamos a crear los siguientes:</p>
<p><i>templates_common</i><br />
<i>static_common</i></p>
<p>¿Por qué así? Dada la naturaleza de <strong>Django</strong>, lo interesante sería hacer que las aplicaciones de nuestro proyecto fuesen lo más independiente posibles. Por ejemplo, creo una web y añado una aplicación que sea un visor de <i>Twitter</i>. Estaría de puta madre si pudiera coger esa aplicación tal cual y pegarla en mi proyecto de blog y colocar dicho visor en la barra lateral.</p>
<p>Para lograr este resultado, entre otras cosas, la aplicación deberá contener sus propios ficheros estáticos y sus propios templates, así que tendremos un directorio para los ficheros estáticos comunes de todo el proyecto y otro para los templates comunes.</p>
<p>Luego cada proyecto tendrá sus propios directorios también como veremos luego.</p>
<p>Vamos a darle un poco de amor al <i>settings.py</i></p>
<p>Empezamos añadiendo una variable para definir la ruta actual del proyecto:</p>
<pre class="brush: python;">
MANAGERS = ADMINS

CURRENT_PATH = os.path.dirname(__file__)

DATABASES = {
</pre>
<p>No os olvidéis de importar la librería <i>os</i>.</p>
<p>Acto seguido vamos a configurar tres variables (ya creadas de antemano):</p>
<pre class="brush: python;">
STATIC_ROOT = os.path.join(CURRENT_PATH, 'static')

STATICFILES_DIRS = (
    os.path.join(CURRENT_PATH, 'static_common'),
)

TEMPLATE_DIRS = (
    os.path.join(CURRENT_PATH, 'templates_common'),
)
</pre>
<p>Esto lo explicaré cuando llegue el momento, por ahora creed en mi palabra <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>También tenemos que añadir nuestra aplicación al fichero:</p>
<pre class="brush: python; highlight: [12];">
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
    'estaticos.ejemplo',
)
</pre>
<p>Bueno, ya está listo.</p>
<p>Vamos a crear un template que nos sirva de base para nuestra aplicación (/templates_common/base.html):</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;title&gt;Ejemplo de ficheros estáticos&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div id=&quot;wrapper&quot;&gt;
        {% block content %}{% endblock %}
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Ok, ya tenemos una página base. Vamos a darle algo de color y alegría con <i>css</i>.</p>
<p>Creamos un css (/static_common/css/styles.css):</p>
<pre class="brush: css;">
body {
    background-color: #add8e6;
}

#wrapper {
    width: 960px;
    margin: 0 auto;
    background-color: #ffffff;
    padding: 10px;
}
</pre>
<blockquote><p>
Lo he creado dentro de un directorio llamado <i>css</i> para organizar mejor los ficheros estáticos. (para los javascript se suele crear uno llamado <i>js</i>).
</p></blockquote>
<p>Bueno, un css simplón.</p>
<p>Vamos a añadirlo a <i>base.html</i>:</p>
<pre class="brush: xml; highlight: [4, 5];">
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;title&gt;Ejemplo de ficheros estáticos&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;{{ STATIC_URL }}css/styles.css&quot;&gt;
    {% block external %}{% endblock %}
&lt;/head&gt;
</pre>
<p>Lo de <i>{{ STATIC_URL }}</i> lo explicaré mejor luego, pero básicamente es por si cambiamos la ruta de los ficheros estáticos, para no tener que ir fichero por fichero actualizando las rutas.</p>
<p>Aparte de eso hemos añadido un bloque nuevo. Lo usaremos por si nuestros otros templates necesitan importar sus cosas.</p>
<p>Como el html base y el css de este son cosas comunes de toda la aplicación, los crearemos en los directorios comunes.</p>
<p>Bueno, pues vamos a crear algo de contenido para nuestra aplicación.</p>
<p>Creamos las siguientes directorios:</p>
<p><i>/templates/ejemplo/</i><br />
<i>/static/ejemplo/</i></p>
<p>Los creamos dentro del directorio de nuestra aplicación <i>ejemplo</i>, o sea quedaría así:</p>
<p><i>~/ejemplo/templates/ejemplo/</i><br />
<i>~/ejemplo/static/ejemplo/</i></p>
<p>Aunque suene raro, hay que crear un directorio con el nombre de la aplicación dentro de los directorios <i>static</i> y <i>templates</i>. Luego esto tendrá mas sentido, de verdad.</p>
<p>Bueno, vamos a crear una vista, así que abrimos el views.py de nuestra aplicación y colocamos la siguiente vista:</p>
<pre class="brush: python;">
from django.shortcuts import render_to_response
from django.template.context import RequestContext

def home(request):
    gente = ['Jesus', 'Rosi', 'Alvaro', 'Pol', 'Juan']
    return render_to_response('ejemplo/index.html', locals(), context_instance=RequestContext(request))
</pre>
<p>Bueno, creamos una lista y la enviamos al template. Nótese que he puesto <i>&#8216;ejemplo/index.html&#8217;</i>. Django ya sabe donde buscar el template (Luego verás el por qué).</p>
<p>Vamos a crear el template (ejemplo/templates/ejemplo/index.html):</p>
<pre class="brush: xml;">
{% extends &quot;base.html&quot; %}
{% block external %}
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;{{ STATIC_URL }}ejemplo/css/styles.css&quot; /&gt;
{% endblock %}
{% block content %}
    &lt;div id=&quot;ejemplo&quot;&gt;
        &lt;p&gt;Estamos en la aplicación ejemplo&lt;/p&gt;
        &lt;ul&gt;
            {% for persona in gente %}
                &lt;li&gt;{{ persona }}&lt;/li&gt;
            {% endfor %}
        &lt;/ul&gt;
    &lt;/div&gt;
{% endblock %}
</pre>
<p>Bueno, creamos un div, y mostramos la lista. Además hemos hecho uso del bloque <i>external</i> para cargar un css más que será el css que diseñe nuestra aplicación <i>ejemplo</i>, así cuando movamos la aplicación a otro lado, se llevará los <i>css</i> con el.</p>
<p>Bueno, vamos a crear el <i>css</i> (ejemplo/static/ejemplo/css/styles.css):</p>
<pre class="brush: css;">
#ejemplo {
    width: 500px;
    background-color: #cecece;
    border: 1px solid #030303;
    padding: 5px;
}

#ejemplo ul {
    list-style: none;
}
</pre>
<p>He creado un directorio llamado <i>css</i> dentro de <i>/ejemplo/static/ejemplo/</i> como ya hicimos con <i>static_common</i>. Ya se que es un poco lio, pero todo tendrá sentido luego.</p>
<p>Finalmente vamos a modificar urls.py para que esto empiece a andar:</p>
<pre class="brush: python;">
urlpatterns = patterns('',
    url(r'^$', 'ejemplo.views.home'),
)
</pre>
<p>Vale, vamos a ejecutar la aplicación y vamos a verla.</p>
<p>Uh, qué fea <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> . Bueno, la idea no era la web en sí <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>Vale, la web funciona, ¿Cual era la idea pues de este post?</p>
<p>El desarrollo en <strong>Django</strong> es muy bonito, el servidor integrado que tiene hace muuuuuuucha magia, pero cuando desplegamos, la magia se va.</p>
<p>¿De qué magia hablo? Pues del primo de Harry Potter que suspendió la escuela de mágia y ahora se dedica a facilitarnos la vida. Venga no, ahora en serio.</p>
<p>El servidor integrado de <strong>Django</strong> nos simplifica mucho la vida, muchisimo. Es capaz de encontrar ficheros estáticos fácilmente. ¿Recuerdas <i>STATICFILES_DIRS</i>? Le dice a dicho servidor dónde buscar ficheros estáticos. ¿Recuerdas <i>STATCFILES_FINDERS</i>? Son clases que saben donde buscar más ficheros estáticos, por ejemplo:</p>
<p><i>&#8216;django.contrib.staticfiles.finders.AppDirectoriesFinder&#8217;,</i></p>
<p>Con esa clase, el servidor busca en los directorios de nuestras aplicaciones para ver si hay más ficheros estáticos.</p>
<p>Con toda esta ayuda, sólo necesitamos arrancar la aplicación y ésta será capaz de encontrar todos los ficheros estáticos por si sola. Ahora bien, toda esa mágia desaparece en cuanto colocamos el <i>DEBUG</i> a <i>False</i>, así que &#8230; ¿Ahora qué? ¿Copiamos a mano todo a un directorio? Nah. ¿Recuerdas el parámetro que pusimos al principo de la aplicación?</p>
<pre class="brush: python;">
STATIC_ROOT = os.path.join(CURRENT_PATH, 'static')
</pre>
<p>Y el ya por defecto:</p>
<pre class="brush: python;">
STATIC_URL = '/static/'
</pre>
<p>El primero lo que dice es: El directorio de los ficheros estáticos estará en <i>~/static/</i> y el segundo no es útil para hacer referencia a dicho directorio en los templates (entre otros sitios) como ya hemos visto antes.</p>
<p>Vale, te sigo, pero&#8230; ¿Ese directorio donde está? El que tenemos se llama <i>static_common</i> y ese no es.</p>
<p>Ese directorio es donde pondremos TODOS los ficheros estáticos de nuestro proyecto. ¿A mano? ¿O a máquina?</p>
<p>A maquina a maquina&#8230;</p>
<p>Tenemos un comando que nos hace todo el trabajo:</p>
<pre class="brush: plain;">
python manage.py collectstatic
</pre>
<p>Ya está, en nuestro caso nos ha creado algo así:</p>
<pre class="brush: plain;">
static
----css
--------styles.css
----ejemplo
--------css
------------styles.css
</pre>
<p>¿Le veis ahora sentido a los directorios raros? Ahora tenemos un directorio <i>static</i> y está super bien organizado, los estáticos comunes en el directorio principal y los de cada aplicación en su propio directorio.</p>
<p>Simplemente tenemos que decirle a nuestro servidor (<strong>Cherokee</strong> por ejemplo) que nos sirva ese directorio.</p>
<p>Todo esto es importante también si usais el módulo de admin, puesto que el servidor integrado también encuentra automágicamente los css del admin pero una vez depleguemos pues no estarán. Así que ejecutando <i>collectstatic</i> también copiará a <i>static</i> los <i>css</i> del admin.</p>
<p>Os dejo el source del proyecto por si estáis flojos: <a href="http://pyblog.foxandxss.net/cosasblog/estaticos/estaticos.zip">Ejemplo.</a></p>
<p>Si no estáis flojos, dejad un comentario ya de paso <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://pyblog.foxandxss.net/organizando-ficheros-estaticos/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Reseña: Beginning Django E-Commerce</title>
		<link>http://pyblog.foxandxss.net/resena-beginning-django-e-commerce</link>
		<comments>http://pyblog.foxandxss.net/resena-beginning-django-e-commerce#comments</comments>
		<pubDate>Sun, 13 Nov 2011 13:17:45 +0000</pubDate>
		<dc:creator>Fox</dc:creator>
				<category><![CDATA[Reseña]]></category>
		<category><![CDATA[E-Commerce]]></category>
		<category><![CDATA[libro]]></category>

		<guid isPermaLink="false">http://pyblog.foxandxss.net/?p=52</guid>
		<description><![CDATA[Vamos con la primera reseña del blog. Para los que conozcan mi otro blog, me gusta reseñar las cosas que voy leyendo. Este caso es un poco más especial, porque no he podido terminarlo, ya veréis por qué. El libro &#8230; <a href="http://pyblog.foxandxss.net/resena-beginning-django-e-commerce">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Vamos con la primera reseña del blog.</p>
<p>Para los que conozcan mi otro <a href="http://blog.foxandxss.net/" title="blog" target="_blank">blog</a>, me gusta reseñar las cosas que voy leyendo.</p>
<p>Este caso es un poco más especial, porque no he podido terminarlo, ya veréis por qué.</p>
<p>El libro en cuestión es:</p>
<p><strong>Beginning Django E-Commerce</strong></p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/resenaecommerce/portada.jpg"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/resenaecommerce/portada.jpg" class="alignnone" width="200" height="265" /></a><br />
<span id="more-52"></span><br />
Este libro hace 2 cosas, una muy bien y una bastante regular.</p>
<p>Nos introduce al mundo del <i>E-Commerce</i> y lo hace muy cojonudamente, sin embargo, aunque se supone que es un libro de introducción a <strong>Django</strong>, esto no lo hace taan bien.</p>
<p><strong>Django</strong> tiene una documentación oficial al nivel de <i>MSDN</i> de <i>Microsoft</i>. Es buena a rabiar y encontrarás de todo. El &#8220;problema&#8221; que tiene la documentación, es que es una referencia, y dejando de lado el pequeño tutorial que tiene (que es muy bueno, pero escaso) pues necesitamos de algún libro para aprender. Al menos yo.</p>
<p>El problema (y esta vez sin comillas) es que hubo un <i>bum</i> de libros hace un tiempo y ahí se quedó la cosa.</p>
<p>Mientras escribo esto, <strong>Django</strong> va por la versión <i>1.3</i> y el libro más moderno se basa en la versión <i>1.2</i> (Aunque las malas lenguas dicen que no es 1.2 ni de cerca).</p>
<p><strong>Django</strong> es un lenguaje muy vivo y los desarrolladores suelen meter muchas mejoras con las nuevas versiones y cambios. A veces rompen cosas (por un bien mayor) y esto supone que los libros más viejos explican cosas que ya no funcionan de la misma forma.</p>
<p>Este libro está basado en la versión 1.1 de <strong>Django</strong> lo cual tiene ciertas cosas que ya se hacen de la misma forma y nos hará darle 20 vueltas al asunto hasta que nos demos cuenta que está deprecated o bien modificado en la versión <i>1.3</i>.</p>
<p>La leyenda cuenta de que existe una página de erratas con toodo documentado, pero es sólo eso, una leyenda. Bueno, al parecer <i>Apress</i> borró todas las erratas y el autor no las guardaba, así que estás solo ante el peligro&#8230;</p>
<p>¡Y que peligro! Dejando de lado las cosas que en la versión <i>1.3</i> se hacen de otra forma, tiene el mayor numero de <i>typos</i> que he visto en mi vida, y he leido muchos libros. Te vas a estar dando cabezazos contra el teclado cada dos por tres. No sé, en el primer tema te pone una entrada para <i>urls.py</i> y luego en otro <i>snippet</i> ves que la ha puesto de otra forma y tu&#8230; ¿Por qué lo ha cambiado? Buena pregunta, estaba mal.</p>
<p>Tiene fallos, fallos, fallos, muchos fallos, errores muy muy tontos que te hacen mirar y remirar el código por si lo has copiado mal, te hacen mirar google por si es algo deprecated pero no, finalmente es un <i>typo</i> como una catedral.</p>
<p>Avanzar por este libro es a veces desesperante porque intentas ejecutar tu aplicación y ves que tienes errores y tienes que buscarte la vida para solucionarlos.</p>
<p>Dejando de lado sus fallos, tiene otro gran problema. No explica.</p>
<p>¿Un libro que no explica? Pues sí, toda una sorpresa. Es curioso, lo relacionado con <i>E-Commerce</i> lo explica muy muy bien, pero todo lo relacionado con <strong>Django</strong> pues no lo hace.</p>
<p>No es que lance líneas de código sin decir nada, solo es que sus explicaciones son muy simples, te cuenta tres o cuatro cosas sobre esa función y ya está, te quedas a medias.</p>
<p>Te puede hacer escribir un algoritmo de búsqueda o uno para encontrar productos recomendados. Escribir 200 lineas de código y quedarte perdido. Apenas te explica nada y yo he llegado al momento donde escribía código sin saber el por qué y llegado a ese momento, he cerrado el libro y me he dedicado a otra cosa.</p>
<p>De nada vale leer si tus conocimientos no avanzan con el libro, es estúpido y punto.</p>
<p>Por otro lado, por simplificar (vamos a pensar bien), muchas de sus implementaciones son malísimas, código ignora cualquier principio de programación.</p>
<p>Bueno, no todo es malo en este libro. Tiene cosas muy muy buenas.</p>
<p>Explica muuuy bien todo lo relacionado con E-Commerce.</p>
<p>Te explica como montarte un sistema de <i>checkout</i> usando <i>Google checkout</i>, usando tu propio carrito de la compra y pasandoselo a <i>Google Checkout</i> en XML. No sólo te explica como hacerlo, también te explica el por qué deberías de hacerlo para una tienda nueva. Aquí si que va paso a paso desde registrarte en <i>Google Checkout</i> (Usando la sandbox, claro está) hasta poder hacer pedidos en tu tienda y verlos en la web de <i>Google Checkout</i>.</p>
<p>También explica como montarte tu propio sistema de <i>checkout</i> usando <i>Authorize.net</i> como pasarela de pago. También te explica perfectamente como montarlo todo para hacerlo funcionar en tu aplicación. Te enseña algoritmos para comprobar tarjetas de créditos y cosas por el estilo.</p>
<p>Cosas para el <i>E-Commerce</i> las explica muy bien, pero el resto pues no tanto.</p>
<p><strong>Positivo</strong></p>
<ul>
<li>Todo el tema relacionado con <i>E-Commerce</i> es brillante.
<li>La introduccion a <strong>Django</strong>, dejado de lado los typos, es buena.
</ul>
<p><strong>Negativo</strong></p>
<ul>
<li>Libro desactualizado, tiene muchas cosas deprecated</li>
<li>El editor no hizo un buen trabajo, tiene MUCHOS typos</li>
<li>Muchas de las cosas que hacen tienen una explicación bastante deficiente</li>
<li>El código es muy muy mejorable, y bajo mi opinión, no le costaba mucho mejorarlo</li>
</ul>
<p>Mi nota final es de <strong>4</strong>. Así que vuelva en septiembre, quiero decir, necesitamos una nueva edición quitando todo lo malo.</p>
]]></content:encoded>
			<wfw:commentRss>http://pyblog.foxandxss.net/resena-beginning-django-e-commerce/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Entendiendo virtualenv y pip</title>
		<link>http://pyblog.foxandxss.net/entendiendo-virtualenv-y-pip</link>
		<comments>http://pyblog.foxandxss.net/entendiendo-virtualenv-y-pip#comments</comments>
		<pubDate>Sun, 06 Nov 2011 17:14:21 +0000</pubDate>
		<dc:creator>Fox</dc:creator>
				<category><![CDATA[Articulos]]></category>
		<category><![CDATA[Cherokee]]></category>
		<category><![CDATA[pip]]></category>
		<category><![CDATA[virtualenv]]></category>

		<guid isPermaLink="false">http://pyblog.foxandxss.net/?p=44</guid>
		<description><![CDATA[Vamos a hablar de estos dos maravillosos paquetes de Python. ¿Qué es pip y qué es virtualenv? Empezaremos hablando de pip. pip pip es un gestor de paquetes de Python, como los gestores que hay para Linux tipo apt-get, pacman, &#8230; <a href="http://pyblog.foxandxss.net/entendiendo-virtualenv-y-pip">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Vamos a hablar de estos dos maravillosos paquetes de <strong>Python</strong>.</p>
<p>¿Qué es <strong>pip</strong> y qué es <strong>virtualenv</strong>?</p>
<p>Empezaremos hablando de <strong>pip</strong>.<br />
<span id="more-44"></span></p>
<h1>pip</h1>
<p><strong>pip</strong> es un gestor de paquetes de <strong>Python</strong>, como los gestores que hay para <i>Linux</i> tipo <i>apt-get</i>, <i>pacman</i>, etc.</p>
<p>Para aquellos que esten pensando&#8230; ¿No es lo mismo que <strong>easy_install</strong>? Bueno, <strong>pip</strong> es su evolución.</p>
<p>Con <strong>pip</strong> podemos buscar, instalar, actualizar y desinstalar paquetes.</p>
<p>Vale, en mi sistema no está&#8230; ¿Cómo lo instalo?</p>
<p>Tenemos varias maneras, si ya tenemos el comando <strong>easy_install</strong> podemos hacer un:</p>
<pre class="brush: plain;">
$ sudo easy_install pip
</pre>
<p>Siempre podéis tirar de vuestro gestor de paquete de vuestra distro:</p>
<pre class="brush: plain;">
$ sudo apt-get install python-pip
$ sudo pacman -S python2-pip
</pre>
<p>para Ubuntu / Archlinux respectivamente.</p>
<p>Si usais windows y no tenéis <strong>easy_install</strong> podéis bajar <a href="http://pyblog.foxandxss.net/cosasblog/virtualenv/ez_setup.py" title="este script" target="_blank">este script</a> y ejecutarlo de la siguiente forma (usando cmd):</p>
<pre class="brush: plain;">
python ez_setup.py
</pre>
<p>Y ya proceder con la instalación igual que en <i>Linux</i> (Obviamente ignorando el <i>$</i> pues es solo para indicar que estamos en la consola <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> )</p>
<p>Ahora que está instalado, veremos que su uso es muy facilito, con un simple:</p>
<pre class="brush: plain;">
$ sudo pip install django
</pre>
<p>en Linux y:</p>
<pre class="brush: plain;">
pip install django
</pre>
<p>en Windows.</p>
<p>Con eso instalaríamos <strong>Django</strong> en nuestro sistema.</p>
<p>En concreto, su uso básico (permite hacer cosas más complejas como instalar desde un fichero local o de un sistema de control de versiones) se reduce a:</p>
<pre class="brush: plain;">
$ sudo pip search django
$ sudo pip install django
$ sudo pip install --upgrade django
$ sudo pip uninstall django
</pre>
<p>En el cual, buscaríamos, instalaríamos, actualizaríamos y borraríamos un paquete respectivamente.</p>
<p>Como veis, el uso de <strong>pip</strong> es bastante sencillo.</p>
<p>Si queréis más información podéis acudir a su <a href="http://www.pip-installer.org/en/latest/index.html#">documentación oficial</a> que es bastante sencillita de entender.</p>
<p>Si queréis, también podéis consultar via web la lista de paquetes con los que <strong>pip</strong> trabaja, o sea, en la página de <a href="http://pypi.python.org/pypi/pip">PyPi</a>.</p>
<h1>virtualenv</h1>
<p>¿Qué es <strong>virtualenv</strong> y por qué no paran de hablar del el?</p>
<p>Tengo por costumbre dar razones del <i>por qué</i> antes de decir el <i>qué</i>.</p>
<p>Vamos a poner un supuesto caso:</p>
<p>Tenemos nuestro <strong>Cherokee</strong> funcionando con dos aplicaciones <strong>Django</strong> a pleno rendimiento y estamos trabajando en nuestra tercera aplicación y vemos un anuncio:</p>
<p>¡Nueva beta de la próxima release de <strong>Django</strong> y tu&#8230; mola, voy a ver los cambios&#8230; Viendo esos cambios resulta que ponen algo nuevo que te vendría fenomenal para tu nueva aplicación y decides pues instalar dicha beta y hacer uso de esas cosas nuevas.</p>
<p>Terminas la aplicación, la montas en su servidor y actualizas el <strong>Django</strong> que tienes ahí instalado para instalar la beta. Pruebas tu nueva aplicación y de fábula pero luego te pones a usar las otras dos que tienes y plaf, revienta.</p>
<p>Te das cuenta que la nueva versión ha roto algo que esa aplicación usa o bien al ser una beta pues tiene un hermoso bug. ¿Ahora qué? Estás en una dificil situación.</p>
<p>O bien vuelves a poner la versión antigua de <strong>Django</strong> haciendo que tu nueva aplicación no funcione, o bien adaptas la nueva aplicación para la versión antigua o intentas adaptar las viejas a la nueva versión (y si tiene bugs pues va a ser que no).</p>
<p>¿Es un poco putada, no?</p>
<p>Si, la verdad es que sí, por eso los chicos de <strong>Django</strong> han pensado en una perfecta solución: <strong>virtualenv</strong>.</p>
<p>¿Qué es <strong>virtualenv</strong>? <strong>virtualenv</strong> es un <i>sandbox</i>, vale, parezco la <i>RAE</i> cuando le pides la definición de algo y te da una respuesta que necesita otra definición y así sucesivamente <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>Un <i>sandbox</i> es un mecanismo de seguridad que se usa para ejecutar programas de forma aislada. Suena un poco raro, así que vamos a <i>&#8220;pythonear&#8221;</i> esa definición.</p>
<p><strong>virtualenv</strong> es un paquete que nos sirve para tener una instalación <i>virtual</i> de <strong>Python</strong>, o sea, <strong>virtualenv</strong> es un entorno virtual de <strong>Python</strong> en el cual tendremos nuestro propio interprete y las librerías que nosotros queramos.</p>
<p>¿Qué significa esto? Pues que para nuestro caso de antes, podemos tener un <strong>virtualenv</strong> con esa versión beta de <strong>Django</strong> y hacer que nuestra nueva aplicación use dicho <strong>virtualenv</strong> y que las otras pues sigan como estaban.</p>
<p>Así que <strong>virtualenv</strong> nos sirve para tener entornos separados de <strong>Python</strong> con su conjunto de librerías, y así poder usar nuestras aplicaciones <strong>Django</strong> con el <strong>virtualenv</strong> que queramos, sin riesgo de fastidiar a ninguna otra aplicación aunque usemos librerías de dudosa estabilidad <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>¿Estamos ya emocionados? Pues vamos a instalarlo:</p>
<pre class="brush: plain;">
pip install virtualenv
</pre>
<p>Vemos qué bien nos viene <strong>pip</strong> <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Bueno, esto nos instalará <strong>virtualenv</strong> como ya hemos deducido y además vendrá con <strong>pip</strong> instalado también.</p>
<p>Bueno, ¿Cómo lo usamos?</p>
<p>En linux es tan facil como hacer:</p>
<pre class="brush: plain;">
$ virtualenv --no-site-packages --distribute prueba
$ cd prueba
$ source bin/activate
</pre>
<p>Y en windows:</p>
<pre class="brush: plain;">
virtualenv --no-site-packages --distribute prueba
cd prueba
cmd.exe /K Scripts\activate.bat
</pre>
<p>En windows es algo más lioso, pero lo solucionaremos como veremos más adelante.</p>
<p>Con esto creamos un entorno virtual con el nombre <i>prueba</i>, y luego lo activamos.</p>
<blockquote><p>
<strong>&#8211;no-site-packages</strong> sirve para que al crear el nuevo entorno virtual, no se le de acceso a dicho entorno virtual a los paquetes instalados en nuestra instalación <i>normal</i>, o sea, si ya teniamos <strong>Django</strong> instalados en nuestro <i>Python</i>, no tendremos acceso a el en el <strong>virtualenv</strong>. Tendríamos que instarlo de nuevo (es la idea).</p>
<p><strong>&#8211;distribute</strong> es para usar <i>Distribute</i> en vez de <i>Setuptools</i>
</p></blockquote>
<p>Con esto, esa terminal trabajará usando ese <strong>virtualenv</strong> así que todo lo que hagamos en ella será usando dicho <strong>virtualenv</strong>. Por ejemplo podemos hacer:</p>
<pre class="brush: plain;">
(prueba) $ pip install django
</pre>
<p>Y esto nos instalará <strong>Django</strong> en dicho <strong>virtualenv</strong>.</p>
<p>Si queremos ejecutar nuestra aplicación <strong>Django</strong> haremos:</p>
<pre class="brush: plain;">
(prueba) $ python manage.py runserver
</pre>
<p>Así nuestro servidor usará nuestro <strong>virtualenv</strong> <i>prueba</i> para funcionar.</p>
<p>Lo BUENO de <strong>virtualenv</strong> es que nuestros proyectos y los entornos virtuales NO están vinculados entre ellos, lo que quiere decir que podemos correr nuestra aplicación en una variedad de <strong>virtualenv</strong> sin tener que modificar nada en nuestra aplicación. Así podremos probar distintas versiones de librerías para ver como nos funcionan y si alguna combinación nos da problemas, simplemente tendremos que borrar el <strong>virtualenv</strong> y nadie ha visto nada <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<h1>Usando virtualenv en Cherokee</h1>
<p>Bueno, queremos usar también <strong>virtualenv</strong> en <strong>Cherokee</strong>, ¿no?</p>
<p>Hay múltiples maneras de hacerlo, pero la más sencilla es editando el fichero <i>uwsgi.xml</i> que tenemos junto a nuestra aplicación, así que por ejemplo, para nuestra aplicación <i>tutocherokee</i> e imaginando que tenemos el <strong>virtualenv</strong> en <i>/home/web/virtualenvs/prueba/</i> el fichero quedaría así:</p>
<pre class="brush: xml; highlight: [4];">
&lt;uwsgi&gt;
    &lt;pythonpath&gt;/srv/http/tutocherokee/&lt;/pythonpath&gt;
    &lt;pythonpath&gt;/srv/http/&lt;/pythonpath&gt;
	&lt;home&gt;/home/web/virtualenvs/prueba/&lt;/home&gt;
    &lt;app mountpoint=&quot;/&quot;&gt;
        &lt;script&gt;django_wsgi&lt;/script&gt;
    &lt;/app&gt;
&lt;/uwsgi&gt;
</pre>
<p>La única diferencia ahora es que especificamos la ruta de nuestro <strong>virtualenv</strong>.</p>
<p>Obviamente tienes que tener un <strong>virtualenv</strong> instalado y configurado de antemano.</p>
<p>Ya está, nuestra aplicación <i>tutocherokee</i> usará nuestro <strong>virtualenv</strong> creado para la ocasión.</p>
<h1>Helpers de virtualenv para Windows y Linux</h1>
<p>Podemos hacer que nuestra vida con <strong>virtualenv</strong> sea más sencilla de lo que ya es.</p>
<p>Empezaremos con windows:</p>
<p>Bajamos <a href="http://pyblog.foxandxss.net/cosasblog/virtualenv/env.py" title="env.py" target="_blank">env.py</a> y lo metemos en el directorio <i>script</i> de nuestra instalación python (por ejemplo: C:\Python27\Scripts).</p>
<p>Si ya habéis estado usando <strong>Django</strong> bajo Windows sabréis que dicha ruta tiene que estar en el <i>PATH</i> de Windows para funcionar.</p>
<p>Vale, <i>env.py</i> es un script que nos ayudará a manejar <strong>virtualenv</strong> en Windows.</p>
<p>Para empezar lo editamos y colocamos la ruta donde queremos instalar nuestros <strong>virtualenv</strong>:</p>
<pre class="brush: python;">
DEFAULT_DIR_PATH = &quot;C:\\Django\\virtualenvs\\&quot;
</pre>
<p>Una vez hecho, simplemente tenemos que usarlo:</p>
<pre class="brush: plain;">
env.py -c prueba
env.py prueba
env.py -l
env.py -r prueba
</pre>
<p>El primero crea un entorno virtual llamado <i>prueba</i> y lo activa, el segundo activa el entorno (que ya debe estar creado), el tercero lista todos los que tenemos y el último borra un entorno.</p>
<p>No necesitamos estar en ningún directorio concreto para usar el script ya que el directorio de trabajo de este, está definido en el script.</p>
<p>Ahora bien, y por cortesía de <a href="http://juanriaza.com">Juan Riaza</a> (quien me enseñó a usarlo) tenemos <i>virtualenvwrapper</i>, un helper para Linux.</p>
<p>Primero lo instalamos como ya sabemos hacer:</p>
<pre class="brush: plain;">
$ sudo pip install virtualenvwrapper
</pre>
<p>Creamos un directorio para nuestros entornos, por ejemplo:</p>
<pre class="brush: plain;">
$ mkdir ~/.virtualenvs
</pre>
<p>Configuramos el fichero <i>.bashrc</i>:</p>
<pre class="brush: plain;">
$ vim ~/.bashrc
</pre>
<p>Y añadimos:</p>
<pre class="brush: plain;">
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
</pre>
<p>Tenemos que ver si <strong>pip</strong> copió <i>virtualenvwrapper.sh</i> en esa ruta, pues en archlinux está en <i>/usr/bin/virtualenvwrapper.sh</i></p>
<p>Otra cosa a tener en cuenta, es que si usarmos Archlinux, y Python 2, nuestro ejecutable será <i>python2</i> y no <i>python</i> así que tenemos que:</p>
<p>Abrir <i>virtualenvwrapper.sh</i>:</p>
<pre class="brush: plain;">
$ sudo vim /usr/bin/virtualenvwrapper.sh
</pre>
<p>y buscamos estas líneas y las editamos así:</p>
<pre class="brush: plain; highlight: [4];">
# Locate the global Python where virtualenvwrapper is installed.
if [ &quot;$VIRTUALENVWRAPPER_PYTHON&quot; = &quot;&quot; ]
then
    VIRTUALENVWRAPPER_PYTHON=&quot;$(\which python2)&quot;
fi
</pre>
<p>Vale, ya tenemos <i>virtualenvwrapper</i> configurado, así que o bien reabrimos el terminal o hacemos:</p>
<pre class="brush: plain;">
$ source ~/.bashrc
</pre>
<p>El uso de <i>virtualenvwrapper</i> es muy sencillo:</p>
<pre class="brush: plain;">
$ mkvirtualenv prueba
$ workon prueba
$ deactivate
$ rmvirtualenv prueba
</pre>
<p>El primero crea el entorno virtual, el segundo lo activa, el tercero lo desactiva y el último lo borra.</p>
<p>Con esto terminamos ya el tema.</p>
<p>Hasta otra <img src='http://pyblog.foxandxss.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://pyblog.foxandxss.net/entendiendo-virtualenv-y-pip/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Desplegando nuestra primera aplicación Django en Cherokee</title>
		<link>http://pyblog.foxandxss.net/desplegando-django-en-cherokee</link>
		<comments>http://pyblog.foxandxss.net/desplegando-django-en-cherokee#comments</comments>
		<pubDate>Tue, 01 Nov 2011 14:43:07 +0000</pubDate>
		<dc:creator>Fox</dc:creator>
				<category><![CDATA[Articulos]]></category>
		<category><![CDATA[Cherokee]]></category>
		<category><![CDATA[Despliegue]]></category>
		<category><![CDATA[Django]]></category>

		<guid isPermaLink="false">http://pyblog.foxandxss.net/?p=17</guid>
		<description><![CDATA[Para empezar con este blog, vamos a explicar como desplegar nuestra primera aplicación Django en Cherokee con uWSGI. Vamos a partir desde cero, así que vamos a empezar instalando las distintas cosas. Instalación de Cherokee y uWSGI Voy a especificar &#8230; <a href="http://pyblog.foxandxss.net/desplegando-django-en-cherokee">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Para empezar con este blog, vamos a explicar como desplegar nuestra primera aplicación <strong>Django</strong> en <strong>Cherokee</strong> con <strong>uWSGI</strong>.</p>
<p>Vamos a partir desde cero, así que vamos a empezar instalando las distintas cosas.<br />
<span id="more-17"></span></p>
<h1>Instalación de Cherokee y uWSGI</h1>
<p>Voy a especificar los pasos para instalar <strong>Cherokee</strong> y </strong>uWSGI</strong> en <strong>ArchLinux</strong> que es la distro que yo uso. Aún así no debería ser muy diferente en Ubuntu por ejemplo.</p>
<pre class="brush: plain;">
$ sudo pacman -S cherokee
</pre>
<p>Con esto tendremos <strong>Cherokee</strong>.</p>
<p>Para <strong>uWSGI</strong> tendremos que tirar de AUR, pero no lo hace mucho más complicado:</p>
<pre class="brush: plain;">
$ wget https://aur.archlinux.org/packages/uw/uwsgi/uwsgi.tar.gz
$ tar zxvf uwsgi.tar.gz
$ cd uwsgi
$ makepkg
$ sudo pacman -U uwsgi-0.9.9.2-1-i686.pkg.tar.xz
</pre>
<p>Si os pide alguna dependencia en el <i>makepkg</i> pues se la instalais y santas pascuas. Y como ya habréis imaginado, la versión del paquete puede cambiar cuando leáis esto.</p>
<p>Con esto ya tendríamos lo necesario para empezar.</p>
<h1>Configuración de directorios y permisos</h1>
<p>Esta es la parte más controvertida del artículo pues cada uno lo hace a su forma y bueno, esta es la mía, puede no ser perfecta ni 100% segura (que no lo sé, la verdad) pero es un buen punto de partida.</p>
<p>Cherokee por defecto funciona usando el user <i>http</i> y el grupo <i>http</i>. Esto significa que los directorios donde tengamos nuestras aplicaciones van a tener que estar bajo este usuario y grupo, o por lo contrario Cherokee no podrá ejecutar dichas aplicaciones y mucho menos, escribir en esos directorios.</p>
<p>Por lo personal, considero que es una buena idea crear un nuevo grupo donde agregaremos a <i>http</i> y en un futuro, a otros usuarios que podamos considerar necesarios para la web (como <i>ftp</i> para subir las cosas aquí).</p>
<p>Vamos a ello:</p>
<pre class="brush: plain;">
$ sudo groupadd webgroup
$ sudo usermod -a -G webgroup http
</pre>
<p>Vale, tenemos nuestro grupo y nuestro usuario. Ahora vamos con los permisos.</p>
<pre class="brush: plain;">
$ sudo chown -R http:webgroup /srv/http
$ sudo chmod -R 775 /srv/http
</pre>
<p>Guay, ya tenemos los permisos puestos para nuestro directorio donde alojaremos nuestras webs.</p>
<blockquote><p>
NOTA: En muchas otras distros, este directorio se llama <i>/var/www/</i>
</p></blockquote>
<p>Bien, lo último que nos queda es decirle a Cherokee que use es grupo.</p>
<pre class="brush: plain;">
$ sudo cherokee-admin -b -u
</pre>
<p>Con esto ejecutaremos el administrador de cherokee.</p>
<p>Con <i>-b</i> hará que el admin pueda ser usado desde fuera de esa red (por si tenemos el servidor en un VPS y queremos acceder al admin desde nuestro pc)<br />
Con <i>-u</i> hará que no nos pida contraseña al entrar (cuidado, pues todo el mundo podría entrar en nuestra config en ese momento)</p>
<p>Bueno, ahora accedemos al admin usando o bien <i>localhost:9090</i> si lo tenemos en local o <i>ip/dominio:9090</i> si es remoto.</p>
<p>Una vez en el admin, nos vamos a <i>General -> Permisos</i> y configuramos el nuevo usuario y grupo:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/1.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/1.png" class="alignnone" width="549" height="258" /></a></p>
<p>Vale. Le damos a guardar y ya está.</p>
<h1>Nuestra aplicación Django</h1>
<p>Bueno, vamos a crear un bonito <i>Hello World</i> en Django pues realmente no necesitamos más para este tutorial.</p>
<pre class="brush: plain;">
$ django-admin.py startproject tutocherokee
$ cd tutocherokee
$ python manage.py startapp helloworld
$ mkdir static &amp;&amp; mkdir -p templates/helloworld
</pre>
<p>Vale, ya tenemos nuestro proyecto con su aplicación y el directorio para ficheros estáticos y para los templates.</p>
<p>Vamos a empezar configurando el fichero <i>settings.py</i>:</p>
<pre class="brush: python;">
CURRENT_PATH = os.path.abspath(os.path.dirname(__file__).decode('utf-8')).replace('\\', '/')
</pre>
<p>No os olvideis de hacer un</p>
<pre class="brush: python;">
import os
</pre>
<p>al principio del fichero.</p>
<p>Como los directorios pueden (y van) a cambiar de nuestra maquina al servidor, pues con esta linea obtendremos la ruta actual correcta estemos donde estemos.</p>
<p>Ahora le diremos donde tenemos nuestro directorio de fichero estáticos:</p>
<pre class="brush: python; highlight: [5];">
STATICFILES_DIRS = (
    # Put strings here, like &quot;/home/html/static&quot; or &quot;C:/www/django/static&quot;.
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
    os.path.join(CURRENT_PATH, 'static'),
)
</pre>
<p>También el de templates:</p>
<pre class="brush: python; highlight: [5];">
TEMPLATE_DIRS = (
    # Put strings here, like &quot;/home/html/django_templates&quot; or &quot;C:/www/django/templates&quot;.
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
    os.path.join(CURRENT_PATH, 'templates'),
)
</pre>
<p>Ambos usan el método <i>join</i> para crear una ruta absoluta de nuestro proyecto y esos directorios.</p>
<blockquote><p>
NOTA: No olvidéis la coma al final, es importante.
</p></blockquote>
<p>Por último en el fichero <i>settings.py</i>, vamos a añadir nuestra aplicación:</p>
<pre class="brush: python; highlight: [8];">
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'tutocherokee.helloworld',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
)
</pre>
<p>De nuevo, la comita al final.</p>
<p>Vale, vamos a empezar a con nuestra aplicación:</p>
<p>Abrimos el <i>views.py</i> de nuestra aplicación <i>helloworld</i> y añadimos el siguiente código:</p>
<pre class="brush: python;">
from django.shortcuts import render_to_response
from django.template.context import RequestContext

def home(request):
    nombre = &quot;PyBlog&quot;
    return render_to_response(&quot;helloworld/index.html&quot;, locals(), context_instance=RequestContext(request))
</pre>
<p>Estamos creando una nueva función llamada <i>home</i> la cual abrirá un .html (que todavía no hemos creado) pasándole el nombre de este blog.</p>
<p>Vamos a crear el <i>index.html</i> dentro del directorio <i>templates/helloworld</i>:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE HTML&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=utf-8 /&gt;
    &lt;title&gt;Hola Mundo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    Hola, {{ nombre }}
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Y ahora vamos a configurar el fichero <i>urls.py</i> del proyecto añadiendo una nueva url dentro de <i>urlpatterns</i>:</p>
<pre class="brush: python;">
urlpatterns = patterns('',
    url(r'^$', 'helloworld.views.home'),
)
</pre>
<p>Lanzamos el servidor:</p>
<pre class="brush: plain;">
$ python manage.py runserver
</pre>
<p>Abrimos la url en nuestro navegador&#8230;</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/2.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/2.png" class="alignnone" width="468" height="179" /></a></p>
<p>Anda, perfecto.</p>
<p>Ahora vamos a añadirle un <i>css</i></p>
<p>Creamos un fichero llamado <i>styles.css</i> en el directorio <i>static</i></p>
<pre class="brush: css;">
body {
    background-color: lightblue;
}
</pre>
<p>Y ahora añadimos el <i>css</i> a nuestro <i>index.html</i>:</p>
<pre class="brush: xml; highlight: [3];">
&lt;head&gt;
    &lt;meta charset=utf-8 /&gt;
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;{{ STATIC_URL }}styles.css&quot; /&gt;
    &lt;title&gt;Hola Mundo&lt;/title&gt;
&lt;/head&gt;
</pre>
<p>relanzamos el servidor y&#8230;:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/3.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/3.png" class="alignnone" width="423" height="180" /></a></p>
<p>Vale, ya tenemos nuestra aplicación lista.</p>
<h1>Desplegar nuestra aplicación Django a Cherokee</h1>
<p>Antes de subir nuestra aplicación al servidor, tenemos que hacer algunos cambios al <i>settings.py</i> aunque en este caso, por ser una aplicación tan básica sólo tendremos que cambiar:</p>
<pre class="brush: python;">
DEBUG = True
</pre>
<p>por:</p>
<pre class="brush: python;">
DEBUG = False
</pre>
<p>Hecho. Ahora tenemos que crear un par de ficheros para que <i>uWSGI</i> funcione con nuestra aplicación.</p>
<p>Vamos a crear un fichero en el directorio <i>tutocherokee</i> llamado <i>django_wsgi.py</i> con este código:</p>
<pre class="brush: python;">
import os
import django.core.handlers.wsgi

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
application = django.core.handlers.wsgi.WSGIHandler()
</pre>
<p>Luego vamos a crear otro en el mismo directorio llamado <i>uwsgi.xml</i> con esto:</p>
<pre class="brush: xml;">
&lt;uwsgi&gt;
    &lt;pythonpath&gt;/srv/http/tutocherokee/&lt;/pythonpath&gt;
    &lt;pythonpath&gt;/srv/http/&lt;/pythonpath&gt;
    &lt;app mountpoint=&quot;/&quot;&gt;
        &lt;script&gt;django_wsgi&lt;/script&gt;
    &lt;/app&gt;
&lt;/uwsgi&gt;
</pre>
<p>Necesitamos estos dos ficheros en cada aplicación que vayamos a desplegar a cherokee.</p>
<p>El primero contendrá siempre lo mismo y no necesitaréis tocarlo nunca.</p>
<p>El segundo, contiene 2 rutas. La primera es la ruta absoluta de nuestro proyecto y la segunda la ruta absoluta donde se encuentra dicho proyecto.</p>
<p>El resto no hay que tocarlo, siempre y cuando tengamos estos dos ficheros en el directorio principal del proyecto.</p>
<p>Vale, ahora tenemos que mover el directorio tutocherokee a nuestro directorio del servidor (/var/www o /srv/http si estais en Arch).</p>
<p>Vale, ya tenemos (en mi caso):</p>
<pre class="brush: plain;">
/srv/http/tutocherokee
</pre>
<p>Vamos a darle permisos:</p>
<pre class="brush: powershell;">
$ sudo chown -R http:webgroup /srv/http/tutocherokee
$ sudo chmod -R 775 /srv/http/tutocherokee
</pre>
<p>Ya tenemos todo listo. Ahora solo nos queda crear un <i>servidor virtual</i> en <strong>Cherokee</strong>.</p>
<p>Vamos al admin de Cherokee como ya sabemos hacer y le damos arriba a <i>vServers</i>:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/4.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/4.png" class="alignnone" width="574" height="76" /></a></p>
<p>Y luego añadimos un nuevo <i>Servidor Vitual</i></p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/5.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/5.png" class="alignnone" width="242" height="78" /></a></p>
<p>En la ventana que nos saldrá elegimos <i>Plataformas -> uWSGI</i>:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/6.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/6.png" class="alignnone" width="735" height="504" /></a></p>
<p>Y nos va a pedir el fichero de configuración de <i>uWSGI</i> AKA el fichero <i>uwsgi.xml</i>:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/7.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/7.png" class="alignnone" width="560" height="287" /></a></p>
<p>Y por último nos va a pedir el nombre del servidor, el cual le damos lo que queramos, la ruta donde tenemos la aplicación y si queremos configurar logs:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/8.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/8.png" class="alignnone" width="559" height="403" /></a></p>
<p>Vale, ya tenemos nuestro servidor virtual:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/9.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/9.png" class="alignnone" width="241" height="118" /></a></p>
<p>Antes de poder verlo en acción tenemos que dar un último paso.</p>
<p>¿Cómo sabe Cherokee que tu quieres acceder a esa aplicación?</p>
<p>Se lo tenemos que decir, ¿Cómo? Dentro de nuestro nuevo servidor virtual nos vamos a <i>Evaluación del host</i> y lo configuramos de la siguiente manera:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/10.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/10.png" class="alignnone" width="459" height="535" /></a></p>
<p>Aquí lo que hacemos es decirle que para acceder a nuestra aplicación lo haga a través de <i>tutocherokee.foxexperiments.com</i>.</p>
<p>Ya solo tenemos que hacer click en <i>Guardar -> Reinicio suave</i> arriba a la derecha.</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/11.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/11.png" class="alignnone" width="581" height="54" /></a></p>
<p>Ejecutamos nuestra aplicación y&#8230;</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/12.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/12.png" class="alignnone" width="397" height="123" /></a></p>
<p>¿Funciona? Sí, hemos entrado en nuestra aplicación pero&#8230; ¿Y mi fondito azul?</p>
<p>Para desplegar una aplicación <strong>Django</strong> necesitamos hacer 2 cosas:</p>
<p>a) Usar un servidor para desplegar nuestra aplicación. En nuestro caso estamos usando <strong>uWSGI</strong><br />
b) Usar otro servidor para desplegar nuestro contenido estático. Por ejemplo <strong>Cherokee</strong>.</p>
<p>Vale, lo primero está hecho, pero no le hemos dicho a Cherokee que haga nada con dicho contenido estático.</p>
<p>Lo solucionamos rápido.</p>
<p>Nos vamos a nuestro servidor virtual y a la pestaña <i>Comportamiento</i> y hacemos click en <i>Gestión de reglas</i></p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/13.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/13.png" class="alignnone" width="381" height="329" /></a></p>
<p>Y creamos un nuevo <i>comportamiento</i>:<br />
<a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/14.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/14.png" class="alignnone" width="242" height="182" /></a></p>
<p>Lo configuramos de la siguiente forma:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/15.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/15.png" class="alignnone" width="728" height="498" /></a></p>
<p>En <i>Directorio Web</i> aparce <i>/</i> por defecto, el cual señala el directorio principal de nuestro proyecto. Como directorio <i>static</i> está en dicho directorio principal, solo tendremos que poner su ruta relativa a dicho directorio, o sea, <i>/static</i>.</p>
<p>Lo añadimos, vamos a la pestaña <i>Gestor</i> de dicho <i>comportamiento</i> y lo dejamos así:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/16.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/16.png" class="alignnone" width="546" height="280" /></a></p>
<p>Solo es cambiar el <i>Gestor</i> por <i>Listar y enviar</i>.</p>
<p>Ahora guardamos como siempre y probamos nuestra aplicación:</p>
<p><a href="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/17.png"><img alt="" src="http://pyblog.foxandxss.net/cosasblog/cherokeedeploy/17.png" class="alignnone" width="406" height="108" /></a></p>
<p>Voilà, se hizo la magia.</p>
<p>De hecho podéis comprobarlo en:</p>
<p><a href="http://tutocherokee.foxexperiments.com">tutocherokee.foxexperiments.com</a>.</p>
<p>Y nada más, solo mis agradecimientos a mi amigo <a href="http://soft10.es">Pol Cámara</a> que tuvo la paciencia de enseñarme a mi esto que os enseño hoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://pyblog.foxandxss.net/desplegando-django-en-cherokee/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>¡Hola Mundo!</title>
		<link>http://pyblog.foxandxss.net/bienvenida</link>
		<comments>http://pyblog.foxandxss.net/bienvenida#comments</comments>
		<pubDate>Tue, 01 Nov 2011 14:01:39 +0000</pubDate>
		<dc:creator>Fox</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://pyblog.foxandxss.net/?p=15</guid>
		<description><![CDATA[¡Hola a todos! Bienvenidos a mi blog de Django. Yo soy Jesús y soy programador tanto de .NET como de Django. Acabo de empezar el aprendizaje de Django y tengo como costumbre enseñar todo lo que voy aprendiendo por el &#8230; <a href="http://pyblog.foxandxss.net/bienvenida">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>¡Hola a todos!</p>
<p>Bienvenidos a mi blog de <b>Django</b>.</p>
<p>Yo soy Jesús y soy programador tanto de <b>.NET</b> como de <b>Django</b>.</p>
<p>Acabo de empezar el aprendizaje de <b>Django</b> y tengo como costumbre enseñar todo lo que voy aprendiendo por el camino.</p>
<p>Así que lo que podéis esperar de este blog son artículos relacionados con <b>Django</b> y todo lo que se mueve alrededor de éste. Así que también veréis artículos sobre HTML, CSS, Javascript / jQuery, Python, reseñas de libros, etc.</p>
<p>Obviamente al estar empezando en <b>Django</b> hará que mis artículos puedan no ser lo más correctos que podáis encontrar, pero haré que sean lo mejor posible.</p>
<p>Mis artículos suelen ser bastante largos, pero eso hace que sean lo más detallados posibles, lo cual es bueno para aquel que está aprendiendo.</p>
<p>Y nada más, conforme vaya aprendiendo cosas interesantes las iré explayando aquí.</p>
<p>Un saludo.</p>
]]></content:encoded>
			<wfw:commentRss>http://pyblog.foxandxss.net/bienvenida/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
