<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2spanishfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">

<channel>
	<title>Maestros del Web</title>
	
	<link>http://www.maestrosdelweb.com</link>
	<description>Un espacio para los entusiastas del web</description>
	<lastBuildDate>Thu, 31 May 2012 22:09:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/mwactual" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="mwactual" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Conociendo a fondo el repositorio de Mejorando.la creado con Python y Django</title>
		<link>http://www.maestrosdelweb.com/editorial/repositorio-python-django-mejorandola/</link>
		<comments>http://www.maestrosdelweb.com/editorial/repositorio-python-django-mejorandola/#comments</comments>
		<pubDate>Thu, 31 May 2012 21:00:41 +0000</pubDate>
		<dc:creator>Gissela Peralta</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[adan sánchez]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[herramientas]]></category>
		<category><![CDATA[mejorandola]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24977</guid>
		<description><![CDATA[En un artículo anterior te comentamos Cómo se utiliza Python y Django en Mejorando.la, hoy junto a Adán Sanchez seguimos comentando algunas funciones y herramientas que se pueden ver en el repositorio Github público del proyecto. La parte fundamental de Django: El patron MTV En el articulo anterior Adán ya nos había comentado sobre lo [...]]]></description>
			<content:encoded><![CDATA[<p>En un artículo anterior te comentamos <a href="http://www.maestrosdelweb.com/editorial/python-django-mejorandola/">Cómo se utiliza Python y Django en Mejorando.la</a>, hoy junto a <a href="http://twitter.com/dual3nigma">Adán Sanchez</a> seguimos comentando algunas funciones y herramientas que se pueden ver en el <a href="https://github.com/Mejorandola/Mejorando.la">repositorio Github público del proyecto</a>.</p>
<h3>La parte fundamental de Django: El patron MTV</h3>
<p>En el articulo anterior Adán ya nos había comentado sobre lo indispensable que es el “ceñirse fielmente” al patrón MTV (o MVC) al utilizar Django. Ahora hablemos de los templates, parte importante de este patrón.</p>
<p><strong>Templates</strong></p>
<p>Nos dice Adán que una de las partes más fuertes de Django es su <a href="http://www.maestrosdelweb.com/editorial/curso-django-las-plantillas/">motor de plantillas</a>, el mismo permite abstraer completamente la presentación de las demás partes de la aplicación, esto gracias a etiquetas y filtros:</p>
<p><strong>Filtros</strong><br />
“En las plantillas de Django hacemos uso de la rica cantidad de filtros que pone a nuestra disposición. Desde convertir a mayúsculas, eliminar etiquetas html y agregar saltos de línea.” comentó Adán y agregó que gracias a estos filtros es más fácil tener una clara separación entre datos, lógica y presentación.</p>
<p>Para dar formato a una fecha:</p>
<p>Ejemplo de filtros en plantillas</p>
<pre>&lt;p class=”fecha”&gt;{{ video.fecha|date:"F • j"}}&lt;/p&gt;</pre>
<h3>Algunas baterías incluidas o Módulos Django</h3>
<p>Ya habíamos mencionado que Django es el framework con baterías incluidas, aqui te comentamos algunas de ellas:</p>
<p><strong>Localización</strong><br />
Nos comenta Adán sobre <a href="http://www.maxmind.com/app/ip-location">GeoIP</a>, una librería de localización basada en C: “La integración que trae Django con esta librería da mucho poder a la hora de crear sitios internacionales.” Agrega que “esta librería básicamente es una base de datos gigantesca, optimizada para ser de rápido acceso, con los rangos de direcciones IP por regiones, países, etc.”</p>
<p><strong>Feed</strong><br />
A su vez el módulo de sindicalización se ciñe perfectamente a los patrones propuestos por Django, permite tener todos los métodos y propiedades de los modelos, así como usar plantillas y filtros para la presentación.</p>
<p><strong>Formularios</strong><br />
Django viene con una forma fácil de crear formularios a partir de modelos, con validación automática y completamente personalizable desde la plantilla, Adán nos explica como:</p>
<p>Clase para formulario automático</p>
<p>Un formulario es tan sencillo como:</p>
<pre>class VideoComentarioForm(ModelForm):
class Meta:
model  = VideoComentario
fields = ('autor', 'autor_email', 'autor_url', 'content')</pre>
<p>Plantilla para personalizar formulario</p>
<pre>&lt;form&gt;
&lt;label for="author"&gt;nombre&lt;/label&gt;{{ form.autor }}
{{ form.autor.errors }}
&lt;label for="email"&gt;email&lt;/label&gt;{{ form.autor_email }}
{{ form.content.errors }}
…
&lt;/form&gt;
[ formulario ]</pre>
<p>y personalizar la plantilla es tan sencillo como:</p>
<pre>[ plantilla formulario ]</pre>
<h3>Lo poco que no tiene Django, se soluciona</h3>
<p>Si es que Django no incluye algunos módulos, es extremadamente sencillo crear módulos adicionales que encapsulen funcionalidad extra.</p>
<p><strong>Imágenes</strong></p>
<p>En <a href="http://mejorando.la">Mejorando.la</a> hay diferentes tipos de imágenes; estas imágenes distintas son generadas recortando y optimizando desde el administrador, cuando se crea el video. Nos cuenta Adán que esta tarea fue muy fácil de realizar gracias a la <a href="http://www.pythonware.com/products/pil/">librería PIL</a>.</p>
<p>“Esta librería está en C por lo que es muy veloz, en Python te vas a encontrar muchos módulos en C, sobre todo aquellos que requieren más procesamiento.” agrega Adán.</p>
<p>Ejemplo de uso del módulo PIL</p>
<pre>import Image
image = Image.open(path)
image = image.resize((newWidth, newHeight), Image.ANTIALIAS)
image.save(path)[ ejemplo ]
</pre>
<h3>Consejos para mejorar la web con django y python</h3>
<p>Adán nos dio algunas consideraciones para tener en cuenta al llevar el sitio a producción:</p>
<ul>
<li><strong>Configurar un administrador</strong>, que recibirá alertas cuando algo salga mal.</li>
<li>No olvides crear tus páginas 400 y 500 (<strong>páginas de errores</strong>).</li>
<li>Profundizar en los <strong>múltiples parámetros de configuración</strong> que ofrece Django. Antes de llevar cualquier sitio Django a producción<strong> lee la guia</strong> para que veas todo lo que puede “tweakear”.</li>
<li>Con una línea puedes <strong>activar el uso de memcached</strong> para cachear las páginas de Django. Es muy simple y puede hacer una gran diferencia en el rendimiento de tu aplicación cuando tienes muchas visitas.</li>
<li>Hay muchas <strong>formas de llevar a </strong><strong>producción</strong> <strong>un sitio Django</strong>. Mejorando.la utiliza una combinación de Nginx (para archivos estáticos) y mod_wsgi, que es un módulo de apache, para el código python.</li>
<li>Con respecto al <strong>hosting</strong>, hostgator es una buena opción para iniciar probando Django, sin pagar mucho.</li>
</ul>
<h3>El trabajo en equipo. No todo es programación</h3>
<p>Además de las tecnologías que mencionamos, también se necesitaron herramientas que ayudaron al trabajo en equipo.</p>
<ol>
<li><a href="http://basecamp.com/">BaseCamp</a>, lo más importante es mantenerse comunicado con tu equipo.</li>
<li><a href="https://github.com/dual3nigma/Mejorando.la">Github</a>, es una parte central para asegurar la fluidez del trabajo ya que acelera mucho el proceso de comunicación al llevar un registro de “quién hizo qué”. En Mejorando.la se manejan dos ramas principales, hay dos sitios montados uno en desarrollo y otro que es el produccion.</li>
<li>Feedback, al desarrollar un sitio es importante lo que opinan los usuarios, para ello <a href="http://twitter.com">Twitter</a> ha brindado una enorme cantidad de feedback muy valioso, “nunca ignoren a un usuario que les reporta un bug”.</li>
<li>Diferentes dispositivos, cada uno de los que forman parte del equipo cuentan con dispositivos diferentes, aún así ayuda cualdo alguien manda un error con una captura de pantalla en X dispositivo.</li>
<li><a href="http://newrelic.com/">Newrelic</a>, es una herramienta muy completa para el monitoreo del sitio.</li>
</ol>
<blockquote><p><strong id="internal-source-marker_0.608838414773345"><br />
</strong>Es importante que estés consciente de que con Django las posibilidades son muchas, y conforme vayas profundizando en el tema irás aprendiendo trucos.</p></blockquote>
<p>Ya sabes cómo se utiliza python, django y otras tecnologías para desarrollar el sitio de <a href="http://mejorando.la">Mejorando.la</a>. El sitio es Open Source y el <a href="https://github.com/Mejorandola/Mejorando.la">código está disponible en Github</a>.</p>
<p>Y si quieres profundizar más en el tema recuerda que puedes revisar la <a href="http://www.maestrosdelweb.com/guias/#guias-django">guía Django</a> y la <a href="http://www.maestrosdelweb.com/guias/#guia-python">guía Python</a>.</p>
<hr /><p style="height: 64px;"><div class="entry_author_image"><img src="http://www.maestrosdelweb.com/wp-content/authors/gissejo-77.jpg" alt="" style="float:left;padding:0 5px" /></div>
 <strong>Gissela Peralta</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/repositorio-python-django-mejorandola/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/repositorio-python-django-mejorandola/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/repositorio-python-django-mejorandola/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/wp-content/authors/gissejo-77.jpg" />
		<media:content url="http://www.maestrosdelweb.com/wp-content/authors/gissejo-77.jpg" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Sigamos aprendiendo Python</title>
		<link>http://www.maestrosdelweb.com/editorial/sigamos-aprendiendo-python/</link>
		<comments>http://www.maestrosdelweb.com/editorial/sigamos-aprendiendo-python/#comments</comments>
		<pubDate>Thu, 31 May 2012 18:22:33 +0000</pubDate>
		<dc:creator>Eugenia Tobar</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Guía Python]]></category>
		<category><![CDATA[Guías]]></category>
		<category><![CDATA[adan sánchez]]></category>
		<category><![CDATA[alvaro martinez]]></category>
		<category><![CDATA[cadenas]]></category>
		<category><![CDATA[cursos]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[dual3nigma]]></category>
		<category><![CDATA[listas]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tuplas]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=25076</guid>
		<description><![CDATA[La semana pasada dos héroes de Python nos contaron sus experiencias trabajando con el lenguaje y Gissela, con la ayuda de Adán Sánchez nos mostraron cómo se utiliza Python y Django en Mejorando.la dónde profundizamos más en el código. Nuevos capítulos de la guía Python En busca de generar mayor contenido los capítulos de Python [...]]]></description>
			<content:encoded><![CDATA[<p>La semana pasada <a href="http://www.maestrosdelweb.com/editorial/heroes-python-cuentan-experiencias/">dos héroes de Python nos contaron sus experiencias</a> trabajando con el lenguaje y Gissela, con la ayuda de <a href="http://twitter.com/#!/dual3nigma">Adán Sánchez</a> nos mostraron <a href="http://www.maestrosdelweb.com/editorial/python-django-mejorandola/">cómo se utiliza Python y Django en Mejorando.la</a> dónde profundizamos más en el código. </p>
<h3>Nuevos capítulos de la guía Python</h3>
<p>En busca de generar mayor contenido los capítulos de Python aún no se han convertido en eBook como usualmente lo hacemos, <a href="http://blog.elcodiguero.com/varios/18-sobre-el-sitio.html">Alvaro Martínez</a>, trabaja desde hace tres años con Python, es desarrollador y <a href="http://www.forosdelweb.com/f130/">moderador del foro Python</a> en <a href="http://www.forosdelweb.com">Foros del Web</a> ha realizado 4 capítulos para integrar en la guía desarrollando los temas:</p>
<ul>
<li>Cadenas de Texto.</li>
<li>Secuencias (Tuplas, listas y cadenas).</li>
<li>Expresiones regulares en Python.</li>
<li>Trabajando con listas, funciones y archivos.</li>
</ul>
<p>Algunos temas que Alvaro desarrollará han sido tratados en otros capítulos por Eugenia Bahit, sin embargo, el fin es también aclarar algunos aspectos de forma específica. No olvides revisar los capítulos anteriores de la guía Python:</p>
<ul>
<li><a href="http://www.maestrosdelweb.com/editorial/guia-python/">Programación Orientada a objetos en Python</a></li>
<li><a href="http://www.maestrosdelweb.com/editorial/guia-python-primeros-pasos/">Métodos y Propiedades en Python</a></li>
<li><a href="http://www.maestrosdelweb.com/editorial/guia-python-plantilla-html-lista-precios/">Listas, tuplas, diccionarios y estructuras de control</a></li>
<li><a href="http://www.maestrosdelweb.com/editorial/guia-python-templates-archivos-condicionales/">Trabajando con templates, archivos y condicionales</a></li>
<li><a href="http://www.maestrosdelweb.com/editorial/guia-python-excepciones-helpers-refactoring/">Excepciones, helpers y refactoring</a></li>
<li><a href="http://www.maestrosdelweb.com/editorial/guia-python-herencia-relacion-clases/">Herencia, relación entre dos o más clases</a></li>
<li><a href="http://www.maestrosdelweb.com/editorial/guia-python-testeando-codigo-doctest-comentarios/">Testeando código con doctest en los comentarios</a></li>
<li><a href="http://www.maestrosdelweb.com/editorial/guia-python-interfaces-graficas/">Interfaces gráficas con wxPython</a></li>
<li><a href="http://www.maestrosdelweb.com/editorial/guia-python-bases-de-datos-mysql/">Finalizando con Python y MySQL</a></li>
</ul>
<p>El lanzamiento del primer capítulo es el miércoles 6 de junio y a partir de ese día se publicarán semanalmente lo cuatro capítulos. ¿Qué te parecen los temas? ¿Le seguiste la pista a las publicaciones de Eugenia? </p>
<hr /><p style="height: 64px;"><div class="entry_author_image"><img src="http://www.maestrosdelweb.com/wp-content/authors/eutobar-73.jpg" alt="" style="float:left;padding:0 5px" /></div>
 <strong>Eugenia Tobar</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/sigamos-aprendiendo-python/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/sigamos-aprendiendo-python/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/sigamos-aprendiendo-python/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/wp-content/authors/eutobar-73.jpg" />
		<media:content url="http://www.maestrosdelweb.com/wp-content/authors/eutobar-73.jpg" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Curso Django: Las Plantillas</title>
		<link>http://www.maestrosdelweb.com/editorial/curso-django-las-plantillas/</link>
		<comments>http://www.maestrosdelweb.com/editorial/curso-django-las-plantillas/#comments</comments>
		<pubDate>Mon, 28 May 2012 16:37:05 +0000</pubDate>
		<dc:creator>Sergio Infante Montero</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[Editorial]]></category>
		<category><![CDATA[curso django]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[plantillas]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24838</guid>
		<description><![CDATA[Esta semana tocaremos el tema de las plantillas, si antes no has tenido tiempo para seguir el curso, lo importante es que entiendas como funciona Django y por supuesto si no has leído el curso completo, debes hacerlo para que no te pierdas con los ejemplos. El motor de plantillas Django posee un componente conocido [...]]]></description>
			<content:encoded><![CDATA[<p>Esta semana tocaremos el tema de las plantillas, si antes no has tenido tiempo para seguir el curso, lo importante es que entiendas <a href="http://www.maestrosdelweb.com/editorial/curso-django-entendiendo-como-trabaja-django/" title="Entendiendo a Django">como funciona Django</a> y por supuesto si no has leído <a href="http://www.maestrosdelweb.com/guias/#guias-django" title="Curso de Django en Maestros del Web">el curso completo</a>, debes hacerlo para que no te pierdas con los ejemplos.</p>
<h2>El motor de plantillas</h2>
<p>Django posee un componente conocido como &#8220;el motor de plantillas&#8221;, este motor brinda un poderoso mini-lenguaje para definir detalles de la capa de la aplicación, que visualizará el usuario. Esto refuerza la separación de la lógica de programación y la lógica de presentación. </p>
<p>Las plantillas pueden ser desarrolladas y mantenidas por cualquier persona con un poco de conocimiento de HTML y lógica  común. No necesita fundamentos de Python. <a href="https://docs.djangoproject.com/en/1.4/topics/templates/" title="Django Templates">Puedes revisar la documentación con respecto al lenguaje de plantillas.</a></p>
<p><a href="http://www.maestrosdelweb.com/editorial/curso-django-las-vistas/" title="Las vistas en Django">Algunos ejemplos fueron mostrados en el capítulo anterior</a></p>
<h2>Etiquetas y Filtros</h2>
<p>Es necesario para aplicar las plantillas con Django, conocer más sobre su propio mini-lenguaje de plantillas. Para ello tenemos las siguientes chuletas (cheatsheets):</p>
<p><a href="http://www.maestrosdelweb.com/images/2012/05/django-templates.pdf" target='_blank' title="Django Template Cheatsheet"><div id="attachment_25000" class="wp-caption aligncenter" style="width: 327px"><img src="http://www.maestrosdelweb.com/images/2012/05/django-templates-0-317x450.jpg" alt="Django: Etiquetas y Filtros" width="317" height="450" class="size-medium wp-image-25000" /><p class="wp-caption-text">Django: Etiquetas y Filtros</p></div><div id="attachment_25001" class="wp-caption aligncenter" style="width: 327px"><img src="http://www.maestrosdelweb.com/images/2012/05/django-templates-1-317x450.jpg" alt="Django: Formatos de fecha" width="317" height="450" class="size-medium wp-image-25001" /><p class="wp-caption-text">Django: Formatos de fecha</p></div></a></p>
<p>Y como siempre les hago recordar, <a href="https://docs.djangoproject.com/en/1.4/ref/templates/" title="Documentación sobre plantillas">la revisión a la documentación oficial</a> es muy importante. Están divididas en <a href="https://docs.djangoproject.com/en/1.4/ref/templates/builtins/" title="Etiquetas y Filtros Django">etiquetas y filtros predefinidos</a> y el <a href="https://docs.djangoproject.com/en/1.4/ref/templates/api/" title="El lenguaje de plantillas de Django para programadores Python">lenguaje de plantillas de Django para programadores de Python</a>. </p>
<h2>Las plantillas de nuestro proyecto</h2>
<p>En el capítulo anterior, trabajamos con algunas plantillas simples, sin entrar en detalle de su funcionamiento, esta semana modificaremos las plantillas, utilizaremos algunos filtros y etiquetas predeterminadas, obviamente veremos a detalle de que tratan.</p>
<div class='tipexperto'>
<h4>Nota:</h4>
<div class='tipcont'>Las plantillas están almacenadas en la carpeta configurada en el settings.py, si no recuerdas su ubicación, revisa los capítulos anteriores.</div>
</div>
<h3>base.html</h3>
<p>Esta es una nueva plantilla, no habíamos utilizado anteriormente alguna de este tipo, esta plantilla base, hace exactamente lo que su nombre sugiere, sirve de base para las demás.</p>
<div id="attachment_24994" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-template-base.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-template-base-450x346.png" alt="base.html" width="450" height="346" class="size-medium wp-image-24994" /></a><p class="wp-caption-text">base.html</p></div>
<p>En esta plantilla es importante notar, que se encuentra la estructura principal de toda la aplicación. Ademas se usa la etiqueta <strong>{% block _______ %} {% endblock %}</strong> (reemplaza _______ con el nombre del bloque), esta etiqueta se reemplazará con contenido en cada una de las plantillas que restan. Por ahora agregaremos CSS dentro de la etiquetación HTML, no lo hacemos todavia desde un archivo CSS porque esto lo veremos con mayor detalle en el capítulo de archivos estáticos.</p>
<h3>inicio.html</h3>
<p>Esta es la plantilla que estamos usando para la página de inicio, y debe quedar con las siguientes modificaciones:<br />
<div id="attachment_24995" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-template-inicio.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-template-inicio-450x443.png" alt="inicio.html" width="450" height="443" class="size-medium wp-image-24995" /></a><p class="wp-caption-text">inicio.html</p></div></p>
<ul>
<li><strong>{% extends &#8216;base.html&#8217; %}</strong>, esta línea permite importar la plantilla <strong>base.html</strong> y reemplazar cada vez que encuentre los bloques, con los de esta plantilla.</li>
<li><strong>{% comment %}{% endcomment %}</strong> es un ejemplo de como pueden incluirse comentarios en el lenguaje de plantillas de Django, todo lo que se encuentre dentro de estas etiquetas, será ignorado.</li>
<li><strong>{% with %}</strong> permite poner la cantidad de elementos de alguna respuesta y puede ser usado para mostrar palabras en plurales, dependiendo de la circunstancia.</li>
<li><strong>{% for dato in recetas %}</strong> permite acceder a cada receta en particular.</li>
<li><strong>{% cycle &#8216;impar&#8217; &#8216;par&#8217; %}</strong> permite iterar con los valores &#8216;impar&#8217; o &#8216;par&#8217;, que pueden verse afectados con algunas reglas en CSS simples que se encuentran en <strong>{% block style_css %}</strong></li>
<li><strong>{% empty %}</strong> es usado en caso de que no existan elementos en las recetas.</li>
</ul>
<h3>usuarios.html</h3>
<p>La plantilla que muestra los usuarios registrados:<br />
<div id="attachment_24998" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-template-usuarios.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-template-usuarios-450x369.png" alt="usuarios.html" width="450" height="369" class="size-medium wp-image-24998" /></a><p class="wp-caption-text">usuarios.html</p></div></p>
<p>Además de las etiquetas vistas anteriormente, aquí podemos encontrar:</p>
<ul>
<li><strong>{{dato.username|capfirst}}</strong> esto se usa para capitalizar el nombre del usuario (primera letra en mayúscula)</li>
<li>Bloque <strong>{% if %}{% endif %}</strong> para comprobar que receta pertenece al usuario actual del bucle <strong>{% for %}</strong></li>
</ul>
<h3>recetas.html</h3>
<p>Esta plantilla nos muestra la lista de recetas registradas:<br />
<div id="attachment_24997" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-template-recetas.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-template-recetas-450x289.png" alt="recetas.html" width="450" height="289" class="size-medium wp-image-24997" /></a><p class="wp-caption-text">recetas.html</p></div></p>
<ul>
<li><strong>{% url principal.views.detalle_receta dato.id %}</strong> esta etiqueta, trabaja con <em>views.py</em> (ubica una vista y le pasa un parametro), se traduce en <em>/receta/dato.id</em>, donde <em>dato.id</em> es reemplazado por la id de la receta del elemento actual del bucle <strong>{% for %}</strong> </li>
</ul>
<h3>receta.html</h3>
<p>Esta plantilla se usará para mostrar los detalles de cada receta registrada:<br />
<div id="attachment_24996" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-template-receta.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-template-receta-450x274.png" alt="receta.html" width="450" height="274" class="size-medium wp-image-24996" /></a><p class="wp-caption-text">receta.html</p></div></p>
<p>Ademas de todas las etiquetas usadas y ya explicadas anteriormente se puede notar:</p>
<ul>
<li><strong>{{receta.titulo|title}}</strong> transforma los títulos de la receta en formato título (la primera letra de cada palabra en mayúscula.</li>
<li><strong>{{ receta.tiempo_registro|date:&#8217;SHORT_DATETIME_FORMAT&#8217; }}</strong> configura la impresión de fecha como:  dd/mm/aaaa hh:mm (ejemplo: 20/05/2012 21:05), se puede ver mas formatos de fecha a usar en los cheatsheets de arriba.</li>
</ul>
<h3>Practica y practica</h3>
<p>La mejor forma de aprender Django es practicando, así que supongo que lo estas haciendo, durante todos los capítulos, ahora toca que crees tus propias plantillas, para tus propias consultas y vistas, que seguramente ya programaste con ayuda del curso de Django.</p>
<p>No te olvides de <a href="https://docs.djangoproject.com/en/1.4/" title="Documentación Django">revisar la documentación</a> por si buscas más ejemplos y detalles de las diversas etiquetas, es la mejor fuente para aprender más sobre este estupendo framework.</p>
<p>Puedes leer también: <a href="http://www.maestrosdelweb.com/editorial/python-django-mejorandola/" title="Python y Django en Mejorando.la">Cómo se utiliza Python y Django en Mejorando.la</a> y si el ingles no es problema para tí, puedes ver una charla del PyCon 2012 sobre las plantillas en Django:</p>
<span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='640' height='390' src='http://www.youtube.com/embed/ahM4GBZ-6qg?version=3&amp;rel=1&amp;fs=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;wmode=transparent' frameborder='0'></iframe></span>
<p>Eso es todo por esta semana, deja tus comentarios como siempre, que ayudan a mejorar el contenido del curso, y que ayudan de manera importante a todos los que siguen el curso, que tengan un buen inicio de semana con Django <img src='http://www.maestrosdelweb.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<hr /><p style="height: 64px;"><img alt='Sergio Infante Montero' src='http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Sergio Infante Montero</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/curso-django-las-plantillas/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/curso-django-las-plantillas/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/curso-django-las-plantillas/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-templates-0-150x150.jpg" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-templates-0.jpg" medium="image">
			<media:title type="html">Django: Etiquetas y Filtros</media:title>
			<media:description type="html">Django: Etiquetas y Filtros</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-templates-0-150x150.jpg" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-templates-1.jpg" medium="image">
			<media:title type="html">Django: Formatos de fecha</media:title>
			<media:description type="html">Django: Formatos de fecha</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-templates-1-150x150.jpg" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-template-base.png" medium="image">
			<media:title type="html">base.html</media:title>
			<media:description type="html">base.html</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-template-base-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-template-inicio.png" medium="image">
			<media:title type="html">inicio.html</media:title>
			<media:description type="html">inicio.html</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-template-inicio-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-template-usuarios.png" medium="image">
			<media:title type="html">usuarios.html</media:title>
			<media:description type="html">usuarios.html</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-template-usuarios-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-template-recetas.png" medium="image">
			<media:title type="html">recetas.html</media:title>
			<media:description type="html">recetas.html</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-template-recetas-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-template-receta.png" medium="image">
			<media:title type="html">receta.html</media:title>
			<media:description type="html">receta.html</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-template-receta-150x150.png" />
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Sergio Infante Montero</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Es viernes: ¿Cuál es el precio de tu trabajo?</title>
		<link>http://www.maestrosdelweb.com/editorial/cual-es-el-precio-de-tu-trabajo/</link>
		<comments>http://www.maestrosdelweb.com/editorial/cual-es-el-precio-de-tu-trabajo/#comments</comments>
		<pubDate>Fri, 25 May 2012 07:00:08 +0000</pubDate>
		<dc:creator>Stephanie Falla Aroche</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Productividad]]></category>
		<category><![CDATA[Dinero]]></category>
		<category><![CDATA[es viernes!]]></category>
		<category><![CDATA[Freelancer]]></category>
		<category><![CDATA[Negocios]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24918</guid>
		<description><![CDATA[Cuando empecé en este medio el discurso de estudiantes de las carreras de ingeniería, diseño y afines decían que les gustaba pertenecer a las comunidades e iniciativas por entusiasmo. Participar en eventos y ser parte del staff por &#8220;estar en la jugada&#8221; aprender y conocer hacia dónde apuntaba el futuro en este medio. Pero, son [...]]]></description>
			<content:encoded><![CDATA[<p>Cuando empecé en este medio el discurso de estudiantes de las carreras de ingeniería, diseño y afines decían que les gustaba pertenecer a las comunidades e iniciativas por entusiasmo. Participar en eventos y ser parte del staff por &#8220;estar en la jugada&#8221; aprender y conocer hacia dónde apuntaba el futuro en este medio. Pero, son etapas y esta bien apoyar iniciativas, pero también esta bien hacer las cosas para obtener ganancias y encontrar modelos de negocios.</p>
<p><a href="http://www.401kcalculator.org/"><img src="http://www.maestrosdelweb.com/images/2012/05/mooney.png" alt="¿Cuál es el precio de tu trabajo?" /></a></p>
<p>En Latinoamérica existe un problema con el tema del dinero, quizás sea una cuestión cultural, quizás nuestra educación o simples paradigmas que nos asechan. Pero, <strong>nos cuesta hablar de dinero</strong>, negociar, hablar de presupuestos y lo más común nunca sabemos cuánto ganamos realmente, decimos -más o menos-, -aproximadamente- ¿acaso no sabemos el costo de nuestro trabajo? ¿no sabemos negociar? ¿por qué nos andamos por las ramas? <a href="http://www.maestrosdelweb.com/editorial/es-viernes-%C2%BFcuanto-dinero-quieres-ganar-y-en-cuanto-tiempo/">¿sabes cuánto quieres ganar?</a> ¿por qué nos sentimos ofendidos al hablar de dinero?</p>
<h3>¿Cuánto vale una hora de tu tiempo?</h3>
<p>En las iniciativas que tenemos en nuestros proyectos como Maestros del Web, <a href="http://forosdelweb.com">Foros del Web</a>, <a href="http://120segundos.com">120segundos</a>, <a href="http://mejorando.la">Mejorando.la</a> con sus cursos y conferencias siempre tenemos un equipo de personas apoyando como socios y de la comunidad que se ofrecen apoyarnos, como agradecimiento al conocimiento que les hemos aportado a través de nuestros proyectos. Nos alegra la gente entusiasta, pero también nos motiva la gente que quiere hacer negocios, ofrece soluciones a nuestras necesidades y <a href="http://www.maestrosdelweb.com/editorial/como-ponerle-precio-a-nuestro-trabajo-como-freelance/">no temen ponerle un precio</a>.</p>
<p>Si eres freelancer, emprendedor y quieres tener tu propia empresa, debes romper con la dinámica de no tener respuesta cuando alguien te pregunta ¿cuánto ganas al mes? ¿qué cuesta una hora de tu trabajo? ¿cuánto cobras por asesorar? ¿cuánto te pagaron por tu último proyecto? ¿cuánto me cobras por hacerme ABCD tareas? ¿cuánto me costaría o me puedes dar un estimado? ¿en tu sitio están los costos? si no sabes qué contestar, toma un tiempo para hacer los cálculos y define tus costos ¿por qué te da vergüenza o pena decir el valor de tu trabajo?</p>
<h3>Aprendamos a negociar en todas la áreas</h3>
<p><strong>Existe una dinámica que debemos practicar todos los días, con todas las personas, relaciones y objetivos de vida: negociar</strong>. El negociar no es sólo cuestión de dinero, también de intereses, bien común, calidad de vida y justicia. Pero, la negociación no es una cualidad o valor que nos instruyen desde pequeños, porque nos enseñan a obedecer y acatar las reglas de los que sí saben. Eso se traslada al valor que tenemos de nuestro trabajo, los negocios y entonces preferimos que sea una empresa la que ponga el precio.</p>
<p>Que tu trabajo, una hora de tu tiempo y tu asesoría tenga un precio, está ligado con la autoestima que tengas en(de) tu trabajo. Puede que a muchas personas les moleste que no quieras tomarte un café con ellos para contarte de sus proyectos y tener tu opinión. Es posible que al decirles <a href="http://www.maestrosdelweb.com/editorial/es-viernes-no-mas-consejos-y-asesorias-gratuitas/">¿quieres una asesoría?</a> les parezca una ofensa, pero sí tu no te tomas en serio entonces ¿por qué otras personas lo harán? el rol que quieras tomar también es una negociación contigo mismo.</p>
<h3>Siempre debes obtener un beneficio a cambio</h3>
<p>Cuando se trata de trabajo, siempre debemos obtener un beneficio a cambio, ya sea económico, experiencia, reconocimiento, etc. Cuando somos jóvenes es común que &#8220;regalemos nuestro trabajo&#8221; como se suele decir, pero en realidad estamos ganando experiencia, práctica y aprendiendo del medio. Sin embargo, debemos saber cuándo es bueno invertir nuestro tiempo en actividades, iniciativas, comunidades o proyectos porque <strong>no siempre obtenemos resultados que suman</strong>. </p>
<p>Hay quienes al apoyar afirman con orgullo que <strong>-no lo hacen por dinero-</strong> yo creo que no existe nada malo en ganar dinero por nuestro esfuerzo, apoyo y dedicación. Lo único que debemos aprender muy bien es a saber negociar. Cuando alguien sabe negociar, obtiene siempre ganancias de su esfuerzo, quitemos de nuestra mente que es malo hacer las cosas por interés o dinero. Diseñemos modelos y dinámicas que nos permitan ganar y así mismo construir con otras personas para que todos salgan ganando de igual forma. </p>
<p>Espero que sigamos la reflexión en los comentarios, estoy segura que ustedes tendrán mucha experiencia que compartir con relación al tema, sigamos aprendiendo a negociar y ser mejores freelancer en este medio tan competitivo. Feliz fin de semana. Enjoy! </p>
<p>Imagen: <a href="http://www.401kcalculator.org/">401kcalculator</a></p>
<hr /><p style="height: 64px;"><img alt='Stephanie Falla Aroche' src='http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Stephanie Falla Aroche</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/cual-es-el-precio-de-tu-trabajo/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/cual-es-el-precio-de-tu-trabajo/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/cual-es-el-precio-de-tu-trabajo/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/mooney.png" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/mooney.png" medium="image">
			<media:title type="html">¿Cuál es el precio de tu trabajo?</media:title>
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Stephanie Falla Aroche</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Cómo se utiliza Python y Django en Mejorando.la</title>
		<link>http://www.maestrosdelweb.com/editorial/python-django-mejorandola/</link>
		<comments>http://www.maestrosdelweb.com/editorial/python-django-mejorandola/#comments</comments>
		<pubDate>Thu, 24 May 2012 18:27:55 +0000</pubDate>
		<dc:creator>Gissela Peralta</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[herramientas]]></category>
		<category><![CDATA[mejorando la web]]></category>
		<category><![CDATA[mejorando.la]]></category>
		<category><![CDATA[programacion]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24880</guid>
		<description><![CDATA[Seguramente conoces Mejorando.la, es el proyecto web de Maestros y Cristalab. Comenzó como programa online una vez por semana y ahora se ha expandido con cursos presenciales alrededor de latinoamérica y tres conferencias con alcance mundial. Leonidas Esteban, Renzo Avalos y Adan Sanchez son quienes hace unos meses estuvieron trabajando para lograr el sitio que hoy [...]]]></description>
			<content:encoded><![CDATA[<p>Seguramente conoces <a href="http://mejorando.la">Mejorando.la</a>, es el proyecto web de <a href="http://maestrosdelweb.com">Maestros</a> y <a href="http://cristalab.com">Cristalab</a>. Comenzó como <a href="http://mejorando.la/videos">programa online una vez por semana</a> y ahora se ha expandido con <a href="http://mejorando.la/cursos/">cursos presenciales alrededor de latinoamérica</a> y <a href="http://mejorando.la/conferencia/">tres conferencias con alcance mundial</a>.</p>
<p><a href="http://twitter.com/leonidasesteban">Leonidas Esteban</a>, <a href="http://twitter.com/sp3ncer">Renzo Avalos</a> y <a href="http://twitter.com/dual3nigma">Adan Sanchez</a> son quienes hace unos meses estuvieron trabajando para lograr el sitio que hoy se puede disfrutar al ingresar a <a href="http://mejorando.la">Mejorando.la</a>. Para lograrlo hubo todo un proceso de rediseño y reprogramación que fue posible gracias a varias herramientas y servicios que con la ayuda de <a href="http://twitter.com/dual3nigma">Adan Sanchez</a> te contaré a continuación.</p>
<h3>Python y Django: Lenguaje y framework de la magia</h3>
<p>“Al momento de planear el rediseño y reprogramacion de un sitio <strong>es importante identificar bien sus elementos y componentes principales para crear los modelos necesarios y una buena estructura</strong>” es lo primero que resaltó Adán Sanchez. Y hablando especificamente de Mejorando.la hay que destacar que <em>el componente principal son los videos</em>. Desde ahí parten todas las funciones que se van agregando al sitio.</p>
<p><a href="http://www.maestrosdelweb.com/guias/#guia-python">Python</a> es el lenguaje y <a href="http://www.maestrosdelweb.com/editorial/curso-django-introduccion/">Django</a> es el framework detrás del sitio de Mejorando.la. Nos cuenta Adán que gracias a la <em>flexibilidad</em> que ofrece, se pudo realizar la reprogramación y rediseño del sitio <em>en pocos días</em>: &#8220;Digamos que Django se ha vuelto prácticamente un estándar como framework para desarrollo ágil.&#8221;</p>
<blockquote><p>Es especialmente recomendado para un proyecto grande desarrollado por un equipo pequeño o cuando se trata de un sitio para entregar en pocos días.</p></blockquote>
<p>Al consultar por qué la elección de Django y no otro, nos explicó que &#8220;Django era la solución principal, puesto que si bien wordpress es muy flexible, en Django hay aun mas flexibilidad.&#8221;</p>
<h3>Un framework con baterías incluídas</h3>
<p>Django trae lo que en Python se conoce como “<em>baterías incluidas</em>”. Desde <em>clases</em> para tareas sencillas como <em>paginación</em>, <em>geolocalización</em>, <em>autentificación</em> y <em>caché</em> hasta componentes bastante completos como el <em>módulo de comentarios</em>, <em>notificaciones</em>, <em>administrador</em>, <em>internacionalización</em> y <em>feeds</em>.</p>
<p>Adán explica que un sitio en Django es más limpio puesto que python tiene una estructura modular, agrega que “en otros lenguajes hay que descargarse muchos archivos y el tener tantos archivos en el directorio puede hacer mas dificil manejar el sitio”. Para “graficar” la facilidad con la que se activan estos módulos desde el archivo de configuración, nos mostró el código correspondiente:</p>
<pre>INSTALLED_APPS = (
'django.contrib.auth', # funciones de autentificacion
'django.contrib.comments', # funciones para agregar comentarios a los modelos
'django.contrib.admin', # administrador autogenerado
)</pre>
<p>Además afirma que es muy fácil encontrar un módulo en los repositorios para aquellas funcionalidades que no vienen incluidas en Django, un ejemplo de ello es el modulo Gravatar que se utiliza en Mejorando.la para los avatares de los comentarios.</p>
<h3>Modelo-Vista-Controlador</h3>
<p>&#8220;Un punto más a favor de Django es el <em>patrón Modelo-Vista-Controlador</em> que maneja, esto quiere decir que separas tu aplicación en tres componentes&#8221;, explicó Adán. El modelo principal en este caso seria Video, en donde un &#8220;video&#8221; tiene titulo, imagen, descripcion, comentarios.</p>
<p>Para entender mejor puedes ver el<a href="http://www.maestrosdelweb.com/editorial/curso-django-entendiendo-como-trabaja-django/"> tercer capitulo de la guia Django </a>y luego ver estos ejemplos:</p>
<p><strong>Modelo</strong>: <a href="http://www.maestrosdelweb.com/editorial/curso-django-el-modelo-de-datos/">son los datos</a>, en el sitio se tiene un modelo para los Videos.</p>
<p>Ejemplo de modelo</p>
<pre>class Video(models.Model):
titulo = models.CharField()
slug = models.CharField()
imagen = models.ImageField()
fecha = models.DateField()
descripcion = models.TextField()
</pre>
<p><strong></strong></p>
<p><strong>Vista</strong>: sería la presentación de este modelo, en Django entra en los templates, que reciben los datos del controlador. Hay una plantilla para cada vista: home.html, videos.html, video.html, heredando de base.html gracias al poderoso sistema de plantillas de Django.<br />
<strong></strong></p>
<p><strong>Controlador</strong>: se encarga de elegir los datos que se van a mostrar y hacer el procesamiento que haga falta en estos, validacion y condicionamientos. En Mejorando.la hay un controlador para cada página: home, archivo de videos y página de video.</p>
<p>Ejemplo de controlador</p>
<pre>def video(solicitud_http, video_slug):
video = get_object_or_404(Video, slug=video_slug)
return render_to_response('website/video.html', { 'video': video })
</pre>
<p><strong></strong></p>
<h3>Unidad, código limpio y filtros.</h3>
<p>La unidad que existe en toda la plataforma es una de las caracteristicas que más le gustó a Adán: &#8220;cualquier método que defina en un modelo estará presente tanto en el controlador como en las plantillas.&#8221;</p>
<blockquote><p>&#8220;Los modelos de Django permiten abstraer lo que tradicionalmente se haría con SQL en clases y funciones. Esto permite tener un código más limpio.&#8221;</p></blockquote>
<p>Por ejemplo:</p>
<pre>SQL
SELECT titulo, descripcion, imagen FROM videos ORDER BY fecha LIMIT 10</pre>
<p>Django</p>
<pre>Video.objects.all().order_by(‘-fecha’)[:10]</pre>
<p>Nos comentó también que en las plantillas de Django se hace uso de la rica cantidad de filtros que pone a disposición, desde convertir a mayúsculas, eliminar etiquetas html y agregar saltos de línea.</p>
<blockquote><p>Gracias a estos filtros es más fácil tener una clara separación entre datos, lógica y presentación.</p></blockquote>
<h3>Sólo un comienzo</h3>
<p>Cómo te imaginarás el proceso de rediseño y reprogramación de un sitio como Mejorando.la no se puede comentar y explicar en detalle en tan sólo un artículo, sin embargo en una proxima publicación con Adán te contaremos más funcionalidades y caracteristicas que hacen de <a href="http://www.maestrosdelweb.com/editorial/guia-python/">python un lenguaje fácil de aprender</a> y de <a href="http://www.maestrosdelweb.com/editorial/curso-django-introduccion/">Django el framework ideal para perfeccionistas</a>.</p>
<hr /><p style="height: 64px;"><div class="entry_author_image"><img src="http://www.maestrosdelweb.com/wp-content/authors/gissejo-77.jpg" alt="" style="float:left;padding:0 5px" /></div>
 <strong>Gissela Peralta</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/python-django-mejorandola/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/python-django-mejorandola/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/python-django-mejorandola/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/wp-content/authors/gissejo-77.jpg" />
		<media:content url="http://www.maestrosdelweb.com/wp-content/authors/gissejo-77.jpg" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>¿La plataforma para aprender a programar se llama CodeCademy?</title>
		<link>http://www.maestrosdelweb.com/editorial/codecademy-educacion-virtual/</link>
		<comments>http://www.maestrosdelweb.com/editorial/codecademy-educacion-virtual/#comments</comments>
		<pubDate>Thu, 24 May 2012 05:00:03 +0000</pubDate>
		<dc:creator>Christian Van Der Henst S.</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[codecademy]]></category>
		<category><![CDATA[educacion virtual]]></category>
		<category><![CDATA[elearning]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[plataforma]]></category>
		<category><![CDATA[programar]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24945</guid>
		<description><![CDATA[Aprender a programar es más fácil frente a la pantalla. Con una consola que te dice si lo hiciste bien, si lo hiciste mal. Así hice yo mis primeros programas y confieso que la gran mayoría de libros de programación que consumí no me cautivaron. ¿Hay alguna plataforma natural para aprender? Constantemente me preguntan que [...]]]></description>
			<content:encoded><![CDATA[<p>Aprender a programar es más fácil frente a la pantalla.  Con una consola que te dice si lo hiciste bien, si lo hiciste mal.  Así hice yo mis primeros programas y confieso que la gran mayoría de libros de programación que consumí no me cautivaron. ¿Hay alguna plataforma natural para aprender?</p>
<p>Constantemente me preguntan que lenguaje de programación aprender: Por cierto, aprende <a href="http://www.maestrosdelweb.com/editorial/no-aprendas-jquery-aprende-javascript/" title="No aprendas jQuery, aprende javascript">Javascript</a> y eso no lo digo solo yo, <a href="https://github.com/languages" title="Top Languates en Github">lo dicen las estadísticas de Github</a> donde destaca como el lenguaje más usado. Pero aquí hay un problema, ve a buscar buenos tutoriales de javascript a algún buscador y lo que encontrarás es un tsunami de desinformación.</p>
<h3>Marketing para futuros desarrolladores</h3>
<p><a href="http://codecademy.com" title="CodeCademy">CodeCademy</a> (no confundir con <a href="http://www.codeacademy.org/" title="Code Academy"></a>Code Academy que enseña Ruby on Rails en 3 meses físicamente en Chicago) es una incréible propuesta que ha sobresalido en su buen marketing hacia ese nicho necesitado de programadores, de rutas fáciles a un prototipo, porque ahora resulta que todos queremos aprender a programar.  Incluso <a href="https://twitter.com/mikebloomberg/status/154999795159805952" title="">el alcalde de Nueva York</a>.</p>
<p style="text-align:center"><img src="http://www.maestrosdelweb.com/images/2012/05/codecademy.jpg" alt="CodeCademy" title="CodeCademy" width="600" height="188" /></p>
<p>Me encantaría hablar de Codecademy hablando de profesores que tenían un sueño y una vocación y la transformaron en empresa luego de mucha investigación y años de desarrollo.  En el caso de Codecademy, nació en <a href="http://ycombinator.com/" title="YCombinator">YCombinator</a> con emprendedores que a última hora vieron que no es fácil contratar desarrolladores en Silicon Valley y buscaron la forma de entrenarlos y reclutarlos. Además tenían un mercado cautivo.   Y ojo, admiro mucho a la empresa, pero me he prometido ser muy crítico en esta reseña de proyectos para no escribir lo mismo que se puede leer de ellos.</p>
<h3>¿Podemos aprender Javascript en CodeCademy?</h3>
<p>Si, <a href="http://www.codecademy.com/tracks/javascript" title="Javascript fundamentals en Codecademy">es su primer curso</a>.  Y la plataforma es una idea muy bien armada de como combinar la gamificación (se que algunos que leen odiarán los anglicismos totalmente no aprobados por la RAE que a veces uso), una consola interactiva de programar y ejercicios prácticos para empezar desde cero.</p>
<p>También importante destacar que en este mercado hay otro proyecto muy interesante llamado <a href="http://teamtreehouse.com/" title="Three House">Treehouse</a> del que espero hacer un review más adelante en esta serie.</p>
<p>Lo más admirable de Codecademy es su propuesta para democratizar la teoría de programar.  Todos deberían intentarlo.  Y creo que su plataforma puede ser el mejor examen vocacional que cualquier futuro ingeniero o programador debería de tomar.  Me convencieron cuando leí de esta <a href="http://www.thecollegeprepster.com/2012/01/code-academy.html" title="College Prepster">college prepster (algo así como chica fresa) programando</a>.  Y no solo eso, también están en grandes ligas <a href="http://www.whitehouse.gov/blog/2012/01/17/new-summer-jobs-commitments-plan-introduce-low-income-youth-technology-related-skill" title="Summer Jobs +">trabajando con la misma Casa Blanca y el gobierno de Obama</a>.</p>
<p>Aún no veo si van a conseguir a los mejores programadores del futuro o si esta misma plataforma ayudará a aprender conceptos extremadamente complejos de algunos lenguajes de programación.  En ese caso, yo confiaría mucho más en <a href="https://www.hackerschool.com/" title="Hacker School NY">Hacker School</a> y su modelo para encontrar y preparar al mejor talento desarrollador. </p>
<h3>El 2012 y CodeYear</h3>
<p>La primera semana de enero este proyecto lanzó una de mis campañas favoritas en el mundo de startups. <a href="http://www.codeyear.com/" title="Code Year">CodeYear</a> es su propuesta de aprender a programar en un año y se basan en una combinación del curso de Javascript con otro de <a href="http://www.codecademy.com/tracks/web" title="Web Fundamentals">fundamentos de la Web</a>.  Todas las semanas te envían un correo electrónico con una tarea nueva a completar en su plataforma gratuita. </p>
<p>Yo me suscribí, recibo los mails cada semana y jamás seguí ninguna clase luego de mis pruebas iniciales con su plataforma.   Pero esto no tiene ninguna relación con mis pocas habilidades para javascript, he de aclarar.</p>
<p>Algo que si he aprendido con CodeYear es a diseñar una excelente landing page, trabajo de Sacha Greif que <a href="http://sachagreif.com/how-i-designed-codeyear-com-in-1-hour/" title="Como diseñe Code Year en una hora">documentó con detalle</a>.</p>
<h3>Los detractores de CodeCademy</h3>
<p>Algo que mencioné en el artículo sobre <a href="http://www.maestrosdelweb.com/editorial/khan-academy-educacion-virtual/" title="Khan Academy en Maestros del Web">Khan Academy</a> y que valida la importancia de estos modelos son las constantes críticas que tienen.</p>
<p>Importante también seguir los debates que CodeCademy empresa ha generado. Audrey Watters menciona que <a href="http://www.hackeducation.com/2011/10/28/codecademy-and-the-future-of-not-learning-to-code/" title="">se ganó los badges y avanzó niveles, pero no ha aprendido realmente mucho</a>. También cuestiona cuántos de los 500mil usuarios del sistema habían aprendido Javascript.  Esto a finales del 2011.</p>
<p>Unos días atrás, Jeff Atwood criticó su campaña de que todos tenemos que aprender a programar y nos pedía que <a href="http://www.codinghorror.com/blog/2012/05/please-dont-learn-to-code.html" title="Please do't learn to code">no aprendieramos a programar</a>. Recomendada también la respuesta de Sacha Greif que <a href="http://sachagreif.com/please-learn-to-code/" title="Please learn to code">nos insiste a programar a todos</a>. Ella hizo la landing de CodeYear como comenté arriba.  </p>
<p>Yo me quedo con la opinión de que todos debemos tener más cualidades tecnológicas porque vas a poder desarrollar prototipos de tus ideas aunque sea con entender mejor cómo usar un programa para armar presentaciones.  Y Codecademy, con una reciente inversión de 2.5 millones de dólares se gana el honor de haber difundido este mensaje en menos de un año a muchísima gente.  Seguiré pendiente de a donde se destinarán esos fondos.</p>
<p>Finalizo agradeciendo sus mensajes y comentarios sobre esta serie para <a href="http://www.maestrosdelweb.com/editorial/re-definiendo-educacion-virtual/" title="Re-definiendo la Educación Virtual">re-definir la educación virtual</a>.  <a href="http://www.maestrosdelweb.com/editorial/khan-academy-educacion-virtual/" title="Khan Academy en Maestros del Web">Khan Academy</a>, Codecademy y mañana tocará Treehouse, aunque ya la lista de proyectos a revisar se está acumulando y eso me encanta.   Hasta mañana. </p>
<hr /><p style="height: 64px;"><div class="entry_author_image"><img src="http://www.maestrosdelweb.com/wp-content/authors/cvander-72.jpg" alt="" style="float:left;padding:0 5px" /></div>
 <strong>Christian Van Der Henst S.</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/codecademy-educacion-virtual/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/codecademy-educacion-virtual/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/codecademy-educacion-virtual/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/codecademy.jpg" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/codecademy.jpg" medium="image">
			<media:title type="html">CodeCademy</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/wp-content/authors/cvander-72.jpg" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Dos héroes de Python nos cuentan sus experiencias</title>
		<link>http://www.maestrosdelweb.com/editorial/heroes-python-cuentan-experiencias/</link>
		<comments>http://www.maestrosdelweb.com/editorial/heroes-python-cuentan-experiencias/#comments</comments>
		<pubDate>Wed, 23 May 2012 21:05:03 +0000</pubDate>
		<dc:creator>Eugenia Tobar</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Guía Python]]></category>
		<category><![CDATA[alvaro martinez]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[experiencia]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[guia python]]></category>
		<category><![CDATA[julian amaya]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=23279</guid>
		<description><![CDATA[Dentro de la diversidad de lenguajes que existen, Python se ha caracterizado por su facilidad de aprendizaje y flexibilidad en el desarrollo de aplicaciones y web. Permite a programadores principiantes entender rápidamente su sintaxis y a experimentados la simplificación de lineas de código. El crecimiento de su comunidad va en aumento al igual que la [...]]]></description>
			<content:encoded><![CDATA[<p>Dentro de la diversidad de lenguajes que existen, <a href="http://www.maestrosdelweb.com/guias/#guia-python">Python</a> se ha caracterizado por su facilidad de aprendizaje y flexibilidad en el desarrollo de aplicaciones y web. Permite a programadores principiantes entender rápidamente su sintaxis y a experimentados la simplificación de lineas de código. </p>
<p><img style="float:right;padding:5px" src="http://www.maestrosdelweb.com/images/2012/05/julian-amaya-photo.jpg" alt="Julian-amaya" />El crecimiento de su comunidad va en aumento al igual que la presencia de aplicaciones y desarrollo web. En una entrevista <a href="http://twitter.com/#!/julian_amaya">Julián Amaya</a>, co-fundador de <a href="http://monoku.com/">Monoku</a>, nos confiesa estar enamorado de Python desde hace 3 años y nos comenta algunas razones del porqué está enfocado en éste lenguaje:</p>
<blockquote><p>Una de las cosas chévere de Python es que se usa en muchas cosas, como lenguaje es muy flexible para trabajar aplicaciones nativas y juegos.</p></blockquote>
<p>Julián menciona también que algo que le gusta de Python es que permite escribir frameworks como <a href="http://www.maestrosdelweb.com/guias/#guias-django">Django</a> &#8220;que son muy bonitos y permiten trabajar muy fácil&#8221;. Opina que el que algunas aplicaciones trabajen Python en el Frontend en vez de Javascript y otros lenguajes que trabajan cosas que se parecen a Python muestra que &#8220;Python está aquí para quedarse y para hacer muchas cosas&#8221;.</p>
<h3>Desarrollemos propuestas</h3>
<p><a href="http://blog.elcodiguero.com/varios/18-sobre-el-sitio.html">Alvaro Martínez</a> desarrolla en Python y es <a href="http://www.forosdelweb.com/f130/">moderador del foro</a> en <a href="http://www.forosdelweb.com/">Foros del Web</a> desde el 2005, nos comenta que en principio se interesó mucho por HTML porque &#8220;lo veía como algo con lo que se podían lograr cosas interesantes&#8221;. También visitaba los foros de php y css, sin embargo, desde hace tres años participa activamente en el foro de Python. </p>
<p><img style="float:right;padding:5px" src="http://www.maestrosdelweb.com/images/2012/05/alvaro-martinez.jpg" alt="alvaro-martinez" />Alvaro comenta que es importante que la comunidad que programe en Python evolucione, que hayan nuevas propuestas para asegurar su avance y desarrollo sino, por ejemplo, visitar un foro se vuelve aburrido cuando no hay más que las mismas preguntas por parte de los usuarios. </p>
<p>He mencionado algunas características positivas que nos hacen considerar aprender Python a quienes no saben y reafirmar porqué lo hemos elegido para desarrollar, a pesar de ellos el lenguaje tiene aspectos negativos en los cuales ambos desarrolladores están de acuerdo: Python tiene una comunidad grande pero carece de soporte, como menciona Julián no es tan fácil encontrar un servidor para Python como lo es para PHP. </p>
<h3>¿Cómo puedo aprender Python?</h3>
<p>Python es bastante intuitivo, ambos desarrolladores comentan que aprendieron practicando, realizando proyectos con aspectos básicos y poco a poco mejorarlos. Si quieres aprender Python y no conoces ningun lenguaje de programación Julian recomienda el libro <a href="http://learnpythonthehardway.org/">Learn Python: The hard way</a> que te lleva de lo básico a lo avanzado. Si tienes ya experiencia en algún lenguaje que no sea Python, &#8220;crea un proyecto&#8221; es fácil y aprendes mientras lo desarrollas. </p>
<h3><a href="http://www.maestrosdelweb.com/guias/#guia-python">Guía Python</a></h3>
<p>En Maestros del web publicamos hace algunos meses el <a href="http://www.maestrosdelweb.com/editorial/guia-python/">primer capítulo de la guía Python</a> y aún estamos en proceso de agregar más capítulos de este lenguaje. En próximas entregas publicaremos más capítulos con autoría de Alvaro Martínez. </p>
<hr /><p style="height: 64px;"><div class="entry_author_image"><img src="http://www.maestrosdelweb.com/wp-content/authors/eutobar-73.jpg" alt="" style="float:left;padding:0 5px" /></div>
 <strong>Eugenia Tobar</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/heroes-python-cuentan-experiencias/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/heroes-python-cuentan-experiencias/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/heroes-python-cuentan-experiencias/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/julian-amaya-photo.jpg" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/julian-amaya-photo.jpg" medium="image">
			<media:title type="html">Julian-amaya</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/alvaro-martinez.jpg" medium="image">
			<media:title type="html">alvaro-martinez</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/wp-content/authors/eutobar-73.jpg" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Curso Symfony 2: Seguridad de acceso</title>
		<link>http://www.maestrosdelweb.com/editorial/curso-symfony2-seguridad-de-acceso/</link>
		<comments>http://www.maestrosdelweb.com/editorial/curso-symfony2-seguridad-de-acceso/#comments</comments>
		<pubDate>Wed, 23 May 2012 16:07:52 +0000</pubDate>
		<dc:creator>Maycol Alvarez</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[access control]]></category>
		<category><![CDATA[capitulo13]]></category>
		<category><![CDATA[firewall]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[Seguridad]]></category>
		<category><![CDATA[symfony 2]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=22970</guid>
		<description><![CDATA[Uno de los aspectos más importantes en el desarrollo de cualquier aplicación es la Seguridad de acceso, para ello Symfony 2 dispone de una moderna librería que se encarga de las validaciones de acceso y seguridad. En este capítulo nos dispondremos a crear un ejemplo básico de seguridad que nos permita hacer el &#8220;login&#8221; de [...]]]></description>
			<content:encoded><![CDATA[<p>Uno de los aspectos más importantes en el desarrollo de cualquier aplicación es la Seguridad de acceso, para ello Symfony 2 dispone de una moderna librería que se encarga de las validaciones de acceso y seguridad.</p>
<p>En este capítulo nos dispondremos a crear un ejemplo básico de seguridad que nos permita hacer el &#8220;login&#8221; de los usuarios y a su vez bloquear el acceso a determinados usuarios según su rol, para ello tendremos que adentrarnos en como funciona la librería de seguridad de Symfony2, luego crearemos las estructuras necesarias para definir un mini-backend donde crearemos unos CRUD&#8217;s para usuarios y roles utilizando Doctrine como proveedor de usuarios.</p>
<h3>Autenticación vs. Autorización </h3>
<p>Representan los 2 conceptos más fundamentales de seguridad en Symfony, el primero se encarga de verificar si el usuario en cuestión está Autenticado (logeado) y se le conoce como &#8220;Firewall&#8221;, el segundo verifica si el usuario tiene los permisos o &#8220;roles&#8221; necesarios y se le conoce como &#8220;access_control&#8221;.</p>
<p>El primer paso es verificar si el usuario está o no autenticado, en tal caso lo deja pasar y el segundo paso es verificar si el usuario tiene el rol necesario para dicha acción, para comprenderlo mejor veamos un ejemplo básico del archivo de configuración:</p>
<div class="codigo">
<pre># proyecto/app/config/security.yml
security:
    firewalls:
        secured_area:
            pattern:    ^/
            anonymous: ~
            http_basic:
                realm: "Secured Demo Area"

    access_control:
        - { path: ^/admin, roles: ROLE_ADMIN }

    providers:
        in_memory:
            users:
                usuario:  { password: user, roles: 'ROLE_USER' }
                admin: { password: kitten, roles: 'ROLE_ADMIN' }

    encoders:
        Symfony\Component\Security\Core\User\User: plaintext</pre>
</div>
<p>Vemos como primer elemento definido los conjuntos de firewall y en él una &#8220;secured_area&#8221; donde:</p>
<ol>
<li><strong>pattern:</strong> es una expresión regular para hacer empatar la URL, toda ruta que empate con ello obligará al mecanismo de firewall que verifique si el usuario está autenticado, si no lo está procederá a re-dirigirlo al formulario de autenticación (en el caso anteterior mostrar el díalogo nativo de autenticación HTTP del navegador).</li>
<li><strong>anonymous: ~: </strong>indica que permite usuarios anónimos, no se debe aplicar en caso de backends.</li>
<li><strong>http_basic: </strong> indica que utilice la autenticación HTTP.</li>
</ol>
<p>Por su parte el Mecanismo de Autorización <strong>&#8220;access_control&#8221;</strong> actúa de forma diferente, porque aunque dependa de que el usuario esté autenticado verifica si el mismo dispone de los permisos (roles) necesarios para determinada operación:</p>
<ul>
<li><strong>- { path: ^/admin, roles: ROLE_ADMIN }</strong>indica una regla básica para autorización, donde en toda ruta que coincida al principio con <strong>/admin</strong>, el usuario debe de tener dicho rol &#8220;ROLE_ADMIN&#8221; indicado.</li>
</ul>
<div class="tipexperto"><h3>Nota</h3> <div class="tipcont"> Puedes añadir tantos access_control como necesites.</div></div>
<p><strong>&#8220;providers&#8221;</strong> simplemente define el proveedor de usuario, que en este caso es en memoria, y <strong>&#8220;encoders&#8221;</strong> define el codificador de la contraseña, el cual debe ser de algún tipo de HASH como SHA512, en el ejemplo se usa texto plano. (más adelante se exponen ejemplos detallados).</p>
<h3>Configuraciones del Control de Acceso</h3>
<p>El control de acceso no sólo se limita a controlar que el usuario cumpla con un rol determinado para un patrón de ruta determinada, permite cierta flexibilidad con el que podrás adaptarte a las necesidades de seguridad de tu aplicación.</p>
<p><strong>Protegiendo por IP</strong><br />
Tan simple como añadir el parámetro ip, con la misma puedes obligar a que una ruta solo se pueda acceder desde dicha ip (ideal para el backend interno):</p>
<div class="codigo">
<pre># app/config/security.yml
security:
    # ...
    access_control:
        - { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }</pre>
</div>
<p><strong>Protegiendo por Canal</strong><br />
Si dispones de un certificado SSL puedes obligar a que la ruta solo esté disponible desde https, especificando requires_channel:</p>
<div class="codigo">
<pre># app/config/security.yml
security:
    # ...
    access_control:
        - { path: ^/cart/checkout, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https}</pre>
</div>
<p><strong>Protegiendo un Controlador</strong><br />
En ocasiones necesitamos que el controlador se encargue del control de acceso, de forma que podamos flexibilizarlo según nuestro modelo de negocios, para ello podremos acceder al contexto de seguridad desde nuestros controladores:</p>
<div>
<pre class="brush: php; title: ; notranslate">
//dentro de un controlador
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
// ...
public function helloAction($name)
{
     if (false === $this-&gt;get(’security.context’)-&gt;isGranted(’ROLE_ADMIN’)) {
          throw new AccessDeniedException();
     }
     // ...
}
</pre>
</div>
<p>También puede optar por instalar y utilizar el Bundle opcional <strong>JMSSecurityExtraBundle</strong>, el cual puede asegurar su controlador usando anotaciones:</p>
<div>
<pre class="brush: php; title: ; notranslate">
//dentro de un controlador
use JMS\SecurityExtraBundle\Annotation\Secure;
/**
  * @Secure(roles=&quot;ROLE_ADMIN&quot;)
  */
public function helloAction($name)
{
     // ...
}
</pre>
</div>
<p>Para más información, consulte la documentación de JMSSecurityExtraBundle. Si estás usando la distribución estándar de Symfony, este paquete está disponible de forma predeterminada. Si no es así, lo puedes descargar e instalar.</p>
<p><strong>Controlando el acceso desde plantilla</strong><br />
Incluso puedes verificar si el usuario tiene acceso desde la misma plantilla,<em> útil para ocultar segmentos a roles específicos</em>:<br />
Desde <strong>Twig</strong></p>
<div class="codigo">
<pre class="brush: plain; title: ; notranslate">
{% if is_granted(’ROLE_ADMIN’) %}
     &lt;a href=&quot;...&quot;&gt;Delete&lt;/a&gt;
{% endif %}
</pre>
</div>
<p>Desde <strong>PHP</strong></p>
<div>
<pre class="brush: php; title: ; notranslate">
&lt;?php if ($view[’security’]-&gt;isGranted(’ROLE_ADMIN’)): ?&gt;
    &lt;a href=&quot;...&quot;&gt;Delete&lt;/a&gt;
&lt;?php endif; ?&gt;
</pre>
</div>
<p><strong>Recuperando del objeto usuario</strong><br />
Desde un controlador, puedes acceder fácilmente a la instancia del usuario actual utilizando el Mecanismo de inyección de dependencias:</p>
<div>
<pre class="brush: php; title: ; notranslate">
//dentro de un controlador
public function indexAction()
{
  $user = $this-&gt;get(’security.context’)-&gt;getToken()-&gt;getUser();
}
</pre>
</div>
<h3>Tutorial: mini-backend de usuarios con Doctrine</h3>
<p>Realmente el ejemplo anterior es demasiado básico como para llevarlo a una aplicación real, y una de las opciones más tentadoras es utilizar Doctrine como proveedor de los Usuarios, con el cual podamos crear Roles y Usuarios desde CRUD&#8217;s elaborados por el mismo framework y crear nuestro propio esquema de seguridad, debo resaltar que existen muchos Bundles prefabricados como el FOSUserBundle que facilitan enormemente ésta tarea, pero si quieres profundizar puedes seguir el siguiente tutorial para conocer a fondo como se hace desde 0 con Doctrine <img src='http://www.maestrosdelweb.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<p><strong>Paso 1: Crea las entidades básicas</strong><br />
Antes de empezar debemos de definir las entidades básicas para ser utilizadas como proveedor de usuarios y roles en Sf2, dichas entidades <strong>User</strong> y <strong>Role</strong> deben de implementar las interfaces Symfony\Component\Security\Core\User\UserInterface y Symfony\Component\Security\Core\Role\RoleInterface respectivamente, así que añade estas 2 entidades a tu directorio &#8220;proyecto/src/MDW/BlogBundle/Entity&#8221;:</p>
<p><strong>User.php:</strong></p>
<div>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// proyecto/src/MDW/BlogBundle/Entity/User.php
namespace MDW\BlogBundle\Entity;

use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;
/**
  * @ORM\Entity
  * @ORM\Table(name=&quot;admin_user&quot;)
  */
class User implements UserInterface
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name=&quot;id&quot;, type=&quot;integer&quot;)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy=&quot;AUTO&quot;)
     */
    private $id;

    /**
    * @ORM\Column(type=&quot;string&quot;, length=&quot;255&quot;)
    */
    protected $username;

    /**
     * @ORM\Column(name=&quot;password&quot;, type=&quot;string&quot;, length=&quot;255&quot;)
     */
    protected $password;

    /**
     * @ORM\Column(name=&quot;salt&quot;, type=&quot;string&quot;, length=&quot;255&quot;)
     */
    protected $salt;

    /**
     * se utilizó user_roles para no hacer conflicto al aplicar -&gt;toArray en getRoles()
     * @ORM\ManyToMany(targetEntity=&quot;Role&quot;)
     * @ORM\JoinTable(name=&quot;user_role&quot;,
     *     joinColumns={@ORM\JoinColumn(name=&quot;user_id&quot;, referencedColumnName=&quot;id&quot;)},
     *     inverseJoinColumns={@ORM\JoinColumn(name=&quot;role_id&quot;, referencedColumnName=&quot;id&quot;)}
     * )
     */
    protected $user_roles;

    public function __construct()
    {
        $this-&gt;user_roles = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this-&gt;id;
    }

    /**
     * Set username
     *
     * @param string $username
     */
    public function setUsername($username)
    {
        $this-&gt;username = $username;
    }

    /**
     * Get username
     *
     * @return string
     */
    public function getUsername()
    {
        return $this-&gt;username;
    }

    /**
     * Set password
     *
     * @param string $password
     */
    public function setPassword($password)
    {
        $this-&gt;password = $password;
    }

    /**
     * Get password
     *
     * @return string
     */
    public function getPassword()
    {
        return $this-&gt;password;
    }

    /**
     * Set salt
     *
     * @param string $salt
     */
    public function setSalt($salt)
    {
        $this-&gt;salt = $salt;
    }

    /**
     * Get salt
     *
     * @return string
     */
    public function getSalt()
    {
        return $this-&gt;salt;
    }

    /**
     * Add user_roles
     *
     * @param Maycol\BlogBundle\Entity\Role $userRoles
     */
    public function addRole(\Maycol\BlogBundle\Entity\Role $userRoles)
    {
        $this-&gt;user_roles[] = $userRoles;
    }

    public function setUserRoles($roles) {
        $this-&gt;user_roles = $roles;
    }

    /**
     * Get user_roles
     *
     * @return Doctrine\Common\Collections\Collection
     */
    public function getUserRoles()
    {
        return $this-&gt;user_roles;
    }

    /**
     * Get roles
     *
     * @return Doctrine\Common\Collections\Collection
     */
    public function getRoles()
    {
        return $this-&gt;user_roles-&gt;toArray(); //IMPORTANTE: el mecanismo de seguridad de Sf2 requiere ésto como un array
    }

    /**
     * Compares this user to another to determine if they are the same.
     *
     * @param UserInterface $user The user
     * @return boolean True if equal, false othwerwise.
     */
    public function equals(UserInterface $user) {
        return md5($this-&gt;getUsername()) == md5($user-&gt;getUsername());

    }

    /**
     * Erases the user credentials.
     */
    public function eraseCredentials() {

    }
}
</pre>
</div>
<p><strong>Role.php:</strong></p>
<div>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// proyecto/src/MDW/BlogBundle/Entity/Role.php
namespace MDW\BlogBundle\Entity;

use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name=&quot;admin_roles&quot;)
 */
class Role implements RoleInterface
{
    /**
     * @ORM\Id
     * @ORM\Column(type=&quot;integer&quot;)
     * @ORM\GeneratedValue(strategy=&quot;AUTO&quot;)
     */
    protected $id;

    /**
     * @ORM\Column(name=&quot;nombre&quot;, type=&quot;string&quot;, length=&quot;255&quot;)
     */
    protected $name;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this-&gt;id;
    }

    /**
     * Set name
     *
     * @param string $name
     */
    public function setName($name)
    {
        $this-&gt;name = $name;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this-&gt;name;
    }

    public function getRole() {
        return $this-&gt;getName();
    }

    public function __toString() {
        return $this-&gt;getRole();
    }
}
</pre>
</div>
<p>Una vez creadas nuestras entidades, accedemos a la consola de Symfony2 y generamos las tablas en Base de Datos:</p>
<div class="codigo">
<pre>$ app/console doctrine:schema:update --force</pre>
</div>
<p><strong>Paso 2: Generando los CRUD&#8217;s</strong></p>
<p>Una vez creadas las entidades en DB, procedemos a crear los CRUD&#8217;s desde la consola de symfony:</p>
<div class="codigo">
<pre>$ app/console doctrine:generate:crud</pre>
</div>
<p>Seguimos los pasos colocando <strong>MDWBlogBundle:Role</strong>, luego nos solicita si deseamos crear las opciones de escritura, le decimos <strong>&#8220;y&#8221;</strong> (sí), formato del CRUD: <strong>annotation</strong>, y finalmente en el Routes prefix colocamos <strong>/admin/role</strong>, este paso es importante porque a la ruta le asignamos el prefijo /admin para que nos permita empatar luego con el access_control, confirmamos y aparecerá el mensaje <em>&#8220;You can now start using the generated code!&#8221;</em></p>
<p>Procedemos a aplicar lo mismo pero en este caso con <strong>MDWBlogBundle:User</strong> y en Routes prefix colocamos <strong>/admin/user</strong></p>
<p>Ahora añadiremos las rutas a nuestro archivo de rutas (proyecto/src/MDW/BlogBundle/Resources/Config/routing.yml), porque al crearlas como Anotaciones las mismas no se añaden automáticamente:</p>
<div class="codigo">
<pre>#proyecto/src/MDW/BlogBundle/Resources/Config/routing.yml
# final del archivo:
MDWAnnotations:
    resource: "@MDWBlogBundle/Controller/"
    prefix:   /
    type:     annotation</pre>
</div>
<p>De ésta forma <strong>añadiremos todas las rutas definidas por anotaciones del directorio Controller</strong>, ésta técnica forma parte del <strong>SensioFrameworkExtraBundle</strong> y nos permite definir las rutas directamente en nuestros controladores. si utilizas la Versión estándar de Symfony2 este Bundle viene por defecto.</p>
<p>Ya con esto podemos acceder a nuestros crud&#8217;s desde <strong>localhost/proyecto/web/app_dev.php/admin/user</strong>, pero aún debemos modificar ciertos aspectos en el controlador <strong>User</strong> para codificar el hash de contraseña.</p>
<p>Primero añadiremos la siguiente función en el controlador de usuarios:</p>
<div>
<pre class="brush: php; title: ; notranslate">
// proyecto/src/MDW/BlogBundle/Controller/UserController.php
// añadimos esta función
private function setSecurePassword(&amp;$entity) {
	$entity-&gt;setSalt(md5(time()));
	$encoder = new \Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder('sha512', true, 10);
	$password = $encoder-&gt;encodePassword($entity-&gt;getPassword(), $entity-&gt;getSalt());
	$entity-&gt;setPassword($password);
}
</pre>
</div>
<p>Luego modificamos las funciones de las acciones correspondientes a create y update, añadiendo la llamada al la función anterior para establecer el hash de la contraseña con el algoritmo SHA512:</p>
<div>
<pre class="brush: php; title: ; notranslate">
// proyecto/src/MDW/BlogBundle/Controller/UserController.php

//funcion createAction:
    public function createAction()
    {
        $entity  = new User();
        $request = $this-&gt;getRequest();
        $form    = $this-&gt;createForm(new UserType(), $entity);
        $form-&gt;bindRequest($request);

        if ($form-&gt;isValid()) {
            //establecemos la contraseña: --------------------------
            $this-&gt;setSecurePassword($entity);

            $em = $this-&gt;getDoctrine()-&gt;getEntityManager();
            $em-&gt;persist($entity);
            $em-&gt;flush();

            return $this-&gt;redirect($this-&gt;generateUrl('admin_user_show', array('id' =&gt; $entity-&gt;getId())));

        }

        return array(
            'entity' =&gt; $entity,
            'form'   =&gt; $form-&gt;createView()
        );
    }
//...
//funcion updateAction:
    public function updateAction($id)
    {
        $em = $this-&gt;getDoctrine()-&gt;getEntityManager();

        $entity = $em-&gt;getRepository('MDWBlogBundle:User')-&gt;find($id);

        if (!$entity) {
            throw $this-&gt;createNotFoundException('Unable to find User entity.');
        }

        $editForm   = $this-&gt;createForm(new UserType(), $entity);
        $deleteForm = $this-&gt;createDeleteForm($id);

        $request = $this-&gt;getRequest();

        //obtiene la contraseña actual -----------------------
        $current_pass = $entity-&gt;getPassword();

        $editForm-&gt;bindRequest($request);

        if ($editForm-&gt;isValid()) {
            //evalua si la contraseña fue modificada: ------------------------
            if ($current_pass != $entity-&gt;getPassword()) {
                $this-&gt;setSecurePassword($entity);
            }
            $em-&gt;persist($entity);
            $em-&gt;flush();

            return $this-&gt;redirect($this-&gt;generateUrl('admin_user_edit', array('id' =&gt; $id)));
        }

        return array(
            'entity'      =&gt; $entity,
            'edit_form'   =&gt; $editForm-&gt;createView(),
            'delete_form' =&gt; $deleteForm-&gt;createView(),
        );
    }
</pre>
</div>
<p>Por último sólo nos queda eliminar del formulario (src/MDW/BlogBundle/Form/UserType.php) el campo <strong>salt</strong> el cual no debe ser modificado por el usuario:</p>
<div>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// proyecto/src/MDW/BlogBundle/Form/UserType.php
namespace MDW\BlogBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;

class UserType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder
            -&gt;add('username')
            -&gt;add('password')
            //-&gt;add('salt') //No necesitamos que salt sea mostrado ---------------
            -&gt;add('user_roles')
        ;
    }

    public function getName()
    {
        return 'mdw_blogbundle_usertype';
    }
}
</pre>
</div>
<p>Ahora puedes proceder a registrar usuarios y roles, <strong>es muy importante que al menos crees los roles &#8220;ROLE_ADMIN&#8221; y &#8220;ROLE_USER&#8221;</strong> y <em><strong>dos usuarios</strong></em> (uno con un rol diferente) antes de que procedas en aplicar el esquema de seguridad, de lo contrario no tendrás usuario con que loguearte <img src='http://www.maestrosdelweb.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<p><strong>Paso 3: Creando el esquema de seguridad</strong><br />
Ahora procedemos a sobreescribir nuestro esquema de seguridad (proyecto/app/config/security.yml), recomiendo que antes de hacerlo guardes una copia del security.yml.</p>
<div class="codigo">
<pre># proyecto/app/config/security.yml
security:
    encoders:
        MDW\BlogBundle\Entity\User:
            algorithm: sha512
            encode-as-base64: true
            iterations: 10

    providers:
        user_db:
            entity: { class: MDW\BlogBundle\Entity\User, property: username }

    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false

        login:
            pattern:  ^/admin/login$
            security: false

        secured_area:
            pattern:    ^/admin/
#            http_basic:
#                realm: "Introduzca Usuario y Contraseña"
            form_login:
                login_path: /admin/login
                check_path: /admin/login_check
            logout:
                path: /admin/logout
                target: /

    access_control:
      - { path: ^/admin, roles: ROLE_ADMIN }</pre>
</div>
<p>Como puedes apreciar en &#8220;<strong>encoders</strong>&#8221; se ha definido un codificador especifico para la entidad User, utilizando el algoritmo SHA512, además codificandolo en Base64 con 10 iteracciones, tal cual se apreció en la función <strong>setSecurePassword</strong> del controlador.</p>
<p>En &#8220;<strong>providers</strong>&#8221; se estableció nuestra entidad User de Doctrine, especificando el campo correspondiente al username, es cual es el mismo username en nuestra entidad.</p>
<p>En &#8220;<strong>firewalls</strong>&#8221; se ha añadido la nueva regla (o firewall) <strong>login</strong> desde la cual se aplica el parametro <strong>security: false</strong> lo que permite acceder a la misma sin autenticarse, de lo contrario el formulario de login nunca lo podremos visializar.</p>
<p>Además en &#8220;<strong>secured_area</strong>&#8221; se ha eliminado anonymous, se ha establecido &#8220;<strong>form_login</strong>&#8221; donde definimos la ruta para el login del sistema, y se definió una ruta personalizada para el &#8220;<strong>log_out</strong>&#8220;, donde en &#8220;<strong>target</strong>&#8221; podemos definir el path hacia donde redirigir cuando los usuarios cierren sesión.</p>
<p>Para culminar sólo necesitamos crear el controlador y vista para nuestro login, por lo que debes de crear el archivo SecurityController.php en el directorio (proyecto/src/MDW/BlogBundle/Controller):</p>
<p>SecurityController.php</p>
<div>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// proyecto/src/MDW/BlogBundle/Controller/SecurityController.php
namespace MDW\BlogBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Security\Core\SecurityContext;

/**
 * Security controller.
 *
 * @Route(&quot;/admin&quot;)
 */
class SecurityController extends Controller
{
    /**
     * Definimos las rutas para el login:
     * @Route(&quot;/login&quot;, name=&quot;login&quot;)
     * @Route(&quot;/login_check&quot;, name=&quot;login_check&quot;)
     */
    public function loginAction()
    {
        $request = $this-&gt;getRequest();
        $session = $request-&gt;getSession();
        // obtiene el error de inicio de sesión si lo hay
        if ($request-&gt;attributes-&gt;has(SecurityContext::AUTHENTICATION_ERROR)) {
            $error = $request-&gt;attributes-&gt;get(SecurityContext::AUTHENTICATION_ERROR);
        } else {
            $error = $session-&gt;get(SecurityContext::AUTHENTICATION_ERROR);
        }
        return $this-&gt;render('MDWBlogBundle:Security:login.html.twig', array(
            // el último nombre de usuario ingresado por el usuario
            'last_username' =&gt; $session-&gt;get(SecurityContext::LAST_USERNAME),
            'error'         =&gt; $error,
        ));
    }
}
?&gt;
</pre>
</div>
<p>Ahora crea el directorio &#8220;Security&#8221; dentro de (proyecto/src/MDW/BlogBundle/Resources/views) y procede a crear el archivo de vista:</p>
<p>login.html.twig</p>
<div>
<pre class="brush: xml; title: ; notranslate">
{# proyecto/src/MDW/BlogBundle/Resources/views/Security/login.html.twig #}
{% if error %}
&lt;div&gt;{{ error.message }}&lt;/div&gt;

{% endif %}
&lt;form action=&quot;{{ path('login_check') }}&quot; method=&quot;post&quot;&gt;&lt;label for=&quot;username&quot;&gt;Username:&lt;/label&gt;
 &lt;input id=&quot;username&quot; type=&quot;text&quot; name=&quot;_username&quot; value=&quot;{{ last_username }}&quot; /&gt;
 &lt;label for=&quot;password&quot;&gt;Password:&lt;/label&gt;
 &lt;input id=&quot;password&quot; type=&quot;password&quot; name=&quot;_password&quot; /&gt;

 &lt;input type=&quot;submit&quot; name=&quot;login&quot; /&gt;
&lt;/form&gt;
</pre>
</div>
<p>Y con ello ya puedes intentar acceder a <strong>localhost/proyecto/web/admin/user</strong> y probar el sistema de seguridad de Symfony2 (vaciar la caché en el caso de entrar al entorno de producción), <strong>si creaste previamente 2 usuarios</strong>, intenta acceder con el usuario que no tiene el rol &#8220;ROLE_ADMIN&#8221; y verás como te niega el acceso, en cambio si pruebas con un usuario con dicho rol, puedes entrar perfectamente.</p>
<h3>Resumen Final</h3>
<p>En esta ocasión apreciamos el complejo sistema de seguridad de Symfony2, en donde un <strong>firewall</strong> verifica si el usuario está o no logueado, y un <strong>access control</strong> vigila que dicho usuario no pueda acceder a contenido del cual no se le ha dado acceso, también conocimos que se pueden definir <strong>providers</strong> diferentes para contener a nuestros usuarios y <strong>encoders</strong> para personalizar el HASH de la contraseña.</p>
<p>Además interactuamos con dicho sistema a través de un &#8220;rápido&#8221; tutorial que nos permitió resolver las inquietudes más directas en cuanto a creación de un básico RBAC (Role-based Access Control), reitero que no es la única forma de hacerlo y que existen muchos Bundles Prefabricados como el FOSUserBundle que nos facilita enormemente ésta tarea, pero si no se conoce debidamente la base puede resultar una verdadera <em>caja negra</em> el usar un Bundle sin el previo conocimiento de como Symfony2 implementa tales mecanismos.</p>
<hr /><p style="height: 64px;"><img alt='Maycol Alvarez' src='http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Maycol Alvarez</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-seguridad-de-acceso/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-seguridad-de-acceso/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/curso-symfony2-seguridad-de-acceso/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:thumbnail url="http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" />
		<media:content url="http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Maycol Alvarez</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Khan Academy, una plataforma de educación virtual invirtiendo en ladrillo</title>
		<link>http://www.maestrosdelweb.com/editorial/khan-academy-educacion-virtual/</link>
		<comments>http://www.maestrosdelweb.com/editorial/khan-academy-educacion-virtual/#comments</comments>
		<pubDate>Tue, 22 May 2012 19:21:57 +0000</pubDate>
		<dc:creator>Christian Van Der Henst S.</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[educacion virtual]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[khan academy]]></category>
		<category><![CDATA[plataforma]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24621</guid>
		<description><![CDATA[En serio, ¿por qué invirten en ladrillos? ¿van a dar diplomas? ¿alquilarán birretes? permítanme explicar más y dar un poco de contexto para quienes aún no conocen la historia de Khan Academy y su creador Salman Khan. Un hombre en Boston jugaba a la bolsa de valores exitosamente, pero un día se le presentó un [...]]]></description>
			<content:encoded><![CDATA[<p>En serio, ¿por qué invirten en ladrillos? ¿van a dar diplomas? ¿alquilarán birretes? permítanme explicar más y dar un poco de contexto para quienes aún no conocen la historia de Khan Academy y su creador Salman Khan.</p>
<p>Un hombre en Boston jugaba a la bolsa de valores exitosamente, pero un día se le presentó un gran desafío: enseñarle algebra a sus sobrinos. Como todos nos imaginamos, la forma más eficiente para lograrlo, era contando una historia mientras dibujaba en una pizarra digital y lo compartía en youtube. Así es, el mismo youtube donde vos y yo hemos perdido tanto el tiempo viendo memes y videos musicales.</p>
<p>Con el tiempo, <a href="http://www.khanacademy.org/" title="Khan Academy">Khan Academy</a> en su canal de youtube ha reproducido más de 151 millones de lecciones en vídeos que te enseñan desde álgebra, finanzas, historia y tecnología. La fundación Bill &amp; Melinda Gates junto a otros notables inversionistas les dieron suficiente dinero para que intenten cambiar el mundo educándolo mejor. Han recibido aportes de más de 7 millones de dólares a la fecha. Les recomiendo la charla de <a href="http://www.ted.com/talks/salman_khan_let_s_use_video_to_reinvent_education.html" title="Salman Khan en Ted">Salman Khan en Ted</a> que nos cuenta más del proyecto.</p>
<p style="text-align:center"><img src="http://www.maestrosdelweb.com/images/2012/05/khan-academy.jpg" alt="Khan Academy" title="Khan Academy" width="700" height="215" class="alignnone size-full wp-image-24882" /></p>
<h3>Javascript como base de la plataforma</h3>
<p>Uno de los héroes que se unió a este cometido es <a href="http://ejohn.org/" title="John Resig">John Resig</a>. Si no sabes quién es, digamos que el ayudó a crear el framework de jQuery, del que seguramente has copy&amp;pasteado más de algún código para ponerle alguna funcionalidad al frontend de tu sitio web. Resig, <a href="http://ejohn.org/blog/khan-exercise-rewrite/" title="Khan Excercise Rewrite">se dedica a crear tecnología para esta universidad del futuro</a>. Me pregunto si este esfuerzo logrará erradicar la fórmula que BlackBoard (como software propietario) y Moodle (como software libre) han implementado en miles de centros universitarios. Centros que venden una educación virtual que sigue sin cambiar el mundo.  Y otro punto importante del apoyo de Resig es que está impulsando desde Khan que <a href="http://ejohn.org/blog/javascript-as-a-first-language/" title="Javascript sea el primer lenguaje que aprenden muchos estudiantes a programar">Javascript sea el primer lenguaje que aprenden muchos estudiantes a programar</a>.</p>
<p>Khan Academy va a seguir generando y curando contenido, está desarrollando una plataforma para organizar e impartir mucho mejor sus cursos y además tendrá muy pronto parqueos, sanitarios y cafetería. El mundo de la educación virtual convierte en tangible un espacio donde están comprometidos a enseñar. La marca y el financimiento que ha obtenido le da suficiente fuerza para luchar sola aunque siempre quedamos inquietos de las posibles alianzas con otras universidades.</p>
<p><a href="http://www.khanacademy.org/#browse" title="Catálogo de Khan Academy">Sumergirse en Khan Academy</a> es una experiencia recomendada para los que nos gusta repasar finanzas y algo de álgebra en el tiempo libre.  El proyecto se ha ganado <a href="http://larryferlazzo.edublogs.org/2011/11/20/the-best-posts-about-the-khan-academy/" title="detractores de Khan Academy">bastantes detractores</a> que cuestionan si realmente es el modelo revolucionario que todos esperamos, pero son palabras, no propuestas.  Envidia la dicen por mi tierra. </p>
<h3>¿La educación es un negocio de bienes raices?</h3>
<p>Al inicio de este post cuestionaba sobre la razón de los ladrillos que están comprando para construir un campus físico.  Cuando mueves muchos millones hay que justificar el plan y muchos de los asesores pueden tener más conocimiento sobre cómo generar conceptos universitarios ya reconocidos que transformar desde un catálogo de vídeos y nuevas platormas que funcionen online.  Si solo fuera un proyecto virtual tal vez la valuación no fuera tan alta, quizá solo haría falta seguir ganando de publicidad de las impresiones de los videos.</p>
<p>Sigo sin entender las razones por las que Khan Academy tendrá una universidad física, en mi cabeza sigue sin necesitarla, pero espero que cuando la llegue a visitar, que en lugar de estatuas y monumentos de científicos y notables personajes de la historia, que la estatua en la entrada sea de los sobrinos de Khan. Son los verdaderos heroes de esta nueva universidad. </p>
<p>- En un próximo artículo de esta <a href="http://www.maestrosdelweb.com/editorial/re-definiendo-educacion-virtual/" title="Re-definiendo lo que conocemos como Educación Virtual">serie de educación virtual</a>, hablaremos de Codecademy. Nos leemos mañana. </p>
<hr /><p style="height: 64px;"><div class="entry_author_image"><img src="http://www.maestrosdelweb.com/wp-content/authors/cvander-72.jpg" alt="" style="float:left;padding:0 5px" /></div>
 <strong>Christian Van Der Henst S.</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/khan-academy-educacion-virtual/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/khan-academy-educacion-virtual/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/khan-academy-educacion-virtual/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/khan-academy-150x150.jpg" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/khan-academy.jpg" medium="image">
			<media:title type="html">Khan Academy</media:title>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/khan-academy-150x150.jpg" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/wp-content/authors/cvander-72.jpg" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Curso Django: Las vistas</title>
		<link>http://www.maestrosdelweb.com/editorial/curso-django-las-vistas/</link>
		<comments>http://www.maestrosdelweb.com/editorial/curso-django-las-vistas/#comments</comments>
		<pubDate>Mon, 21 May 2012 12:12:38 +0000</pubDate>
		<dc:creator>Sergio Infante Montero</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[Editorial]]></category>
		<category><![CDATA[curso django]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[las vistas]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24755</guid>
		<description><![CDATA[Esta semana nos toca ver el tema de vistas, no se olviden que si este es el primer artículo que leen sobre Django en Maestros del Web, deben revisar la guía por completo, incluyendo los comentarios, donde se solucionaron muchas dudas, es necesario para que comprendan los ejemplos y aprendan fácilmente Django. Vistas Un función [...]]]></description>
			<content:encoded><![CDATA[<p>Esta semana nos toca ver el tema de vistas, no se olviden que si este es el primer artículo que leen sobre Django en Maestros del Web, deben revisar la <a href="http://www.maestrosdelweb.com/guias/#guias-django" title="Curso Django">guía por completo</a>, incluyendo los comentarios, donde se solucionaron muchas dudas, es necesario para que  comprendan los ejemplos y aprendan fácilmente Django.</p>
<h2>Vistas</h2>
<p>Un función de vista o una vista, <em>como es conocida generalmente</em>, es una función en Python que hace una solicitud Web y devuelve una respuesta Web, esta respuesta puede ser el contenido de una página, un error 404, una imagen, un documento XML, entre muchas cosas más. </p>
<p>La vista contiene toda la lógica necesaria para devolver una respuesta, todas estas respuestas se encuentran en un único archivo y este archivo se llama: <strong>views.py</strong>, que se encuentra dentro de cada aplicación de Django.</p>
<h3>Las consultas y las vistas</h3>
<p>En el <a href="http://www.maestrosdelweb.com/editorial/curso-django-el-shell-de-django/">capítulo anterior</a>, jugamos con algunas consultas, estas consultas son parte fundamental de las vistas, permiten elegir que tipo de contenido se visualizará. <a href="http://www.maestrosdelweb.com/editorial/curso-django-el-shell-de-django/" title="Consultas Django en Maestros del Web">Revisa y practica</a>, si no lo hiciste, para poder obtener mejores resultados.</p>
<h3>Las plantillas y las vistas</h3>
<p>Las plantillas son muy importantes, permiten acomodar el resultado que devuelve la vista. Django tiene un estupendo motor de plantillas que permite separar eficientemente la presentación, de la lógica de programación, esta semana trabajaremos con algunas plantillas simples para no causar confusión.</p>
<h2>Proyecto de ejemplo: las vistas</h2>
<p>Para esta semana debemos tener en cuenta que nuestros modelos almacenados en models.py dentro de la aplicación principal, quedaron así:</p>
<div id="attachment_24793" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-models-recetario.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-models-recetario-450x200.png" alt="models.py recetario" width="450" height="200" class="size-medium wp-image-24793" /></a><p class="wp-caption-text">models.py recetario</p></div>
<p>Rellenamos algunos datos para poder tener resultados:</p>
<div id="attachment_24796" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-admin-dashboard00.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-admin-dashboard00-450x302.png" alt="Django admin dashboard" width="450" height="302" class="size-medium wp-image-24796" /></a><p class="wp-caption-text">Django admin dashboard</p></div>
<div id="attachment_24795" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-add-user-recetario.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-add-user-recetario-450x245.png" alt="Django admin, agregar usuarios" width="450" height="245" class="size-medium wp-image-24795" /></a><p class="wp-caption-text">Django admin, agregar usuarios</p></div>
<div id="attachment_24807" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-recetas-recetario.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-recetas-recetario-450x214.png" alt="Django admin, agregar recetas" width="450" height="214" class="size-medium wp-image-24807" /></a><p class="wp-caption-text">Django admin, agregar recetas</p></div>
<p>Con estos datos empezaremos a hacer algunas vistas para nuestro proyecto. Empezaremos con las importaciones necesarias, que son estas:</p>
<div id="attachment_24812" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-views-import.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-views-import-450x45.png" alt="Django views.py import" width="450" height="45" class="size-medium wp-image-24812" /></a><p class="wp-caption-text">Django views.py import</p></div>
<p>La primera de ellas es porque necesitamos los modelos, la segunda línea para poder usar los datos del modelo usuario, la tercera línea es la respuesta más simple (HttpResponse), la cuarta importa: render_to_response (para las plantillas) y get_object_or_404 (para lanzar un error 404, de no encontrar ningún valor almacenado) y la quinta línea importa el RequestContext (en este caso para poder usar la ruta de las imágenes almacenadas previamente en la carpeta carga y referenciadas por la url media).</p>
<p>Ahora pasemos a ver donde usamos específicamente cada uno de estos componentes.</p>
<h3 id='sobre'>Vista: sobre</h3>
<p>Esta vista es un ejemplo muy simple del uso de HttpResponse, está devolviendo el contenido HTML:</p>
<div id="attachment_24815" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-views-sobre.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-views-sobre-450x54.png" alt="vista sobre" width="450" height="54" class="size-medium wp-image-24815" /></a><p class="wp-caption-text">vista sobre</p></div>
<div class='tipexperto'>
<h4>Nota:</h4>
<div class='tipcont'>Vamos a modificar <strong>urls.py</strong>, reescribir casi por completo, si eres impaciente y quieres ver como queda al final urls.py o no entiendes muy bien como hacerlo, <a href="#urlspy">puedes echarle un vistazo</a></div>
</div>
<p>Debemos tener en cuenta que siempre debemos acompañar una vista de su configuración en urls.py, así que en este archivo debemos tener esta línea: (ubicada dentro de patterns)</p>
<div class="codigo">
<pre>url(r'^sobre/$','principal.views.sobre'),</pre>
</div>
<p>Lanzamos nuestro servidor de desarrollo:(como todas las semanas)</p>
<div class="codigo">
<pre>python manage.py runserver</pre>
</div>
<p>Y vamos a la dirección:<br />
<a href="http://127.0.0.1:8000/sobre/" target="_blank">http://127.0.0.1:8000/sobre/</a></p>
<div id="attachment_24805" class="wp-caption aligncenter" style="width: 415px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-recetario-sobre.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-recetario-sobre.png" alt="vista sobre en el navegador" width="405" height="186" class="size-full wp-image-24805" /></a><p class="wp-caption-text">vista sobre en el navegador</p></div>
<h3>Vista: Inicio</h3>
<div id="attachment_24813" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-views-inicio.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-views-inicio-450x49.png" alt="vista inicio" width="450" height="49" class="size-medium wp-image-24813" /></a><p class="wp-caption-text">vista inicio</p></div>
<p>La vista inicio, hace una consulta de todas las recetas y las almacena en una variable llamada recetas (también), es aquí donde es apropiado usar render_to_response para poder indicarle que vamos a usar la plantilla inicio.html, y que le pasaremos en un diccionario (concepto de python), el resultado de la consulta.</p>
<p>La plantilla <strong>inicio.html</strong> debemos crearla en la carpeta &#8216;plantillas&#8217; que se encuentra en &#8216;recetario&#8217; (creada previamente en capítulos anteriores), su contenido debe ser similar al siguiente:</p>
<div id="attachment_24797" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-inicio-html.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-inicio-html-450x280.png" alt="inicio.html" width="450" height="280" class="size-medium wp-image-24797" /></a><p class="wp-caption-text">inicio.html</p></div>
<p>Veremos unos símbolos {% %} que por no deben distraernos, así que no entraré en detalles al respecto, pueden intuir de que trata, pero prefiero no confundirlos y dejarlos para la próxima semana. </p>
<p>Ahora igual que el ejemplo anterior debemos agregar la siguiente línea en nuestra configuración de las url en <strong>urls.py</strong>:</p>
<div class="codigo">
<pre>url(r'^$','principal.views.inicio'),</pre>
</div>
<p>Nuestro servidor debe estar funcionando y podemos ingresar a la siguiente dirección:</p>
<p><a href="http://127.0.0.1:8000/" target="_blank">http://127.0.0.1:8000/</a></p>
<div id="attachment_24800" class="wp-caption aligncenter" style="width: 378px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-recetario-index.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-recetario-index.png" alt="inicio.html" width="368" height="342" class="size-full wp-image-24800" /></a><p class="wp-caption-text">inicio.html</p></div>
<h3>Vista: usuarios</h3>
<p>Esta vista saca los datos de los usuarios registrados, y las recetas registradas. Y repite el mismo procedimiento de la vista anterior.</p>
<div id="attachment_24816" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-views-usuarios.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-views-usuarios-450x45.png" alt="vista usuarios" width="450" height="45" class="size-medium wp-image-24816" /></a><p class="wp-caption-text">vista usuarios</p></div>
<p>La plantilla <strong>usuarios.html</strong> debe ser creada en la carpeta plantillas y debe tener un contenido similar al siguiente:</p>
<div id="attachment_24809" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-usuarios-html.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-usuarios-html-450x377.png" alt="usuarios.html" width="450" height="377" class="size-medium wp-image-24809" /></a><p class="wp-caption-text">usuarios.html</p></div>
<p>En esta plantilla se estan juntando a los usuarios y sus respectivas recetas, agregamos la siguiente regla al <strong>urls.py</strong>:</p>
<div class="codigo">
<pre>url(r'^usuarios/$','principal.views.usuarios'),</pre>
</div>
<p>para ver el resultado (servidor corriendo), debemos entrar a:</p>
<p><a href="http://127.0.0.1:8000/usuarios/" target="_blank">http://127.0.0.1:8000/usuarios/</a></p>
<div id="attachment_24799" class="wp-caption aligncenter" style="width: 440px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-recetario-colaboradores.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-recetario-colaboradores.png" alt="Resultado de la vista usuarios" width="430" height="325" class="size-full wp-image-24799" /></a><p class="wp-caption-text">Resultado de la vista usuarios</p></div>
<h3>Vista: lista_recetas</h3>
<div id="attachment_24814" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-views-lista-recetas.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-views-lista-recetas-450x29.png" alt="vista lista_recetas" width="450" height="29" class="size-medium wp-image-24814" /></a><p class="wp-caption-text">vista lista_recetas</p></div>
<p>Esta vista, se diferencia de las anteriores por el uso de context_instance=RequestContext(request), usada para indicarle a la plantilla el parámetro {{MEDIA_URL}} que referencia a la ruta de las imágenes, la plantilla <strong>recetas.html</strong>, debe quedar así:</p>
<div id="attachment_24806" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-recetas-html.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-recetas-html-450x343.png" alt="Resultado de la vista lista_recetas" width="450" height="343" class="size-medium wp-image-24806" /></a><p class="wp-caption-text">Resultado de la vista lista_recetas</p></div>
<p>La línea en <strong>urls.py</strong> debe ser así:</p>
<div class="codigo">
<pre>url(r'^recetas/$','principal.views.lista_recetas'),</pre>
</div>
<p>Y se deben visualizar los resultados en:</p>
<p><a href="http://127.0.0.1:8000/recetas/" target="_blank">http://127.0.0.1:8000/recetas/</a></p>
<div id="attachment_24804" class="wp-caption aligncenter" style="width: 319px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-recetario-recetas.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-recetario-recetas-309x450.png" alt="Resultado de la vista lista_recetas" width="309" height="450" class="size-medium wp-image-24804" /></a><p class="wp-caption-text">Resultado de la vista lista_recetas</p></div>
<h3>Vista: detalle_receta</h3>
<div id="attachment_24811" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-views-detalle-receta.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-views-detalle-receta-450x31.png" alt="vista detalle_receta" width="450" height="31" class="size-medium wp-image-24811" /></a><p class="wp-caption-text">vista detalle_receta</p></div>
<p>Esta vista recibe un parametro mas: id_receta, que le sirve para hacer una consulta del detalle de esa receta (corresponde a su llave primaria) y usa <strong>get_object_or_404(Receta, pk=id_receta)</strong>, para obtener un objeto o un error 404 en caso de no encontrar resultado alguno. </p>
<p>Con este resultado, se realiza una consulta para obtener sus comentarios. La plantilla <strong>receta.html</strong>, quedará así:</p>
<div id="attachment_24798" class="wp-caption aligncenter" style="width: 444px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-receta-html.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-receta-html-434x450.png" alt="receta.html" width="434" height="450" class="size-medium wp-image-24798" /></a><p class="wp-caption-text">receta.html</p></div>
<p>La línea en <strong>urls.py</strong> debe ser así: (notar las expresiones regulares en python)</p>
<div class="codigo">
<pre>url(r'^receta/(?P&lt;id_receta&gt;\d+)$','principal.views.detalle_receta'),</pre>
</div>
<p>Y se deben visualizar los resultados al darle clic en los enlaces a recetas en:</p>
<p><a href="http://127.0.0.1:8000/recetas/" target="_blank">http://127.0.0.1:8000/recetas/</a></p>
<div id="attachment_24802" class="wp-caption aligncenter" style="width: 335px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-huevo-frito.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-huevo-frito-325x450.png" alt="receta: huevito frito" width="325" height="450" class="size-medium wp-image-24802" /></a><p class="wp-caption-text">receta: huevito frito</p></div>
<div id="attachment_24801" class="wp-caption aligncenter" style="width: 335px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-agua-hervida.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-agua-hervida-325x450.png" alt="receta: agua hervida" width="325" height="450" class="size-medium wp-image-24801" /></a><p class="wp-caption-text">receta: agua hervida</p></div>
<div id="attachment_24803" class="wp-caption aligncenter" style="width: 335px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-limonada.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-limonada-325x450.png" alt="receta: limonada" width="325" height="450" class="size-medium wp-image-24803" /></a><p class="wp-caption-text">receta: limonada</p></div>
<h3>Archivo final: views.py</h3>
<p>Al final de todo, <strong>views.py</strong> debe quedar de esta manera:</p>
<div id="attachment_24810" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-views.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-views-450x210.png" alt="views.py" width="450" height="210" class="size-medium wp-image-24810" /></a><p class="wp-caption-text">views.py</p></div>
<h3 id='urlspy'>Archivo: urls.py</h3>
<p>El archivo <strong>urls.py</strong>, permite tener unas urls limpias, para nuestro ejemplo este debe quedar de la siguiente manera: (si fuiste impaciente, <a href="#sobre">regresa a la vista: sobre <img src='http://www.maestrosdelweb.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </a> )</p>
<div id="attachment_24808" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-urls-py.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-urls-py-450x234.png" alt="urls.py" width="450" height="234" class="size-medium wp-image-24808" /></a><p class="wp-caption-text">urls.py</p></div>
<p>Para finalizar, si se perdieron con alguna línea o si desean corroborar que todo va bien, pueden estar pendientes del <a href="http://neosergio.github.com/recetario_mdw/" title="Recetario Django en Maestros del Web">repositorio del proyecto</a>. </p>
<p>La próxima semana veremos el tema de las plantillas con un poco más de detalle, practiquen haciendo sus propias vistas, usando las consultas que aprendieron en el capítulo anterior y complementen lo aprendido con <a href="https://docs.djangoproject.com/en/dev/topics/http/views/" title="Views en Django">un vistazo a la documentación oficial</a>, que nunca esta demás. Que tengan buen inicio de semana <img src='http://www.maestrosdelweb.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<hr /><p style="height: 64px;"><img alt='Sergio Infante Montero' src='http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Sergio Infante Montero</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/curso-django-las-vistas/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/curso-django-las-vistas/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/curso-django-las-vistas/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-models-recetario-150x150.png" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-models-recetario.png" medium="image">
			<media:title type="html">models.py recetario</media:title>
			<media:description type="html">models.py recetario</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-models-recetario-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-admin-dashboard00.png" medium="image">
			<media:title type="html">Django admin dashboard</media:title>
			<media:description type="html">Django admin dashboard</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-admin-dashboard00-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-add-user-recetario.png" medium="image">
			<media:title type="html">Django admin, agregar usuarios</media:title>
			<media:description type="html">Django admin, agregar usuarios</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-add-user-recetario-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-recetas-recetario.png" medium="image">
			<media:title type="html">Django admin, agregar recetas</media:title>
			<media:description type="html">Django admin, agregar recetas</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-recetas-recetario-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-views-import.png" medium="image">
			<media:title type="html">Django views.py import</media:title>
			<media:description type="html">Django views.py import</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-views-import-150x56.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-views-sobre.png" medium="image">
			<media:title type="html">vista sobre</media:title>
			<media:description type="html">vista sobre</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-views-sobre-150x64.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-sobre.png" medium="image">
			<media:title type="html">vista sobre en el navegador</media:title>
			<media:description type="html">vista sobre en el navegador</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-sobre-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-views-inicio.png" medium="image">
			<media:title type="html">vista inicio</media:title>
			<media:description type="html">vista inicio</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-views-inicio-150x57.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-inicio-html.png" medium="image">
			<media:title type="html">inicio.html</media:title>
			<media:description type="html">inicio.html</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-inicio-html-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-index.png" medium="image">
			<media:title type="html">inicio.html</media:title>
			<media:description type="html">inicio.html</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-index-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-views-usuarios.png" medium="image">
			<media:title type="html">vista usuarios</media:title>
			<media:description type="html">vista usuarios</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-views-usuarios-150x70.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-usuarios-html.png" medium="image">
			<media:title type="html">usuarios.html</media:title>
			<media:description type="html">usuarios.html</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-usuarios-html-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-colaboradores.png" medium="image">
			<media:title type="html">Resultado de la vista usuarios</media:title>
			<media:description type="html">Resultado de la vista usuarios</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-colaboradores-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-views-lista-recetas.png" medium="image">
			<media:title type="html">vista lista_recetas</media:title>
			<media:description type="html">vista lista_recetas</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-views-lista-recetas-150x56.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-recetas-html.png" medium="image">
			<media:title type="html">Resultado de la vista lista_recetas</media:title>
			<media:description type="html">Resultado de la vista lista_recetas</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-recetas-html-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-recetas.png" medium="image">
			<media:title type="html">Resultado de la vista lista_recetas</media:title>
			<media:description type="html">Resultado de la vista lista_recetas</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-recetas-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-views-detalle-receta.png" medium="image">
			<media:title type="html">vista detalle_receta</media:title>
			<media:description type="html">vista detalle_receta</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-views-detalle-receta-150x71.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-receta-html.png" medium="image">
			<media:title type="html">receta.html</media:title>
			<media:description type="html">receta.html</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-receta-html-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-huevo-frito.png" medium="image">
			<media:title type="html">receta: huevito frito</media:title>
			<media:description type="html">receta: huevito frito</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-huevo-frito-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-agua-hervida.png" medium="image">
			<media:title type="html">receta: agua hervida</media:title>
			<media:description type="html">receta: agua hervida</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-agua-hervida-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-limonada.png" medium="image">
			<media:title type="html">receta: limonada</media:title>
			<media:description type="html">receta: limonada</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-recetario-receta-limonada-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-views.png" medium="image">
			<media:title type="html">views.py</media:title>
			<media:description type="html">views.py</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-views-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-urls-py.png" medium="image">
			<media:title type="html">urls.py</media:title>
			<media:description type="html">urls.py</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-urls-py-150x150.png" />
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Sergio Infante Montero</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Re-definiendo lo que conocemos de educación virtual</title>
		<link>http://www.maestrosdelweb.com/editorial/re-definiendo-educacion-virtual/</link>
		<comments>http://www.maestrosdelweb.com/editorial/re-definiendo-educacion-virtual/#comments</comments>
		<pubDate>Mon, 21 May 2012 07:14:08 +0000</pubDate>
		<dc:creator>Christian Van Der Henst S.</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[educacion virtual]]></category>
		<category><![CDATA[elearning]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24619</guid>
		<description><![CDATA[Hace 10 años deambulaba por los pasillos de la universidad, entre fotocopias, libros de algún profesor, acceso a internet limitado o nulo durante el examen. Era una época donde me hacían aprender contabilidad sin usar excel, no soñaba en compartir documentos en alguna nube y mis apuntes en clase aún utilizaban la tecnología de la [...]]]></description>
			<content:encoded><![CDATA[<p>Hace 10 años deambulaba por los pasillos de la universidad, entre fotocopias, libros de algún profesor, acceso a internet limitado o nulo durante el examen. Era una época donde me hacían aprender contabilidad sin usar excel, no soñaba en compartir documentos en alguna nube y mis apuntes en clase aún utilizaban la tecnología de la tinta y el papel.</p>
<p>Durante ese tiempo, quedé enamorado con la idea de tener un rol en las aulas. Desde muy joven me asigné un nombre que siempre me ha costado llevar en la espalda: Maestros&#8230; ¿<a href="http://www.maestrosdelweb.com/guias/#maestrosdelweb">Maestro del Web</a>? Yo estaba aprendiendo, sigo aprendiendo; enseñar y compartir es una excusa para hacer la tarea. No hay mejor alumno que el que tiene que aprender a la fuerza con el deadline y compromiso de que va a compartir algún tema en clase.</p>
<p>La educación virtual se definió como el uso de las TIC´s en el modelo de aprendizaje que se acopla al tiempo y necesidad del estudiante. Esa educación adquirida en la experiencia y cursos que se imparten fuera del salón de clases, pero que el profesor puede ser un tutor que utiliza el internet como plataforma para impartir conocimiento.</p>
<p>Sin embargo, la educación virtual se ha utilizado falsamente en la batalla por expandir la base de usuarios de centros universitarios y lamentablemente, también para vender una experiencia más pasiva de educación con libertad de horarios, espacios y agenda. La educación virtual es visto como uno de los espacios donde menos se compromete el alumno a estudiar, concretar resultados, aprender un tema y finalmente generar un cambio en el mundo.</p>
<h3>Re-definiendo Educación Virtual</h3>
<p>Hoy estamos intentando re-definir la educación virtual desde muchos frentes. Universidades tan populares en el mundo como <a href="http://www.stanford.edu/">Stanford</a>, <a href="http://www.harvard.edu/">Harvard</a>, <a href="http://www.yale.edu/">Yale</a>, <a href="http://www.cornell.edu/">Cornell</a>, <a href="http://web.mit.edu/">MIT</a> y demás, están en la apuesta. Queremos entender qué paso con <a href="http://www.ox.ac.uk/">Oxford</a>, <a href="http://www.cam.ac.uk/">Cambridge</a>, <a href="http://www.itesm.edu/wps/portal?WCM_GLOBAL_CONTEXT=">Tec de Monterrey</a>, <a href="http://campusvirtual.ub.edu/">UBVirtual</a>, <a href="http://www.palermo.edu/">Palermo</a>, etc. Más importante aún, en el entorno web surgieron otros nombres en poco tiempo: <a href="http://www.khanacademy.org/">Khan Academy</a>, <a href="http://www.codecademy.com/">Codecademy</a>, <a href="http://udacity.com/">Udacity</a> o <a href="https://www.coursera.org/">Coursera</a>.</p>
<p>¿Saben quiénes están también en la lista sin que muchos se den cuenta? Youtube (y por ende Google), Facebook, Wikipedia, Facebook, LinkedIn (hey, ahora tienen a Slideshare) y nuestras comunidades: <a href="http://www.forosdelweb.com/">Foros del Web</a> y <a href="http://cristalab.com/">Cristalab</a>, también están allí desde hace años.</p>
<p>Re-definamos la educación y lo que pasa en Internet, porque cualquier servicio, espacio digital, comunidad o red social puede potenciarse como plataforma para educar a los demás. Puede utilizarse para educar y mercadearse, sin que el capitalismo de esta estrategia sea mal visto hasta por los más izquierdosos del planeta.</p>
<p>A lo largo de este año, voy a compartir con ustedes un análisis de los servicios, las plataformas, las estrategias y los miles de proyectos que hacen que el llamado mundo de la &#8220;Educación Virtual&#8221; demuestre sus verdaderos colores, esos donde no tenemos aún nada claro, pero muchos estamos invirtiendo tiempo en descubrir o re-descubrir.</p>
<h3>¿Te interesa la educación virtual?</h3>
<p>Si participas en esta industria, si te apasiona el tema, charlemos. Estamos en la búsqueda de ampliar nuestro equipo, estamos en busca de alianzas, queremos críticas sinceras.</p>
<p>Si el mundo digital modificó por completo, sin vuelta atrás, el mundo de la música, el vídeo, el entretenimiento y lo sigue haciendo con el comercio y la creación de empresas de servicios. La educación sigue esperando su momento de gloria, donde esa misma materia digital transmite profesiones universales sin importar las distancias de los grandes maestros e investigadores. Espero me acompañen en la aventura.</p>
<p>En un próximo capítulo de la serie <a href="http://www.maestrosdelweb.com/editorial/khan-academy-educacion-virtual/">exploraremos a Khan Academy</a>. </p>
<hr /><p style="height: 64px;"><div class="entry_author_image"><img src="http://www.maestrosdelweb.com/wp-content/authors/cvander-72.jpg" alt="" style="float:left;padding:0 5px" /></div>
 <strong>Christian Van Der Henst S.</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/re-definiendo-educacion-virtual/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/re-definiendo-educacion-virtual/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/re-definiendo-educacion-virtual/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/wp-content/authors/cvander-72.jpg" />
		<media:content url="http://www.maestrosdelweb.com/wp-content/authors/cvander-72.jpg" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Es viernes: Mejorando.la/conferencia ¿Centroamérica?</title>
		<link>http://www.maestrosdelweb.com/editorial/mejorando-laconferencia-centroamerica/</link>
		<comments>http://www.maestrosdelweb.com/editorial/mejorando-laconferencia-centroamerica/#comments</comments>
		<pubDate>Fri, 18 May 2012 18:09:28 +0000</pubDate>
		<dc:creator>Stephanie Falla Aroche</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Productividad]]></category>
		<category><![CDATA[cursos]]></category>
		<category><![CDATA[es viernes!]]></category>
		<category><![CDATA[evento]]></category>
		<category><![CDATA[mejorandola]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24727</guid>
		<description><![CDATA[Hace unos días comenté en mi cuenta en Twitter (@stephaniefalla) que con el equipo de mejorando.la estábamos contemplando realizar el evento mejorando.la/conferencia que ha tenido mucho éxito en Latinoamérica; hemos transmitido desde sedes como México, Colombia y Chile. Nuestros cursos se han llevado a cabo en México, Costa Rica, Perú, Colombia, Argentina, Chile y próximamente [...]]]></description>
			<content:encoded><![CDATA[<p>Hace unos días comenté en mi cuenta en Twitter (@stephaniefalla) que con el equipo de <a href="http://mejorando.la">mejorando.la</a> estábamos contemplando realizar el evento <a href="http://mejorando.la/conferencia">mejorando.la/conferencia</a> que ha tenido mucho éxito en Latinoamérica; hemos transmitido desde sedes como México, Colombia y Chile. Nuestros cursos se han llevado a cabo en México, Costa Rica, Perú, Colombia, Argentina, Chile y próximamente estaremos en España. Este año queremos que Centroamérica sea nuestra sede y transmitir al mundo lo que está pasando en la región y esperamos contar con tu apoyo.</p>
<p><a href="http://mejorando.la/conferencia"><img src="http://www.maestrosdelweb.com/images/2012/05/mejornadola-conferencia.jpg" alt="Mejorando.la/conferencia" /></a></p>
<p>Organizar un evento en donde tienes conferencistas internacionales, expertos en sus áreas y contenido de gran valor no es tarea fácil. La logística empieza con encontrar una sede accesible para los participantes, entender el mercado, conocer la audiencia y las dinámicas culturales. No es lo mismo organizar un evento en Chile que hacerlo para México. La logística en Argentina es muy diferente de la logística en Colombia. Son muchos los factores que debes contemplar y sobre todo, saber que tu audiencia está interesada y quiere participar.</p>
<h3>¿Qué se necesita para un evento Mejorando.la/conferencia?</h3>
<p>Mejorando.la/conferencia es un evento global, es lo más importante de entender, que la sede esté en tu país no significa que sólo los asistentes de la sede estén presentes en el evento, en realidad en nuestra última transmisión logramos que más de 50 mil personas estuvieran conectadas durante 2 días en la serie de conferencias que preparamos para el evento. Así, que no estamos organizando un evento sólo para las 200 o 500 personas en un salón, estamos organizando un evento para 50 mil personas más fuera de ese salón.</p>
<p><iframe width="640" height="360" src="http://www.youtube.com/embed/x4ZwpiKR7ew" frameborder="0" allowfullscreen></iframe></p>
<p>Sin embargo, que la transmisión sea desde un país o región en específico es una gran oportunidad para que profesionales destacados locales muestren lo que está sucediendo en su país. Además, tendrán la oportunidad de conversar con los conferencistas extranjeros, aprovechar el networking y casi siempre, logramos que los participantes se vayan con premios o regalos de los patrocinadores. Entonces dejenme compartirles las piezas que necesitamos ir armando para lograr que el próximo evento de mejorando.la/conferencia sea transmitido desde Centroamérica para el mundo.</p>
<ul>
<li><strong>Participación:</strong> Es muy importante detectar el interés de la audiencia en el país o región. Saber si el lugar seleccionado permitirá que personas de la región viajen al lugar del evento. Desafortunadamente no podemos estar en todos los países, pero sí podemos escoger una Ciudad que sea accesible a muchos más.</li>
<li><strong>Patrocinadores: </strong>Tenemos diferentes rangos de patrocinadores, como sabrán el traer conferencistas y hospedarlos cuesta dinero. Además, la sede en ocasiones es un patrocinio y en otras ocasiones debemos pagarla, el internet también es un servicio que debe pagarse y no siempre las empresas del país están interesadas en patrocinar con ese servicio. Otros patrocinadores nos dan de sus productos para regalar y otros patrocinan con su servicio.</li>
<li><strong>Conferenciastas:</strong> Debemos seleccionar cuidadosamente a los conferencistas, saber qué temas quiere la audiencia, conocer el mercado y lo que les interesa. Además, cuando pensamos en conferencistas muy populares en el medio, su agenda es complicada y debemos garantizarnos un espacio. En este tipo de conferencias se le cubren todos los gastos al conferencista y eso también cuesta dinero. </li>
<li><strong>Sede/Lugar:</strong> Como les comenté, en ocasiones se patrocina la sede, pero en otras simplemente el mercado no ofrece muchas opciones y debemos acudir a alquilar el lugar. Gestionar sus servicio y costos de todo: sillas, mesas, luz, conexiones y el doloroso servicios de Internet que en Latinoamérica siempre será un tema difícil. </li>
<li><strong>Promoción:</strong> Tenemos nuestros canales en donde informamos sobre nuestras actividades, en ocasiones blogger influyentes del lugar también hacen mención e invitan a participar. Las redes sociales y nuestras cuentas también las usamos para promover. Pero, también hemos tenido patrocinio de medios del país, empresas interesadas en que el evento suene en los medios tradicionales y sabemos que también es importante estar allí. </li>
<li><strong>Staff:</strong> Siempre contamos con el apoyo de la comunidad, personas que llegan y nos ofrecen su tiempo o por lo menos orientarnos de cómo funcionan las cosas en su país. Tener personas locales siempre es de gran ayuda, porque nos gusta entender cómo funcionan los mercados, entenderlos y brindar lo mejor de nuestro trabajo.</li>
</ul>
<p>Parecerá que en estos <strong>6 puntos</strong> son fáciles de lograr, pero debo recordarles que son mucho matices en cada uno de ellos. Traté de simplificar para exponerles nuestro interes por hacer un evento en Centroamérica, pero que sin duda no lo podemos lograr sin la ayuda, el interes y colaboración de ustedes. Si están interesados en hacer que esto sea posible, les pregunto <strong>¿en cuál de estos 6 puntos nos quieren apoyar?</strong> nos interesa sumar esfuerzos y seguir promoviendo la tecnología, el talento y los proyectos que existen en la región hispana para el mundo. Feliz fin de semana. Enjoy!</p>
<hr /><p style="height: 64px;"><img alt='Stephanie Falla Aroche' src='http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Stephanie Falla Aroche</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/mejorando-laconferencia-centroamerica/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/mejorando-laconferencia-centroamerica/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/mejorando-laconferencia-centroamerica/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/mejornadola-conferencia.jpg" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/mejornadola-conferencia.jpg" medium="image">
			<media:title type="html">Mejorando.la/conferencia</media:title>
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Stephanie Falla Aroche</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>GeeksOnAPlane: emprendimientos de Miami y México DF</title>
		<link>http://www.maestrosdelweb.com/actualidad/geeksonaplane-emprendimientos-de-miami-y-mexico-df/</link>
		<comments>http://www.maestrosdelweb.com/actualidad/geeksonaplane-emprendimientos-de-miami-y-mexico-df/#comments</comments>
		<pubDate>Thu, 17 May 2012 14:54:45 +0000</pubDate>
		<dc:creator>Claudio Cossio</dc:creator>
				<category><![CDATA[Actualidad]]></category>
		<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Eventos]]></category>
		<category><![CDATA[emprendimiento]]></category>
		<category><![CDATA[geeks on a plane]]></category>
		<category><![CDATA[geeoksonaplane]]></category>
		<category><![CDATA[miami]]></category>
		<category><![CDATA[startup]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24601</guid>
		<description><![CDATA[No hay mejor manera de abrir este articulo que citando a uno de los emprendedores y organizadores que hicieron que Geeks On A Plane llegara a tierras Aztecas: Lo que esta ahora sucediendo en la casa del Embajador de Estados Unidos en México pasara a la historia como un momento clave para el emprendimiento en [...]]]></description>
			<content:encoded><![CDATA[<p>No hay mejor manera de abrir este articulo que citando a uno de los emprendedores y organizadores que hicieron que <strong>Geeks On A Plane</strong> llegara a tierras Aztecas:</p>
<blockquote><p>Lo que esta ahora sucediendo en la casa del Embajador de Estados Unidos en México pasara a la historia como un momento clave para el emprendimiento en Latino América &#8211; <em>Cesar Salazar &#8211; Cofundador de Mexican.vc</em></p></blockquote>
<p><a href="http://www.maestrosdelweb.com/images/2012/05/photo1.jpg"><img class="alignleft  wp-image-24673" style="border: 5px solid white" src="http://www.maestrosdelweb.com/images/2012/05/photo1-e1337188991392-337x450.jpg" alt="" width="207" height="273" /></a>Estoy completamente de acuerdo con Cesar, pero creo que no solo ha sido ese momento lo que ha marcado un hito en el ecosistema de emprendimiento de América Latina; ha sido el esfuerzo colectivo de todas las diferentes iniciativas de emprendedores de Latino América durante un periodo de 5 años que ha logrado que estemos ahora pasando por una de las mejores etapas en países como México, Chile, Colombia, Argentina y Brasil.</p>
<p>Como todo, no siempre los primeros exploradores han sido los que han recibido el mérito y el reconocimiento que se merecen, estoy hablando de gente como Tomas Pollak, Nicolas Orellana, Leo Prieto, Juan Francisco Diez, Adan Vecindad, Carlos Mondragon, Santiago Siri, Damian Voltes, Ivan Sosa, Juan David Vargas y muchos otros que han tenido éxito en sus emprendimientos, pero a pesar de ello tenemos que reconocer que nunca hemos dejado de ser un &#8220;grupo de geeks&#8221; o &#8220;frikis&#8221; con ganas de cambiar el mundo.</p>
<p>El esfuerzo de plantar la semilla emprendedora esta dando sus frutos con Startups como <a href="welcu.com" target="_blank">Welcu</a>, <a href="http://angel.co/yogome" target="_blank">Yogome</a>, <a href="http://angel.co/fontacto" target="_blank">Fontacto</a>, <a href="http://angel.co/ovia" target="_blank">Ovia</a>, <a href="preyproject.com" target="_blank">PreyProject</a>, <a href="http://frogtek.org/" target="_blank">Frogtek</a> y muchas otras mas que tienen a emprendedores Latino Americanos como fundadores.</p>
<h3>Miami como punta de lanza para conectar con Hispanos en Estados Unidos.</h3>
<p>Quede muy impresionado con la versatilidad de esa ciudad, a pesar de tener la etiqueta de &#8220;turística&#8221;; esta haciendo un esfuerzo para hacer uso de lo mejor que tiene: una conexión con dos mundos dentro de un mismo país &#8211; contacto con la población inmigrante latina y anglosajona de Estados Unidos.</p>
<blockquote><p>Nadie conoce mejor a la población hispana en Estados Unidos  y Latino Americana que la comunidad de Miami &#8211; Adriana Cisneros &#8211; CEO de Corporativo Cisneros.</p></blockquote>
<p>Sin embargo aunque esta ofreciendo muchos incentivos por parte de la Asociación de Empresarios del Condado de Miami y varios grupos de Meetups de Tecnología; no vi un hub de talento para alimentar tu Startup. Esta es una pieza fundamental para cualquier empresa tecnológica pueda crecer en un mercado tan demandante como el de Internet, esto no lo vi reflejado en este viaje; espero en algún momento regresar con mas tiempo para tener esto mas claro.</p>
<p>Definitivamente hay capital en la ciudad, aunque no veo que sea un capital inteligente en el sentido que tenga la experiencia de fondear Startups y entiendan la tolerancia al riesgo que se requiere de un inversor en tecnología. Esto no quiere decir que no se pueda recibir inversión de capital riesgo o algún business ángel, en años venideros aterrizaran muchas empresas Latino Americanas en aquella hermosa ciudad que nos hechiza con sus playas y su ambiente Latino que se respira en cada esquina.</p>
<p>Miami será una excelente opción cuando lleguen a tener suficientes Startups y empresas de tecnología en los alrededores para poder auto-abastecerse para que entre ellas mismas se puedan sustentar; sobre todo la necesidad de talento que requiere un ecosistema de emprendimiento tecnológico.</p>
<h3>StartupWeekend Mexico DF, el pais Azteca despertando el interes de geeks de Silicon Valley.</h3>
<p>Algo que se ha venido trabajando desde el 2009 con el primer evento de emprendimiento en la Ciudad de Mexico por parte de la iniciativa de <a href="http://iweekend.org" target="_blank">iWeekend</a>, varias reuniones de hackers Mexicanos como el <a href="http://superhappydevhouse.org/w/page/16345504/FrontPage" target="_blank">SuperHappyDevHouse</a> y <a href="http://mobilecamp.mx/" target="_blank">MobilecampMX</a>. Ha culminado con 4 eventos de <a href="http://startupweekend.org/" target="_blank">StartupWeekend</a> en México (<a href="http://startupweekendgdl.org/" target="_blank">Guadalajara</a>, <a href="http://aguascalientes.startupweekend.org/" target="_blank">Aguascalientes</a>, <a href="http://morelia.startupweekend.org/" target="_blank">Morelia</a> y <a href="http://tijuana.startupweekend.org/" target="_blank">Tijuana</a>) con rotundo éxito y que se proyecta hacer más de 15 en todo el país.</p>
<p><a href="http://www.maestrosdelweb.com/images/2012/05/Captura-de-pantalla-2012-05-16-a-las-2.13.09-PM.png"><img class="alignleft size-full wp-image-24670" style="border: 5px solid white" src="http://www.maestrosdelweb.com/images/2012/05/Captura-de-pantalla-2012-05-16-a-las-2.13.09-PM.png" alt="" width="140" height="179" /></a>Lo que hace memorable esta tercera edición de México DF sea espectacular, es que tuvo un jurado estelar con figuras como David Weekly, Dave McClure, Allen Taylor, e integrantes de GeeksOnAPlane y mas juzgando a 11 proyectos con un potencial de primer nivel. Se reunieron los líderes de todas la comunidades de tecnología de México desde Guadalajara hasta San Luis Potosí, trajeron a su mejor talento y se vio claro en lo que son los 3 primeros lugares del evento.</p>
<blockquote><p>Estamos buscando proyectos que podamos fusionar con Startups en SiliconValley y el ganador de StartupWeekend tiene muchas sinergias con TaskRabbit una empresa de nuestro portafolio &#8211; Dave McClure hablando de Encarguitos.</p></blockquote>
<p>Con el primer lugar que fue Encarguitos, así como Legal You (2do lugar) se vio claro como se pudo identificar una necesidad a nivel global, poder ejecutar a nivel local y como poderla escalar de manera orgánica. Esa fue la propuesta de valor que tuvo Encarguitos, que merecidamente ganaron en <a href="http://startupweekenddf.com/" target="_blank">StartupWeekend México DF</a>.</p>
<p>Me llamo la atención Instareal que es una app para colocar bienes inmuebles de manera sencilla y sindicalizarlos en varias plataformas de búsqueda de bienes raíces. La mención honorífica de RockMob fue para una app que te ayuda a poder quitar la &#8220;frustración&#8221; de aprender a tocar un instrumento musical y pudieron hacer una demostración en vivo para que alguien pudiera tocar una guitarra.</p>
<h3>Convivencia de emprendedores, hackers e inversores en América Latina.</h3>
<p>Lo mejor que esta haciendo <a href="http://geeksonaplane.com" target="_blank">Geeks On A Plane</a>, es habilitar eventos donde se reúne gente clave de las diferentes comunidades y provoca que puedan establecer una conexión que aunque sea momentánea, tenga el potencial de habilitar futuras conversaciones. Hemos visto eventos como <a href="http://twitter.com/#!/traweln" target="_blank">Traweln</a> y <a href="http://twitter.com/#!/traweln" target="_blank">La Red Innova</a> que han permitido mediante conferencias hacer estas conexiones en Chile y España, con representación por parte de iniciativas Ibéricas como <a href="http://dad.es" target="_blank">Digital Asset Deployment</a> (DAD &#8211; fondo de inversión) y <a href="http://smartup.es" target="_blank">Smartup</a> (firma de marketing digital).</p>
<p>Ya que en un periodo de 10 días sabemos que la intimidad de compartir cuartos de hotel, comidas, cenas, almuerzos y como no, algunas bebidas &#8220;refrescantes&#8221; permitirá generar la confianza necesaria para que se pueda trabajar en futuros proyectos.</p>
<blockquote><p>La confianza que genera un emprendedor en el inversor, es la misma que tiene que generar un fondo de inversión con sus inversores. Es una pieza clave para que cualquier ecosistema de emprendimiento pueda florecer a pesar esta crisis global que se esta viviendo; por eso es clave encontrar a estas &#8220;figuras de confianza&#8221; para crearlo &#8211; Paul Ahlstrom &#8211; fundador de Alta Ventures.</p></blockquote>
<p>Así que no se pierdan lo que se publica diariamente en el hashtag <a href="http://twitter.com/#!/search/%23GOAP" target="_blank">#GOAP</a> en twitter para estar al tanto de lo que acontece en esta gira por Latino America de los <strong>Geeks On A Plane</strong>.</p>
<hr /><p style="height: 64px;"><div class="entry_author_image"><img src="http://www.maestrosdelweb.com/wp-content/authors/360-33.jpg" alt="" style="float:left;padding:0 5px" /></div>
 <strong>Claudio Cossio</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/actualidad/geeksonaplane-emprendimientos-de-miami-y-mexico-df/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/actualidad/geeksonaplane-emprendimientos-de-miami-y-mexico-df/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/actualidad/geeksonaplane-emprendimientos-de-miami-y-mexico-df/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/photo1-e1337188991392-150x150.jpg" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/photo1-e1337188991392.jpg" medium="image">
			<media:title type="html">GeeksOnAPlane</media:title>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/photo1-e1337188991392-150x150.jpg" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/Captura-de-pantalla-2012-05-16-a-las-2.13.09-PM.png" medium="image">
			<media:title type="html">Logo StartupWeekend Mexico DF</media:title>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/Captura-de-pantalla-2012-05-16-a-las-2.13.09-PM-140x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/wp-content/authors/360-33.jpg" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Curso Symfony 2: Instalando Bundles de Terceros</title>
		<link>http://www.maestrosdelweb.com/editorial/curso-symfony2-instlando-bundles-de-terceros/</link>
		<comments>http://www.maestrosdelweb.com/editorial/curso-symfony2-instlando-bundles-de-terceros/#comments</comments>
		<pubDate>Wed, 16 May 2012 14:13:07 +0000</pubDate>
		<dc:creator>Maycol Alvarez</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Behaviors]]></category>
		<category><![CDATA[bundles]]></category>
		<category><![CDATA[capitulo12]]></category>
		<category><![CDATA[curso]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[guia]]></category>
		<category><![CDATA[symfony 2]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=20051</guid>
		<description><![CDATA[En reiteradas ocaciones existe la necesidad de implementar librerías de terceros en nuestros proyectos con el objetivo primordial de aprovecharlas, reutilizar código y mejorar nuestros tiempos de entrega; como ya saben en Symfony 2 todo se distribuye en forma de “Bundles” y las librerías de terceros no son la excepción, además en symfony2bundles.org (actualmente http://knpbundles.com/) [...]]]></description>
			<content:encoded><![CDATA[<p>En reiteradas ocaciones existe la necesidad de implementar librerías de terceros en nuestros proyectos con el objetivo primordial de aprovecharlas, reutilizar código y mejorar nuestros tiempos de entrega; como ya saben en Symfony 2 todo se distribuye en forma de “Bundles” y las librerías de terceros no son la excepción, además en symfony2bundles.org (actualmente <a href="http://knpbundles.com/">http://knpbundles.com/</a>) podrás encontrar miles de bundles que podrías necesitar.</p>
<p>En este capítulo nos concentraremos en la instalación de uno de los Bundles más atractivos para incluir en nuestros proyectos, se trata del <a href="https://github.com/stof/StofDoctrineExtensionsBundle">StofDoctrineExtensionsBundle</a> por Christophe Coevoet el cual hace una implementación del complemento <a href="https://github.com/l3pp4rd/DoctrineExtensions">Doctrine2 behavioral extensions</a> creado por Gediminas Morkevicius, cuyo propósito es proveer de los aclamados Comportamientos (behaviors) de Doctrine; en general explicaremos la configuración de 3 comportamientos ampliamente utilizados, como lo son Timestampable, Sluggable y Loggable, reiteramos que el objetivo del capítulo es la instalación de Bundles de Terceros en Symfony2 y no el de profundizar en todos los comportamientos que provee el StofDoctrineExtensionsBundle.</p>
<h3>Paso 1: Instalando el Bundle</h3>
<p>En Symfony 2 existen varias formas para la instalación de los bundles de terceros, entre ellas (y la más práctica) es la instalación por medio de submodule en GIT, si no sabes que es GIT te recomiendo visitar <a href="http://progit.org/book/es/">http://progit.org/book/es/</a> y tratar de instalarlo en tu sistema.</p>
<p>Comenzamos instalando la librería principal de Doctrine Behavioral Extensions, para ello accedemos a nuestra consola, nos ubicamos en la raíz del proyecto de symfony y ejecutamos:</p>
<div class="codigo">
<pre>~$ git submodule add git://github.com/l3pp4rd/DoctrineExtensions.git vendor/gedmo-doctrine-extensions</pre>
</div>
<div class="tipexperto"><h3>Nota</h3> <div class="tipcont">Si tienes problemas puedes descargar manualmente <a href="https://github.com/l3pp4rd/DoctrineExtensions">el paquete</a>, sólo debes descomprimir su contenido y copiarlo al directorio /ruta_hacia_proyecto/<strong>vendor</strong>/gedmo-doctrine-extensions</div></div>
<p>Ahora si añadimos el StofDoctrineExtensionsBundle:</p>
<div class="codigo">
<pre>~$ git submodule add git://github.com/stof/StofDoctrineExtensionsBundle.git vendor/bundles/Stof/DoctrineExtensionsBundle</pre>
</div>
<div class="tipexperto"><h3>Nota</h3> <div class="tipcont">Si tienes problemas puedes descargar manualmente <a href="https://github.com/stof/StofDoctrineExtensionsBundle">el paquete</a>, sólo debes descomprimir su contenido y copiarlo al directorio /ruta_hacia_proyecto/<strong>vendor/bundles</strong>/Stof/DoctrineExtensionsBundle.</div></div>
<p>Registramos los Namespaces en nuestro app/autoload.php:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

use Symfony\Component\ClassLoader\UniversalClassLoader;
use Doctrine\Common\Annotations\AnnotationRegistry;

$loader = new UniversalClassLoader();
$loader-&gt;registerNamespaces(array(
    'Symfony'          =&gt; array(__DIR__.'/../vendor/symfony/src', __DIR__.'/../vendor/bundles'),
    'Sensio'           =&gt; __DIR__.'/../vendor/bundles',
    'JMS'              =&gt; __DIR__.'/../vendor/bundles',
    'Doctrine\\Common' =&gt; __DIR__.'/../vendor/doctrine-common/lib',
    'Doctrine\\DBAL'   =&gt; __DIR__.'/../vendor/doctrine-dbal/lib',
    'Doctrine'         =&gt; __DIR__.'/../vendor/doctrine/lib',
    'Monolog'          =&gt; __DIR__.'/../vendor/monolog/src',
    'Assetic'          =&gt; __DIR__.'/../vendor/assetic/src',
    'Metadata'         =&gt; __DIR__.'/../vendor/metadata/src',
    // Aquí registramos:
    'Stof'  =&gt; __DIR__.'/../vendor/bundles',
    'Gedmo' =&gt; __DIR__.'/../vendor/gedmo-doctrine-extensions/lib',
));
// ... resto del archivo
</pre>
<p>Añadimos el Bundle a nuestro app/AppKernel.php:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            new Symfony\Bundle\SecurityBundle\SecurityBundle(),
            new Symfony\Bundle\TwigBundle\TwigBundle(),
            new Symfony\Bundle\MonologBundle\MonologBundle(),
            new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
            new Symfony\Bundle\DoctrineBundle\DoctrineBundle(),
            new Symfony\Bundle\AsseticBundle\AsseticBundle(),
            new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
            new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),
            new MDW\BlogBundle\MDWBlogBundle(),
            new MDW\DemoBundle\MDWDemoBundle(),
            // Aquí Añadimos:
            new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),
        );
// ... resto del archivo
</pre>
<p>Básicamente es todo lo que se realiza para incluir un Bundle.</p>
<h3>Paso 2: Configurando el Bundle</h3>
<p>En nuestro caso el <strong>StofDoctrineExtensionsBundle</strong> para funcionar requiere agregar configuración adicional al archivo app/config/<strong>config.yml</strong> de la aplicación (la mayoría de los bundles pueden detallar tales configuraciones en su documentación), para ello agregamos estos segmentos:</p>
<p>En la sección <em>Doctrine Configuration</em>, añadimos al final el mapping para StofDoctrineExtensions Bundle:</p>
<div class="codigo">
<pre># Doctrine Configuration
doctrine:
    dbal:
        driver:   %database_driver%
        host:     %database_host%
        port:     %database_port%
        dbname:   %database_name%
        user:     %database_user%
        password: %database_password%
        charset:  UTF8

    orm:
        auto_generate_proxy_classes: %kernel.debug%
        auto_mapping: true
        # Añadimos el Mapping para StofDoctrineExtensionsBundle: -------------
        mappings:
            StofDoctrineExtensionsBundle: ~
# ... resto del archivo</pre>
</div>
<p>Luego añadimos <em>al final del mismo archivo</em> la siguiente configuración:</p>
<div class="codigo">
<pre># Añadimos las configuraciones específicas para el StofDoctrineExtensionsBundle
stof_doctrine_extensions:
    default_locale: en_US
    orm:
        default:
            sluggable: true
            timestampable: true
            loggable: true
            #demás behaviors para activar</pre>
</div>
<p>Donde <strong>default:</strong> representa la configuración para todos los entornos, eso quiere decir que puedes añadir una configuración específica para cada entorno.</p>
<h3>Paso 3: Utilizando los Comportamientos (Behaviors) en los modelos</h3>
<p>En este tutorial nos concentraremos en los comportamientos sluggable, timestampable y loggable, para hacer las cosas más fáciles se recomienda añadir el siguiente Namespace a cada una de nuestras entidades en donde queramos añadir los comportamientos:</p>
<pre class="brush: php; title: ; notranslate">
// añadimos luego del Namespace de la Entidad:
use Gedmo\Mapping\Annotation as Gedmo;
</pre>
<p>Algunos Behaviors como Loggable disponen de Entidades propias que requieren crearse en base de datos, para garantizar ello solo debemos ejecutar en consola el comando siguiente, de este modo Doctrine creará las tablas necesarias para almacenar los datos generados por los comportamientos que lo requieran:</p>
<div class="codigo">
<pre>~$ php app/console doctrine:schema:update --force</pre>
</div>
<p><strong>Sluggable</strong>: Permite que Doctrine cree automáticamente el “slug” o la típica cadena optimizada para buscadores utilizada comúnmente al indexar artículos de un blog. Para definir el slug debemos tener un <em>campo destino</em> que es donde se almacenará y uno o más <em>campos origen</em> (los Sluggable) de los cuales se construirá el slug y es tan simple como agregar los siguientes <strong>Metadatos</strong> a nuestros campos del modelo:</p>
<pre class="brush: php; title: ; notranslate">
    // … dentro de una Entidad
    // Campo origen:
    /**
     * @var string $title
     *
     * @ORM\Column(name=&quot;title&quot;, type=&quot;string&quot;, length=255)
     * @Gedmo\Sluggable()
     */
    private $title;

    // … otras variables

    // Campo Destino:
    /**
     * @var string $slug
     *
     * @ORM\Column(name=&quot;slug&quot;, type=&quot;string&quot;, length=255)
     * @Gedmo\Slug(style=&quot;camel&quot;, separator=&quot;_&quot;, updatable=false, unique=true)
     */
    private $slug;
    // … dentro de una Entidad
</pre>
<p>Note que el campo desde donde se creará el slug ($title) tiene el Metadato @Gedmo\Sluggable(), de hecho puede definir más de uno. En cambio el campo de destino ($slug) tiene el Metadato @Gedmo\Slug(&#8230;) y por convención debe ser uno solo, los argumentos style, separator, updatable y unique son opcionales y se detallan en la documentación propia del autor, en este ejemplo se tiene una forma básica de configuración.</p>
<p>Cada vez que se cree un registro de la entidad, Doctrine automáticamente generará el slug y lo aplicará al campo destino, en el caso de modificaciones depende del valor del argumento updatable.<br />
<strong></strong></p>
<p><strong>Timestampable:</strong> permite que Doctrine gestione la actualización del Timestamp en campos específicos al realizar operaciones de inserción y/o actualización. Para definir un campo con Timestampable solo debemos añadir el Metadato Gedmo\Timestampable(on=&#8221;action&#8221;), donde <em>action</em> puede ser created o updated respectivamente.</p>
<pre class="brush: php; title: ; notranslate">
    // … dentro de una Entidad
    // Campo created:
    /**
     * @var date $created
     *
     * @ORM\Column(name=&quot;created&quot;, type=&quot;date&quot;)
     * @Gedmo\Timestampable(on=&quot;create&quot;)
     */
    private $created;
    // Campo updated:
    /**
     * @var datetime $updated
     *
     * @ORM\Column(name=&quot;updated&quot;, type=&quot;datetime&quot;)
     * @Gedmo\Timestampable(on=&quot;update&quot;)
     */
    private $updated;
    // … dentro de una Entidad
</pre>
<p>Doctrine automáticamente aplicará un nuevo Date al campo definido on=”create” al crear un nuevo registro de la entidad y actualizará el Timestamp del campo definido on=”update” al actualizar el registro de la entidad.</p>
<p><strong>Loggable</strong>: permite que Doctrine lleve un control de Versiones sobre los campos indicados, permitiendo consultar las versiones y revertir hacia una versión anterior.<br />
Para crear campos con <em>log</em> (control de versión) solo debemos añadir a cada campo el Metadato @Gedmo\Versioned(), además de añadir el Metadato @Gedmo\Loggable() a la Entidad correspondiente:</p>
<pre class="brush: php; title: ; notranslate">
// ... encabezados del archivo
// definimos el Metadato @Gedmo\Loggable() a la Entidad:
/**
 * MDW\BlogBundle\Entity\Articles
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass=&quot;MDW\BlogBundle\Entity\ArticlesRepository&quot;)
 * @Gedmo\Loggable()
 */
class Articles
{
    // … dentro de una Entidad
    // Campo $content será Versionable:
    /**
     * @var text $content
     *
     * @ORM\Column(name=&quot;content&quot;, type=&quot;text&quot;)
     * @Gedmo\Versioned()
     */
    private $content;
    // … demás contenido de la entidad
</pre>
<p>Doctrine automáticamente supervisará los updates hacia los atributos marcados como Versioned de  la entidad y llevará un control de versiones en la Entidad (Stof\DoctrineExtensionsBundle\Entity\LogEntry), y gracias al Repositorio de dicha entidad (\Gedmo\Loggable\Entity\Repository\LogEntryRepository) podremos consultar las Versiones e incluso Revertir los cambios (función $logRepositoryInstance-&gt;revert($Entity, $version);), aquí apreciamos un ejemplo de un controlador que lista los cambios:</p>
<pre class="brush: php; title: ; notranslate">
    // Ejemplo dentro de un Controller:
    public function updateArticleAction($id) {
      $em = $this-&gt;getDoctrine()-&gt;getEntityManager();

      $article = $em-&gt;getRepository('MDWBlogBundle:Articles')-&gt;findOneBy(array('id' =&gt; $id));

      $article-&gt;setContent('editado');
      $em-&gt;persist($article);
      $em-&gt;flush();

      $content = '';
      // ver cambios
      $log = $em-&gt;getRepository('Stof\DoctrineExtensionsBundle\Entity\LogEntry');
      /* @var $log \Gedmo\Loggable\Entity\Repository\LogEntryRepository */

      $query_changues = $log-&gt;getLogEntriesQuery($article); //use $log-&gt;getLogEntries() para un result directo
      $changues = $query_changues-&gt;getResult();
      /* @var $version Stof\DoctrineExtensionsBundle\Entity\LogEntry */
      foreach ($changues as $version) {
        $fields = $version-&gt;getData();
        $content.= ' fecha: ' .
            $version-&gt;getLoggedAt()-&gt;format('d/m/Y H:i:s') .
            ' accion: &quot;'  . $version-&gt;getAction() . '&quot;'.
            ' usuario: &quot;' . $version-&gt;getUsername() . '&quot;'.
            ' objeto: &quot;'  . $version-&gt;getObjectClass() . '&quot;'.
            ' id: &quot;'      . $version-&gt;getObjectId() . '&quot;'.
            ' Version: &quot;' . $version-&gt;getVersion() . '&quot;'.
            ' datos:';
            foreach ($fields as $field =&gt; $value) {
              $content.= &quot;-- &quot; . $field . ': '. $value . '';
            }
      }
      // generamos una salida básica
      $r = new \Symfony\Component\HttpFoundation\Response();
      $r-&gt;setContent($content);
      return $r;
    }
</pre>
<p>De esta forma podemos aprovecharnos de algunos de los comportamientos más utilizados de Doctrine, reutilizar código y automatizar tareas en nuestros modelos.</p>
<h3>Resumen Final</h3>
<p>Como pudimos apreciar con Symfony2 disponemos de una amplia variedad de bundles de terceros a incluir para extender las capacidades de nuestras aplicaciones, aprovechar y reutilizar código mejorando considerablemente el tiempo en el desarrollo de nuestros proyectos; aprendimos que existen diversas formas de incluir nuestros bundles y que en dado caso podemos hacer instalaciones a mano, también de lo importante que es seguir la documentación de cada bundle para agregarlo en el Autoload o Kernel según corresponda y aplicar las configuraciones requeridas por el mismo.</p>
<hr /><p style="height: 64px;"><img alt='Maycol Alvarez' src='http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Maycol Alvarez</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-instlando-bundles-de-terceros/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-instlando-bundles-de-terceros/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/curso-symfony2-instlando-bundles-de-terceros/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:thumbnail url="http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" />
		<media:content url="http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Maycol Alvarez</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Curso Django: El Shell de Django</title>
		<link>http://www.maestrosdelweb.com/editorial/curso-django-el-shell-de-django/</link>
		<comments>http://www.maestrosdelweb.com/editorial/curso-django-el-shell-de-django/#comments</comments>
		<pubDate>Mon, 14 May 2012 17:14:50 +0000</pubDate>
		<dc:creator>Sergio Infante Montero</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[Editorial]]></category>
		<category><![CDATA[curso django]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24410</guid>
		<description><![CDATA[En el capítulo anterior, vimos lo fácil que es crear un modelo con Django, en este capítulo veremos que podemos hacer con los modelos. Si llegaste a este capítulo y no leiste los anteriores, quizas lo encuentres un poco dificil de entender, así que dale un vistazo a los capítulos anteriores. Los modelos nos van [...]]]></description>
			<content:encoded><![CDATA[<p>En el <a href="http://www.maestrosdelweb.com/editorial/curso-django-el-modelo-de-datos/">capítulo anterior</a>, vimos lo fácil que es crear un modelo con Django, en este capítulo veremos que podemos hacer con los modelos. Si llegaste a este capítulo y no leiste los anteriores, quizas lo encuentres un poco dificil de entender, así que dale <a href="http://www.maestrosdelweb.com/guias/#guias-django" title="Curso Django en Maestros del Web">un vistazo a los capítulos anteriores</a>.</p>
<p>Los modelos nos van a permitir manipular los datos: registrarlos, editarlos, actualizarlos, consultarlos, eliminarlos y realizar procesos con ellos. Toda está manipulación se reflejará luego en las vistas y posteriormente en las plantillas para mostrar los resultados en el navegador, esta manipulación se le conoce generalmente como: Consultas.</p>
<h2>El Shell</h2>
<p>El Shell es el interprete interactivo de Python, que nos permitirá probar los modelos, hacer consultas, analizar resultados, antes de elaborar las vistas. Es muy útil si queremos ahorrar tiempo al momento de responder a los requerimientos que los usuarios de la aplicación puedan necesitar.</p>
<p>Para poder acceder a la shell, abrimos una terminal o ventana de comandos, y nos ubicamos en la carpeta de proyecto (en donde se encuentre el archivo manage.py) y digitamos:</p>
<div class="codigo">
<pre>python manage.py shell</pre>
</div>
<p>Debemos visualizar el siguiente resultado:</p>
<div id="attachment_24585" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-inicio.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-inicio-450x82.png" alt="Shell" width="450" height="82" class="size-medium wp-image-24585" /></a><p class="wp-caption-text">Shell</p></div>
<p>Lo importante es reconocer los elementos: <a href="http://es.wikipedia.org/wiki/Prompt" title="Prompt">el prompt</a> se representa por &gt;&gt;&gt; y el resultado de nuestras instrucciones se visualizarán en nuevas líneas (sin ningún símbolo previo a ellas)</p>
<h2>Las consultas</h2>
<p>Las consultas en base a los modelos de Django son la base de todo el desarrollo en este framework estas consultas nos pueden permitir saber, por ejemplo, la lista de usuarios, los correos electronicos de los que hacen comentarios, el primero comentario de un artículo, los artículos del mes de mayo, y la lista de posiblidades es larga.</p>
<p>Las consultas <a href="https://docs.djangoproject.com/en/1.4/topics/db/queries/" title="Consultas en Django">están descritas muy claramente en la documentación oficial</a>, para poder hacer esto más simple aquí también usaremos esta pequeña chuleta o cheat sheet como también es conocido.</p>
<div id="attachment_24589" class="wp-caption aligncenter" style="width: 351px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-queries.pdf" target='_blank'><img src="http://www.maestrosdelweb.com/images/2012/05/django-queries-341x450.jpg" alt="Django Queryset CheatSheet" width="341" height="450" class="size-medium wp-image-24589" /></a><p class="wp-caption-text">Django Queryset CheatSheet</p></div>
<p><a href="https://docs.djangoproject.com/en/1.4/ref/models/querysets/" title="Querysets en Django">La referencia de todos estos métodos</a> se encuentran también en la documentación oficial.</p>
<h2>Ejemplos</h2>
<p>Ahora pasamos a lo divertido, <a href="http://neosergio.github.com/recetario_mdw/" title="Recetario de Maestros del Web">seguimos trabajando con nuestro proyecto de ejemplo</a>, para poder realizar algunos ejemplos tenemos que modificar y corregir el <em>models.py</em> y dejarlo así: (ya no existe el modelo Bebida, ya no es necesario, también se debe eliminar cualquier rastro del modelo Bebida de <em>admin.py</em>)</p>
<div id="attachment_24570" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-models-receta.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-models-receta-450x203.png" alt="models.py" width="450" height="203" class="size-medium wp-image-24570" /></a><p class="wp-caption-text">models.py</p></div>
<p>Una vez que tenemos listo el models.py , reiniciamos el modelo (si no recuerdas como reiniciar revisa el capítulo: <a href="http://www.maestrosdelweb.com/editorial/curso-django-el-modelo-de-datos/" title="El modelo de datos Django">El modelo de datos</a>)</p>
<div class="codigo">
<pre>python manage.py reset principal</pre>
</div>
<p>Una vez con los modelos listos, es hora de probar el interprete interactivo (shell). No olvidar que la siguiente instrucción se debe lanzar desde el directorio donde se encuentra el archivo manage.py</p>
<div class="codigo">
<pre>python manage.py shell</pre>
</div>
<p>Una vez dentro del shell, empezamos a importar los modelos, para ello digitamos</p>
<div class="codigo">
<pre>from principal.models import Receta, Comentario</pre>
</div>
<p>Esta instrucción importa todo el modelo al shell. Aquí es donde podemos consultar el contenido de los modelos y otras consultas, la sintaxis es del tipo:</p>
<div class="codigo">
<pre>Nombre_de_modelo.objects.metodo()</pre>
</div>
<p>Donde podemos reemplazar Nombre_de_modelo y método por las diversas opciones que están en el cheatsheet (chuleta)</p>
<div id="attachment_24571" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-01.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-01-450x113.png" alt="all()" width="450" height="113" class="size-medium wp-image-24571" /></a><p class="wp-caption-text">all()</p></div>
<p>En la imagen vemos como resultado una lista vacia [], entonces vamos a agregar elementos, para ello también necesitamos al modelo usuario que ya lo tiene Django, una vez que lo importamos sacamos al usuario cuya llave primaria (pk) sea 1.</p>
<div id="attachment_24569" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-importar-usuario-shell.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-importar-usuario-shell-450x69.png" alt="User.objects.get(pk=1)" width="450" height="69" class="size-medium wp-image-24569" /></a><p class="wp-caption-text">User.objects.get(pk=1)</p></div>
<p>Ahora si introducimos datos a los modelos: (la r es solo una variable cualquiera)</p>
<div id="attachment_24572" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-02.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-02-450x137.png" alt="create()" width="450" height="137" class="size-medium wp-image-24572" /></a><p class="wp-caption-text">create()</p></div>
<p>Y comprobamos que se ha registrado:</p>
<div id="attachment_24573" class="wp-caption aligncenter" style="width: 263px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-03.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-03.png" alt="Receta.objects.all()" width="253" height="67" class="size-full wp-image-24573" /></a><p class="wp-caption-text">Receta.objects.all()</p></div>
<p>Agregamos un comentario a la receta anterior: (la c es solo una variable cualquiera)</p>
<div id="attachment_24574" class="wp-caption aligncenter" style="width: 393px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-04.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-04.png" alt="create() en Comentario" width="383" height="139" class="size-full wp-image-24574" /></a><p class="wp-caption-text">create() en Comentario</p></div>
<p>Agregamos una receta mas: (Se puede escribir todo en una sola línea, yo lo hago para que se vea bien en la imagen)</p>
<div id="attachment_24575" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-05.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-05-450x182.png" alt="create() podría ir en una sola línea" width="450" height="182" class="size-medium wp-image-24575" /></a><p class="wp-caption-text">create() podría ir en una sola línea</p></div>
<p>Sigamos jugando, ahora mostraremos las recetas cuyos ingredientes no empiecen con la letra A: (notar que luego de ingredientes hay <strong>dos</strong> guiones bajos)</p>
<div id="attachment_24576" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-06.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-06-450x55.png" alt="exclude y startswith" width="450" height="55" class="size-medium wp-image-24576" /></a><p class="wp-caption-text">exclude y startswith</p></div>
<p>Ahora las recetas, que mencionen en su preparación la palabra &#8216;tetera&#8217;:</p>
<div id="attachment_24577" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-07.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-07-450x54.png" alt="filter y contains" width="450" height="54" class="size-medium wp-image-24577" /></a><p class="wp-caption-text">filter y contains</p></div>
<p>Y si queremos ordenar alfabéticamente por titulo de receta:</p>
<div id="attachment_24578" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-08.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-08-450x76.png" alt="order_by()" width="450" height="76" class="size-medium wp-image-24578" /></a><p class="wp-caption-text">order_by()</p></div>
<p>Ahora lo invertimos:</p>
<div id="attachment_24579" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-09.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-09-450x60.png" alt="order_by y reverse" width="450" height="60" class="size-medium wp-image-24579" /></a><p class="wp-caption-text">order_by y reverse</p></div>
<p>Mostramos los comentarios de cada receta:</p>
<div id="attachment_24580" class="wp-caption aligncenter" style="width: 405px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-10.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-10.png" alt="filter()" width="395" height="112" class="size-full wp-image-24580" /></a><p class="wp-caption-text">filter()</p></div>
<p>Ahora me gustaría actualizar el titulo &#8216;Huevo Frito&#8217; a la de &#8216;Huevito Frito&#8217;:</p>
<div id="attachment_24581" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-11.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-11-450x62.png" alt="update()" width="450" height="62" class="size-medium wp-image-24581" /></a><p class="wp-caption-text">update()</p></div>
<p>Sigo agregando comentarios a la primera receta y deseo saber cuantos comentarios hay hasta el momento en ambas recetas:</p>
<div id="attachment_24582" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-12.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-12-450x168.png" alt="count()" width="450" height="168" class="size-medium wp-image-24582" /></a><p class="wp-caption-text">count()</p></div>
<p>Agrego un comentario a la segunda receta (un comentario troll) y luego lo elimino:</p>
<div id="attachment_24583" class="wp-caption aligncenter" style="width: 404px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-13.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-13.png" alt="delete()" width="394" height="196" class="size-full wp-image-24583" /></a><p class="wp-caption-text">delete()</p></div>
<p>Ahora deseo saber el nombre de usuario y correo electrónico del usuario que agregó la receta con el título exacto de &#8216;Agua hervida&#8217;:</p>
<div id="attachment_24584" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-14.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-14-450x79.png" alt="Todo está orientado a objetos" width="450" height="79" class="size-medium wp-image-24584" /></a><p class="wp-caption-text">Todo está orientado a objetos</p></div>
<p>Como verán hacer consultas en Django es simple, sin embargo <a href="https://docs.djangoproject.com/en/dev/ref/models/querysets/" title="Django QuerySet API Reference">siempre es bueno tener la documentación a la mano</a>, ya que recordar tantos métodos puede ser tedioso al principio.</p>
<div class='tipexperto'>
<h4>Nota:</h4>
<div class='tipcont'>Las consultas que se realizan en el Shell no se guardan en el proyecto, es por ello que si <a href="http://neosergio.github.com/recetario_mdw/">revisan el repositorio del proyecto de ejemplo</a>, sólo encontraran cambios en models.py y admin.py (retirando la clase Bebida, que ya no es necesaria)</div>
</div>
<p>Las consultas son el paso previo a trabajar con las vistas y las plantillas, nos permitirán entregar a los usuarios del proyecto, la información que requieran. El próximo capítulo será: Las vistas.</p>
<p>Práctica tus propias consultas, juega con los modelos, diviértete, que el momento de aplicarlas serán en el próximo capítulo.</p>
<hr /><p style="height: 64px;"><img alt='Sergio Infante Montero' src='http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Sergio Infante Montero</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/curso-django-el-shell-de-django/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/curso-django-el-shell-de-django/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/curso-django-el-shell-de-django/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-inicio-150x129.png" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-inicio.png" medium="image">
			<media:title type="html">django-shell-inicio</media:title>
			<media:description type="html">Shell</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-inicio-150x129.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-queries.jpg" medium="image">
			<media:title type="html">Django Queryset CheatSheet</media:title>
			<media:description type="html">Django Queryset CheatSheet</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-queries-150x150.jpg" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-models-receta.png" medium="image">
			<media:title type="html">models.py</media:title>
			<media:description type="html">models.py</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-models-receta-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-01.png" medium="image">
			<media:title type="html">all()</media:title>
			<media:description type="html">all()</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-01-150x129.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-importar-usuario-shell.png" medium="image">
			<media:title type="html">User.objects.get(pk=1)</media:title>
			<media:description type="html">User.objects.get(pk=1)</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-importar-usuario-shell-150x74.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-02.png" medium="image">
			<media:title type="html">create()</media:title>
			<media:description type="html">create()</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-02-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-03.png" medium="image">
			<media:title type="html">Receta.objects.all()</media:title>
			<media:description type="html">Receta.objects.all()</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-03-150x67.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-04.png" medium="image">
			<media:title type="html">create() en Comentario</media:title>
			<media:description type="html">create() en Comentario</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-04-150x139.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-05.png" medium="image">
			<media:title type="html">create() podría ir en una sola línea</media:title>
			<media:description type="html">create() podría ir en una sola línea</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-05-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-06.png" medium="image">
			<media:title type="html">exclude y startswith</media:title>
			<media:description type="html">exclude y startswith</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-06-150x69.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-07.png" medium="image">
			<media:title type="html">filter y contains</media:title>
			<media:description type="html">filter y contains</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-07-150x69.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-08.png" medium="image">
			<media:title type="html">order_by()</media:title>
			<media:description type="html">order_by()</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-08-150x80.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-09.png" medium="image">
			<media:title type="html">order_by y reverse</media:title>
			<media:description type="html">order_by y reverse</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-09-150x71.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-10.png" medium="image">
			<media:title type="html">filter()</media:title>
			<media:description type="html">filter()</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-10-150x112.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-11.png" medium="image">
			<media:title type="html">update()</media:title>
			<media:description type="html">update()</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-11-150x110.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-12.png" medium="image">
			<media:title type="html">count()</media:title>
			<media:description type="html">count()</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-12-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-13.png" medium="image">
			<media:title type="html">delete()</media:title>
			<media:description type="html">delete()</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-13-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-14.png" medium="image">
			<media:title type="html">Todo está orientado a objetos</media:title>
			<media:description type="html">Todo está orientado a objetos</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-shell-ejemplo-14-150x110.png" />
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Sergio Infante Montero</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Es viernes: Diseña tu portafolio de trabajos</title>
		<link>http://www.maestrosdelweb.com/editorial/disena-tu-portafolio-de-trabajos/</link>
		<comments>http://www.maestrosdelweb.com/editorial/disena-tu-portafolio-de-trabajos/#comments</comments>
		<pubDate>Fri, 11 May 2012 17:32:20 +0000</pubDate>
		<dc:creator>Stephanie Falla Aroche</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Productividad]]></category>
		<category><![CDATA[es viernes!]]></category>
		<category><![CDATA[Freelancer]]></category>
		<category><![CDATA[Portafolio]]></category>
		<category><![CDATA[redes sociales]]></category>
		<category><![CDATA[reputación digital]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24506</guid>
		<description><![CDATA[El portafolio en línea es la mejor forma de mostrarle al mundo tu conocimiento, lo que te apasiona y de lo que eres capaz. Sin embargo, muchos diseñadores, desarrolladores y freelancer al momento de preguntarles sobre su portafolio de trabajo, tienen excusas relacionadas con la falta de tiempo, el exceso de trabajo o incluso muchos [...]]]></description>
			<content:encoded><![CDATA[<p>El <strong>portafolio en línea</strong> es la mejor forma de mostrarle al mundo tu conocimiento, lo que te apasiona y de lo que eres capaz. Sin embargo, muchos diseñadores, desarrolladores y freelancer al momento de preguntarles sobre su portafolio de trabajo, tienen excusas relacionadas con la falta de tiempo, el exceso de trabajo o incluso muchos consideran que no es necesario tenerlo. En la siguiente conferencia sobre <strong>&#8220;Publica tu pasión al mundo&#8221;</strong> compartí algunas referencias de portafolios en la web y los aspectos básicos que debe contemplar un portafolio.</p>
<p><iframe width="560" height="315" src="http://www.youtube.com/embed/OUFsNh0i13o" frameborder="0" allowfullscreen></iframe></p>
<p>Insisto en el tema porque recibo mensajes en redes sociales y correos en donde muchas personas quieren conversar sobre trabajo o sus proyectos pero no tienen un enlace que me brinde toda la información. En este mundo tan conectado la mejor forma de comunicarnos es a través de la síntesis de ideas, claras y puntuales que brinden el mensaje adecuado. <strong>Tu portafolio en línea es la mejora carta de presentación profesional</strong>, tu reputación digital es tan valiosa como tu reputación profesional y las referencias de trabajo.</p>
<h3>El portafolio y la reputación digital</h3>
<p><img src="http://www.maestrosdelweb.com/images/2008/12/promover-redes.jpg" alt="El portafolio y la reputación digital" style="float:right;padding:5px" />En el mundo web el portafolio y la proyección en las rede sociales es fundamental, debido a que es muy sencillo escribir tu nombre en un buscador, hacernos una idea de tu trabajo y del tipo de persona que eres. Al inicio, la gente creía que en Internet era libre y anónimo con el tiempo las redes sociales nos volvieron más visibles con nombre y apellido de tal forma que hemos construido a lo largo de nuestras cuentas una reputación digital. </p>
<ul>
<li><a href="http://www.maestrosdelweb.com/editorial/%C2%BFtienes-tu-portafolio-en-la-web/">¿Tienes tu portafolio en la web?</a> Conoce las razones por las que un portafolio en línea es indispensable para todo freelancer e inspirate en una serie de referencias. </li>
<li><a href="http://www.maestrosdelweb.com/editorial/es-viernes-freelance-proyeccion-en-redes-sociales/">La proyección en redes sociales:</a> Todo comentario, aporte o publicación en la web con tu nombre o nickname se encuentra registrado en los buscadores. Tus cuentas en redes sociales son parte de tu identidad digital y por ello debes comprender cuál es la mejor forma de proyectarse.</li>
<li><a href="http://www.maestrosdelweb.com/editorial/tips-para-promover-tu-trabajo-en-la-web/">Tips para promover tu trabajo en la web:</a> En otra ocasión compartí sobre la importancia del portafolio y las redes sociales para promover tu trabajo. Pero, también existen algunos tips que expertos en el medio nos han aportado para implementar como el regalar algo a la comunidad.</li>
<li><a href="http://www.maestrosdelweb.com/editorial/creativos-y-hermosos-portafolios/">Inspírate y diseña tu portafolio:</a> Nunca está de más tener referencias del trabajo de otros, ver cómo lo han logrado los demás y revisar estás fuentes puede ser el primer paso para saber por dónde empezar nuestro proyecto de portafolio de evidencias.</li>
</ul>
<h3>Más portafolios de inspiración</h3>
<ul>
<li><a href="http://www.wellsriley.com/">Wellsriley.com</a>: Wells Rilley, diseñador de experiencias. En su portafolio hace uso de tecnologías, diseño, con información clara y puntual. </li>
<li><a href="http://www.lahive.co.uk/about/">Lahive.co.uk</a>: Steve, diseñador y de una forma muy minimalista nos muestra su trabajo y la información de contacto. </li>
<li><a href="http://attackemart.in/">Attackemart.in</a>: Martin Gaue, con su portafolio simplemente nos hace vivir una experiencia del uso de tecnologías y nos despierta la curiosidad. </li>
<li><a href="http://www.stedesign.com/">Stedesign.com:</a> Muestra de un portafolio en una sola página, algo que se está poniendo muy de moda y que ahorra una serie de navegación y links.</li>
</ul>
<p><a href="http://www.Attackemart.in"><img src="http://www.maestrosdelweb.com/images/2012/05/portafolio-android.png" alt="Portafolio" /></a></p>
<p>Debemos superar el curriculum vitae e incursionar en el portafolio de evidencias de nuestra experiencia y capacidad. El conocimiento aplicado, sin duda resulta más atractivo en esta industria en donde necesitamos obtener resultados y menos procesos teóricos para ejecutar proyectos, realizar innovación y ser cada vez más competitivos en el medio. Si aún no tienes un portafolio <strong>hoy es un buen momento para inspirarte y empezar un nuevo proyecto</strong>, que con el tiempo, tendrá sus beneficios y será más práctico al momento de presentarte como freelancer. Feliz fin de semana. Enjoy!</p>
<hr /><p style="height: 64px;"><img alt='Stephanie Falla Aroche' src='http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Stephanie Falla Aroche</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/disena-tu-portafolio-de-trabajos/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/disena-tu-portafolio-de-trabajos/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/disena-tu-portafolio-de-trabajos/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2008/12/promover-redes.jpg" />
		<media:content url="http://www.maestrosdelweb.com/images/2008/12/promover-redes.jpg" medium="image">
			<media:title type="html">El portafolio y la reputación digital</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/portafolio-android.png" medium="image">
			<media:title type="html">Portafolio</media:title>
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Stephanie Falla Aroche</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Curso Symfony 2: Integrando jQuery</title>
		<link>http://www.maestrosdelweb.com/editorial/curso-symfony-2-integrando-jquery/</link>
		<comments>http://www.maestrosdelweb.com/editorial/curso-symfony-2-integrando-jquery/#comments</comments>
		<pubDate>Wed, 09 May 2012 07:00:25 +0000</pubDate>
		<dc:creator>Maycol Alvarez</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[curso]]></category>
		<category><![CDATA[ejemplos]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[symfony2]]></category>
		<category><![CDATA[vistas]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24420</guid>
		<description><![CDATA[En esta ocasión y motivado a sus peticiones con respecto al capítulo &#8220;Integrando AJAX&#8221; les traemos 2 ejemplos, elaborados con la participación de Juan Ardissone y mi persona, con el objetivo de aclarar sus dudas con respecto al manejo de AJAX en Symfony2 y darles ejemplos prácticos de su uso. Como mencioné anteriormente Symfony2 es [...]]]></description>
			<content:encoded><![CDATA[<p>En esta ocasión y motivado a sus peticiones con respecto al capítulo &#8220;<a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-integrando-ajax/">Integrando AJAX</a>&#8221; les traemos 2 ejemplos, elaborados con la participación de <a href="http://www.maestrosdelweb.com/author/jardissone/">Juan Ardissone</a> y mi persona, con el objetivo de aclarar sus dudas con respecto al manejo de AJAX en Symfony2 y darles ejemplos prácticos de su uso.</p>
<p>Como mencioné anteriormente Symfony2 es un Framework PHP orientado al desarrollo en el servidor, por su parte AJAX es una técnica que se implementa desde el JavaScript (JS) cliente, cuyo único objetivo es realizar las peticiones HTTP desde JavaScript y obtener la respuesta para manipularla directamente, sea añadiéndola al DOM o lo que quieras con JavaScript, por lo cual en dicho caso tanto Symfony2 como PHP sólo pueden detectar si la petición fue realizada por dicha técnica, razón por la cual su implementación es realmente simple; también aclaramos que desde su versión 1.3 el proyecto Symfony ha optado por no apoyar ni integrar ningún Framework JS, debido a que ello queda a elección del programador.</p>
<p>En esta continuación del capítulo anterior elegimos a jQuery como el Framework JS a utilizar para los ejemplos, por ser uno de los más populares y fáciles de implementar, reiteramos que puedes usar el FW JS que desees y queda bajo tu absoluta elección, además aclaro que los ejemplos se concentran en el uso de AJAX con jQuery y que para conservar la facilidad con la que implementen los ejemplos no se usaron modelos reales de doctrine, en su caso arrays multidimensionales, si quieren complementarlos con Doctrine, pueden consultar su capítulo: <a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-configurando-bases-de-datos/">Configurando nuestra Base de Datos</a>.</p>
<h3>Ejemplo 1: Ejecutando una llamada ajax con jQuery</h3>
<p>Descargamos el script de la página de jQuery y la guardamos en el directorio web\js\. Para este caso la versión actual es jquery-1.7.2.min.js.</p>
<p>Importamos el archivo dentro del template base que se encuentra en app\Resources\views\base.html.twig:</p>
<div class="codigo">
<pre>&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
        &lt;title&gt;{% block title %}Welcome!{% endblock %}&lt;/title&gt;
        {% block stylesheets %}{% endblock %}
        &lt;link rel="shortcut icon" href="{{ asset('favicon.ico') }}" /&gt;
                &lt;script src="{{ asset('js/jquery-1.7.2.min.js') }}"&gt;&lt;/script&gt;
    &lt;/head&gt;
    &lt;body&gt;
        {% block body %}{% endblock %}
        {% block javascripts %}{% endblock %}
    &lt;/body&gt;
&lt;/html&gt;</pre>
</div>
<p>Con esto ya tenemos el soporte para jQuery en todas nuestras páginas que hereden mediante Twig a este template.</p>
<p>Ya teníamos la página http://localhost/Symfony/web/app_dev.php/articulos/listar que nos mostraba una lista de artículos de la base de datos por lo que podemos hacer otra que simplemente llame por ajax a esta página y muestre los artículos. Para esto creamos la página ver-articulos que simplemente tendrá una link para cargar por ajax el contenido de la página que contiene la lista de artículos. Como cada vez que necesitamos crear una página hacemos los 3 pasos:</p>
<p><strong>CREAMOS LA RUTA</strong></p>
<p>Agregamos a nuestro archivo routing.yml las siguientes líneas para crear la nueva ruta:</p>
<div class="codigo">
<pre>ver_articulos:
    pattern:  /ver-articulos
    defaults: { _controller: MDWDemoBundle:Articulos:verArticulos }</pre>
</div>
<p><strong>CREAMOS EL ACTION</strong></p>
<div class="codigo">
<pre>//Dentro del controlador src\MDW\DemoBundle\Controller\ArticulosController.php agregamos el siguiente action
public function verArticulosAction()
{
        return $this-&gt;render('MDWDemoBundle:Articulos:ver_articulos.html.twig', array());
}</pre>
</div>
<p>Como podemos ver lo único que hace es llamar a la vista que creamos a continuación.</p>
<p><strong>CREAMOS LA VISTA</strong></p>
<p>Creamos el archivo ver_articulos.html.twig dentro de la carpeta src\MDW\DemoBundle\Resources\views\Articulos</p>
<div class="codigo">
<pre>{% extends '::base.html.twig' %}

{% block title %}Symfony - AJAX{% endblock %}

{% block body %}

&lt;div id="articulos"&gt;&lt;/div&gt;
&lt;a id="link_articulos" href="#"&gt;Cargar articulos&lt;/a&gt;

{% endblock %}

{% block javascripts %}
&lt;script&gt;

$(document).ready(function(){
        $('#link_articulos').click(function(){
                $('#articulos').load('{{ path('articulo_listar') }}');
        });
});

&lt;/script&gt;
{% endblock %}</pre>
</div>
<p>En esta página hemos heredado el contenido de template base con el extend y hemos incluído los bloques. Vemos que en el body lo único que tenemos es un div vacío con id &#8220;articulos&#8221; y link con id &#8220;link_articulos&#8221; para obtenerlo utilizamos jQuery. La idea es que al ingresar a la página solo nos muestre el link y no así los artículos. Al dar click sobre el link &#8220;Cargar Artículos&#8221; se ejecutará una llamada ajax mediante jQuery y cargaremos asincrónicamente la ruta {{ path(&#8216;articulo_listar&#8217;) }} que sería la página que ya tenemos lista y que vimos en el <a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-manipulando-datos-con-doctrine/">capítulo 9 &#8211; Manipulando datos con Doctrine</a>.</p>
<p>Entendamos el código jQuery:</p>
<div class="codigo">
<pre>&lt;script&gt;

$(document).ready(function(){
        $('#link_articulos').click(function(){
                $('#articulos').load('{{ path('articulo_listar') }}');
        });
});

&lt;/script&gt;</pre>
</div>
<p>Primeramente registramos el evento ready para que ejecute la función anónima una vez que todo el DOM sea cargado.</p>
<p>Una vez ejecutado el evento ready, agregamos una acción al evento click de nuestro link que ejecutará la función que carga la segunda página:</p>
<div class="codigo">
<pre>$('#link_articulos').click(function(){
        $('#articulos').load('{{ path('articulo_listar') }}');
});</pre>
</div>
<p>La función load() de jQuery se ejectua sobre el div vacío para que el resultado de la respuesta Ajax se cargue dentro de este div y como argumento del método pasamos la dirección en donde, para no escribir la URL a mano, usamos la función Twig {{ path(&#8216;articulo_listar&#8217;) }} para que los genere la ruta relativa de la ruta articulo_listar.</p>
<p>Con esto ya podemos acceder a la página http://localhost/Symfony/web/app_dev.php/ver-articulos donde veremos un link &#8220;Cargar artículos&#8221;. Presionando el link veremos como se obtiene, sin recargar la página, el listado de artículos de la base de datos.</p>
<h3>Ejemplo 2: Gestionando llamadas AJAX con jQuery, Twig y herencia en 3 niveles</h3>
<p>En el ejemplo anterior apreciamos lo sencillo que es implementar una llamada AJAX por medio del FW jQuery y comprendimos que en realidad Symfony2 interviene prácticamente en nada porque su alcance se limita al desarrollo del lado del servidor, en este ejemplo práctico haremos uso de las facilidades que brinda Symfony para detectar peticiones AJAX y modificar la respuesta en función de las necesidades.</p>
<p>Para este ejemplo crearemos una sección o módulo de noticias, en donde nos aparece un listado principal de noticias de las cuales al hacer click nos redirigirá al detalle de la noticia como tal. La idea es conservar un enlace directo a cada noticia, con el cual un motor de búsqueda pueda indexar y a su vez cargar el detalle de la noticia en una capa por medio de AJAX (con load jQuery) con el objetivo de que el usuario pueda cargar las noticias sin recargar la página y si en caso llega desde un buscador pueda apreciar la noticia y el resto de contenidos que ofrezca nuestro layout principal.</p>
<p>Para ello creamos primero nuestro layout:</p>
<div class="codigo">
<pre>{# /src/MDW/DemoBundle/views/layout.html.twig #}
{% extends '::base.html.twig'  %} {# extendemos del layout por defecto #}

{% block javascripts %}
{# añadimos la CDN de jQuery o en su defecto lo descargamos e incluimos con:
&lt;script src="{{ asset('js/jquery-1.7.2.min.js') }}"&gt;&lt;/script&gt;
 #}
&lt;script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"&gt;&lt;/script&gt;
{% endblock javascripts %}

{# creamos una estructura para el layout general #}
{% block body %}
&lt;div&gt;
    &lt;h1&gt;*** Web de Noticias ***&lt;/h1&gt;
    {# según el patrón de 3 niveles, creamos el bloque de contenido #}
    {% block content %}{% endblock content %}
&lt;/div&gt;
{% endblock body%}</pre>
</div>
<p>Procedemos ahora a crear las rutas hacia nuestro controlador, abre el src/MDW/DemoBundle/Resources/config/routing.yml y agrega:</p>
<div class="codigo">
<pre># /src/MDW/DemoBundle/Resources/config/routing.yml

MDWDemoBundle_noticias:
    pattern:  /noticias
    defaults: { _controller: MDWDemoBundle:Notice:index }

MDWDemoBundle_noticeView:
    pattern:  /leerNoticia/{notice_id}
    defaults: { _controller: MDWDemoBundle:Notice:noticeView }</pre>
</div>
<p>Procedemos ahora a crear el controlador, en este ejemplo utilizaremos como Modelo un array de noticias, para enfocarnos en el uso de AJAX:</p>
<div class="codigo">
<pre>&lt;?php
// src/MDW/DemoBundle/Controller/NoticeController.php
namespace MDW\DemoBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class NoticeController extends Controller
{
    // tenemos un array con los datos básicos
    private $array_notice = array(
        array(
            'title' =&gt; 'Titulo de noticia 0',
            'content' =&gt; 'Contenido de noticia 0'
        ),
        array(
            'title' =&gt; 'Titulo de noticia 1',
            'content' =&gt; 'Contenido de noticia 1'
        ),
    );    

    public function indexAction()
    {
        // suponiendo que obtenemos del modelo el listado de noticias
        return $this-&gt;render('MDWDemoBundle:Notice:index.html.twig', array(
            'notices' =&gt; $this-&gt;array_notice
        ));
    }

    public function noticeViewAction($notice_id)
    {
        //obtenemos la noticia del modelo, en este ejemplo proviene de un array
        $notice = $this-&gt;array_notice[$notice_id];
        return $this-&gt;render('MDWDemoBundle:Notice:noticeView.html.twig', array(
            'notice' =&gt; $notice
        ));
    }
}</pre>
</div>
<p>Procedemos ahora a crear las vistas principales:</p>
<div class="codigo">
<pre>{# src/MDW/DemoBundle/Resources/views/Notice/index.html.twig #}

{% extends 'MDWDemoBundle::layout.html.twig'  %}
{% block content %}
&lt;div&gt;
    &lt;p&gt;Noticias recientes&lt;/p&gt;
    &lt;ol&gt;
        {% for index,notice in notices %}
        &lt;li&gt;&lt;a href="{{ path('MDWDemoBundle_noticeView', {'notice_id': index}) }}"&gt;{{notice.title}}&lt;/a&gt;&lt;/li&gt;
        {% endfor %}
    &lt;/ol&gt;
    &lt;div id="notice_viewer"&gt;
    {# en esta capa serán cargadas las noticias por ajax #}
    &lt;/div&gt;
&lt;/div&gt;
{% endblock content %}

{# extendemos el bloque javascript #}
{% block javascripts %}
{{parent()}} {# incluimos las declaraciones de script del layout, como jQuery #}

&lt;script type="text/javascript"&gt;
{# añadirmos una función al evento click de todos los enlaces a.notice_link, para
usar AJAX en vez de su comportamiento por defecto #}
$(document).ready(function(){
    $('a.notice_link').click(function(event){
        event.preventDefault(); //cancela el comportamiento por defecto
        $('#notice_viewer').load($(this).attr('href')); //carga por ajax a la capa "notice_viewer"
    });
});
&lt;/script&gt;
{% endblock javascripts %}</pre>
</div>
<p>Como puede notar en index.html.twig se ha extendido el bloque JavaScript para añadir la carga por medio de jQuery.load (AJAX) hacia la capa DIV “notice_viewer”, esto con el objetivo de que si un buscador indexa nuestra página pueda hallar los links íntegros de las noticias sin afectar al SEO, además de que nos permite cargar por AJAX el contenido de nuestras noticias directamente en la capa asignada.</p>
<div class="codigo">
<pre>{# src/MDW/DemoBundle/Resources/views/Notice/noticeView.html.twig #}

{# note que en este caso utilizamos el layout de ajax para así no cargar todo el contenido del layout general #}
{% extends app.request.isXmlHttpRequest ? "MDWDemoBundle::layout_ajax.html.twig" : "MDWDemoBundle::layout.html.twig" %}
{% block content %}
&lt;div&gt;
    &lt;h2&gt;{{notice.title}}&lt;/h2&gt;
    &lt;p&gt;{{notice.content}}&lt;/p&gt;
&lt;/div&gt;
{% endblock content %}</pre>
</div>
<p>Como puede apreciar ahora en noticeView.html.twig se hace una bifurcación de los layouts para cuando se trata de una petición AJAX, en la cual se utiliza el layout principal cuando el enlace es accedido directamente (origen de un buscador, o de un usuario con Javascript desactivado) y al contrario si proviene de AJAX se utiliza un layout especial:</p>
<div class="codigo">
<pre>{# /src/MDW/DemoBundle/views/layout_ajax.html.twig #}

{# como puede apreciar, el layout para ajax sólo debe incluir el bloque contenido,
adicionalmente podemos añadir extras #}
&lt;div&gt;
    &lt;strong&gt;Visor de Noticias&lt;/strong&gt;
    {% block content %}{% endblock content %}
&lt;/div&gt;</pre>
</div>
<p>De esta forma con Symfony podemos adaptar las respuestas en función de si la petición es AJAX o no, y en este caso devolver sólo el contenido necesario, debido a que en una petición AJAX no es necesario devolver la estructura completa HTML como en una petición normal, sino el fragmento de código que nos interesa.</p>
<h3>CONCLUSIÓN</h3>
<p>Como bien se explica más arriba, las interacciones Ajax no son parte del framework Symfony ya que para esto usamos JavaScript mientras que Symfony es un framework PHP. Existiendo tantas librerías bien robustas para manejo de Ajax como por ejemplo jQuery, incluímos la que más nos guste y ejecutamos la llamada al ajax. La manera de trabajar con librerías JavaScript en Symfony es simplemente incluírlo como un asset de la misma forma que trabajaríamos con las librerías http://www.tinymce.com o http://lightbox.com. Incluímos el archivo y la programación que hacemos para usarla ya es JavaScript y no PHP.</p>
<hr /><p style="height: 64px;"><img alt='Maycol Alvarez' src='http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Maycol Alvarez</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/curso-symfony-2-integrando-jquery/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/curso-symfony-2-integrando-jquery/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/curso-symfony-2-integrando-jquery/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
	
		<media:thumbnail url="http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" />
		<media:content url="http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Maycol Alvarez</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Curso Django: El modelo de datos</title>
		<link>http://www.maestrosdelweb.com/editorial/curso-django-el-modelo-de-datos/</link>
		<comments>http://www.maestrosdelweb.com/editorial/curso-django-el-modelo-de-datos/#comments</comments>
		<pubDate>Mon, 07 May 2012 13:28:51 +0000</pubDate>
		<dc:creator>Sergio Infante Montero</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[Editorial]]></category>
		<category><![CDATA[curso django]]></category>
		<category><![CDATA[datos]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[guia python]]></category>
		<category><![CDATA[modelo]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24336</guid>
		<description><![CDATA[Una vez que ya tenemos instalado Django, creado nuestro primer proyecto y haber revisado como funciona, necesitamos definir el modelo de datos para nuestra aplicación. El Modelo Un modelo es la representación de los datos de nuestra aplicación. Contiene los campos básicos y el comportamiento de los datos que serán almacenados. Por lo general, cada [...]]]></description>
			<content:encoded><![CDATA[<p>Una vez que ya tenemos <a href="http://www.maestrosdelweb.com/editorial/curso-django-instalacion-y-primera-aplicacion/" title="Instalación y primera aplicación Django">instalado Django, creado nuestro primer proyecto</a> y <a href="http://www.maestrosdelweb.com/editorial/curso-django-entendiendo-como-trabaja-django/" title="Entendiendo Django">haber revisado como funciona</a>, necesitamos definir el modelo de datos para nuestra aplicación.</p>
<h2>El Modelo</h2>
<p>Un modelo es la representación de los datos de nuestra aplicación. Contiene los campos básicos y el comportamiento de los datos que serán almacenados. Por lo general, cada modelo se convierte en una tabla de la base de datos.</p>
<h3>Lo fundamental</h3>
<ul>
<li>Cada modelo es una subclase de <strong>django.db.models.Model.</strong></li>
<li>Cada atributo de un modelo representa a un campo de una tabla.</li>
<li>Django automáticamente nos da acceso a la base de datos.</li>
</ul>
<h3>Referencia de los campos</h3>
<p>La referencia de la versión actual esta detallada por completo <a href="https://docs.djangoproject.com/en/1.4/ref/models/fields/" title="Referencia del Modelo en Django">en la documentación del framework</a>, con este recurso podemos elaborar todas las referencias necesarias para el proyecto, sin embargo leerlo por completo puede resultar al principio un poco tedioso.</p>
<p>Para ello siempre es muy útil un cheatsheet o chuleta para poder visualizarlos juntos.</p>
<div id="attachment_24371" class="wp-caption aligncenter" style="width: 328px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-models.jpg" target='_blank'><img src="http://www.maestrosdelweb.com/images/2012/05/django-models-318x450.jpg" alt="Chuleta - Modelos en Django" width="318" height="450" class="size-medium wp-image-24371" /></a><p class="wp-caption-text">Chuleta - Modelos en Django</p></div>
<h3>Ejemplo de modelo en nuestro proyecto</h3>
<p>Vamos con el ejemplo del capítulo para poder entender mejor como va esto del modelo. </p>
<div class="tipexperto">
<h4>Nota</h4>
<div class="tipcont">Para poder continuar con este ejemplo, tienen que seguir el curso desde el primer capítulo y evitar solamente copiar y pegar, escribanlo que es mejor en todo sentido.</div>
</div>
<p>Nuestro archivo: <strong>models.py</strong> de la semana pasada quedó así:</p>
<div class="codigo">
<pre>
from django.db import models

class Bebida(models.Model):
	nombre = models.CharField(max_length=50)
	ingredientes = models.TextField()
	preparacion = models.TextField()

	def __unicode__(self):
		return self.nombre
</pre>
</div>
<p>Este modelo solo fue un ejemplo para saber cómo funcionaba, ahora redactaré algunas líneas que nos ayudarán a tener un modelo más completo:</p>
<div class="codigo">
<pre>
#encoding:utf-8
from django.db import models
from django.contrib.auth.models import User

class Bebida(models.Model):
  nombre = models.CharField(max_length=50)
  ingredientes = models.TextField()
  preparacion = models.TextField()

  def __unicode__(self):
      return self.nombre

class Receta(models.Model):
  titulo = models.CharField(max_length=100, unique=True)
  ingredientes = models.TextField(help_text='Redacta los ingredientes')
  prepacion = models.TextField(verbose_name='Preparación')
  imagen = models.ImageField(upload_to='recetas', verbose_name='Imágen')
  tiempo_registro = models.DateTimeField(auto_now=True)
  usuario = models.ForeignKey(User)

  def __unicode__(self):
      return self.titulo
</pre>
</div>
<p>Son clases en Python (respetar la indentación), les explicaré de que trata todo esto:</p>
<div class="codigo">
<pre>
#encoding:utf-8 &lt;- Esta línea permite usar tíldes y caracteres especiales
from django.db import models &lt;- Clase con la descripción de modelos
from django.contrib.auth.models import User &lt;- Llama al modelo usuario
</pre>
</div>
<p>La clase Bebida de la semana anterior sólo era un ejemplo, no le daremos importancia de ahora en adelante, pasemos con la clase Receta (y sus respectivos comentarios previos a cada línea).</p>
<div class="codigo">
<pre>
#Dato cadena, longitud máxima 100 y único
titulo = models.CharField(max_length=100, unique=True)

#Dato texto, con texto de ayuda
ingredientes = models.TextField(help_text='Redacta los ingredientes')

#Dato texto, con nombre: Preparación
prepacion = models.TextField(verbose_name='Preparación')

#Dato imagen, se almacenarán en la carpeta recetas, titulo: Imágen
imagen = models.ImageField(upload_to='recetas', verbose_name='Imágen')

#Dato Fecha y Hora, almacena la fecha actual
tiempo_registro = models.DateTimeField(auto_now=True)

#Enlace al modelo Usuario que Django ya tiene construido
usuario = models.ForeignKey(User)
</pre>
</div>
<p>La clase Receta (modelo) tiene un atributo imagen, el cuál está direccionando las cargas que haga el usuario a la carpeta &#8216;recetas&#8217; (carpeta que estará dentro de otra llamada: &#8216;carga&#8217;), para que esto funcione debemos modificar nuestro archivo settings.py, exactamente debemos buscar la línea: MEDIA_ROOT (debe ser la número 56 aproximadamente), y dejarla así:</p>
<div class="codigo">
<pre>
MEDIA_ROOT = os.path.join(RUTA_PROYECTO,'carga')
</pre>
</div>
<p>Luego de haber puesto esta línea, debemos crear una carpeta que se llame &#8216;carga&#8217; dentro de la carpeta del proyecto. Debemos tener un árbol de ficheros de este tipo:</p>
<div id="attachment_24392" class="wp-caption aligncenter" style="width: 131px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-tree-directory.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-tree-directory-121x450.png" alt="Mapa de ficheros del proyecto recetario" width="121" height="450" class="size-medium wp-image-24392" /></a><p class="wp-caption-text">Mapa de ficheros del proyecto recetario</p></div>
<p>Dentro de esta carpeta &#8216;carga&#8217; aparecerá una carpeta &#8216;recetas&#8217; al momento de guardar un registro. Pero antes de ello debemos buscar el archivo admin.py y dejarlo asi:</p>
<div class="codigo">
<pre>
from principal.models import Bebida, Receta
from django.contrib import admin

admin.site.register(Bebida)
admin.site.register(Receta)
</pre>
</div>
<p>Esto nos permitirá agregar el modelo Receta dentro de la interfaz administrativa.</p>
<p>Por último debemos habilitar las URL para poder visualizar las imágenes, para ello debemos dejar el archivo urls.py asi:</p>
<div class="codigo">
<pre>
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings

admin.autodiscover()

urlpatterns = patterns('',
    url(r'^$','principal.views.lista_bebidas'),
    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^media/(?P.*)$','django.views.static.serve',
		{'document_root':settings.MEDIA_ROOT,}
	),
)
</pre>
</div>
<p>Esto nos permitirá acceder a las imágenes que subamos desde http://127.0.0.1:8000/media/recetas/nombre-imagen.jpg (o cualquier otra imagen).</p>
<h3>Poniendo a correr todo</h3>
<p>Para hacer funcionar todo, debemos sincronizar la base de datos nuevamente (esto se debe hacer cada vez que se modifique el modelo).</p>
<div class="tipexperto">
<h4>Nota</h4>
<div class="tipcont">Toda ejecución de comando se debe hacer desde una terminal o ventana de comando y dentro de la carpeta del proyecto (donde se encuentra el archivo manage.py)</div>
</div>
<div class="codigo">
<pre>
python manage.py syncdb
</pre>
</div>
<p>Y esto nos debe mostrar un resultado así (prestar atención a la segunda línea):<br />
<div id="attachment_24391" class="wp-caption aligncenter" style="width: 408px"><a href="http://www.maestrosdelweb.com/images/2012/05/django-models-syncdb.png"><img src="http://www.maestrosdelweb.com/images/2012/05/django-models-syncdb.png" alt="python manage.py syncdb" width="398" height="111" class="size-full wp-image-24391" /></a><p class="wp-caption-text">python manage.py syncdb</p></div></p>
<p>En caso de que queramos modificar un modelo ya existente podemos también reiniciar todos los modelos de la aplicación principal así:</p>
<div class="codigo">
<pre>
python manage.py reset principal
</pre>
</div>
<p>Sin embargo si ya se tienen datos almacenados estos se perderán al momento de reiniciarlos, para evitar eso podemos usar aplicaciones como <a href="http://south.aeracode.org/" title="South para Django">South</a>, que nos permitirán trabajar con los datos de manera más profesional. Aquí un video de ejemplo:</p>
<span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='640' height='390' src='http://www.youtube.com/embed/s41rV2kfRPI?version=3&amp;rel=1&amp;fs=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;wmode=transparent' frameborder='0'></iframe></span>
<h3>Probando el ejemplo</h3>
<p>Ya tenemos todo listo, el modelo nuevo sincronizado, las configuraciones listas y la interfaz administrativa. Corremos el proyecto:</p>
<div class="codigo">
<pre>
python manage.py runserver
</pre>
</div>
<p>Entramos a http://127.0.0.1:8000/admin y debemos observar el nuevo modelo: Recetas, listo para ser usado. Para ver las imágenes que se van cargando podemos ir a http://127.0.0.1:8000/media/recetas/nombre-imagen.jpg y si son proactivos, pueden modificar la plantilla de la semana pasada para poder ver el nuevo modelo de Recetas y sus imágenes, o pueden crear nuevos modelos para ver como pueden interactuar entre sí.</p>
<p>No se olviden que pueden revisar el <a href="http://neosergio.github.com/recetario_mdw" title="Recetario para Maestros del Web">repositorio del proyecto en github</a> si desean comprobar como deben quedar los archivos (en orden y en contenido). </p>
<p>La próxima semana sabremos que hacer con estos modelos y como interactuar con sus datos, lo haremos a través de la Shell de Django.</p>
<p>Que tengan un buen inicio de semana con Django, no se olviden comentar, twittear y hacer todas sus consultas, para poder ayudarlos.</p>
<hr /><p style="height: 64px;"><img alt='Sergio Infante Montero' src='http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Sergio Infante Montero</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/curso-django-el-modelo-de-datos/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/curso-django-el-modelo-de-datos/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/curso-django-el-modelo-de-datos/feed/</wfw:commentRss>
		<slash:comments>59</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-models-150x150.jpg" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-models.jpg" medium="image">
			<media:title type="html">Chuleta – Modelos en Django</media:title>
			<media:description type="html">Chuleta - Modelos en Django</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-models-150x150.jpg" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-tree-directory.png" medium="image">
			<media:title type="html">Mapa de ficheros del proyecto recetario</media:title>
			<media:description type="html">Mapa de ficheros del proyecto recetario</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-tree-directory-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/django-models-syncdb.png" medium="image">
			<media:title type="html">python manage.py syncdb</media:title>
			<media:description type="html">python manage.py syncdb</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/django-models-syncdb-150x111.png" />
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Sergio Infante Montero</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Es viernes: ¿Cómo despejar la mente y concretar ideas?</title>
		<link>http://www.maestrosdelweb.com/editorial/como-despejar-la-mente-y-concretar-ideas/</link>
		<comments>http://www.maestrosdelweb.com/editorial/como-despejar-la-mente-y-concretar-ideas/#comments</comments>
		<pubDate>Fri, 04 May 2012 07:00:08 +0000</pubDate>
		<dc:creator>Stephanie Falla Aroche</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Productividad]]></category>
		<category><![CDATA[es viernes!]]></category>
		<category><![CDATA[Freelancer]]></category>
		<category><![CDATA[metas]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24357</guid>
		<description><![CDATA[En la actualidad estamos tan saturados de información, trabajo, estímulos visuales y auditivos. Sales a la calle y escuchas las bocinas de los automóviles, sientes el olor de la ciudad y respiras la contaminación, miras el entorno saturado de imágenes, anuncios y marcas que buscan el top on mind. Pareciera que necesitamos de ese ruido [...]]]></description>
			<content:encoded><![CDATA[<p>En la actualidad estamos tan saturados de información, trabajo, estímulos visuales y auditivos. Sales a la calle y escuchas las bocinas de los automóviles, sientes el olor de la ciudad y respiras la contaminación, miras el entorno saturado de imágenes, anuncios y marcas que buscan el top on mind. Pareciera que necesitamos de ese ruido de fondo como una manifestación de la existencia, de lo real y cotidiano. Pero, entre tanto estímulo, distracción y ocupaciones <strong>¿cómo logramos despejar la mente?</strong> ¿encontrar nuestros pensamientos? <strong>¿volver realidad muchas de esas ideas? </strong>¿concretar proyecto?</p>
<p><a href="http://www.flickr.com/photos/grahamking/826142536/"><img src="http://www.maestrosdelweb.com/images/2012/05/yoga.png" alt="Despejar la mente" /><br />
</a><br />
Con todas estas <a href="http://www.maestrosdelweb.com/editorial/distracciones-limitacion-productividad-teletrabajo/">distracciones</a> del día a día es fácil perder el enfoque, dejar pasar el tiempo y simplemente nos convertimos en espectadores de como las ideas, sueños y proyectos de los demás se van concretando. Pensamos, yo también tengo muchas ideas, pero no tengo tiempo. Yo también tengo una lista de propósitos pero en cuanto salga de este trabajo las iré cumpliendo. En cuanto tenga el dinero suficiente me dedicaré a lo que realmente me gusta y así la vida se nos va. <strong>¿Crees que hoy es un buen día para cambiar de dinámica? </strong></p>
<h3>Con enfoque y determinación</h3>
<p>Era un domingo en la mañana, tenía que correr 20 kilómetros y el terreno era variado, empezamos en un plano, luego un par de bajadas y finalmente 5 kilómetros de subida. Las cuestas son los tramos más complicados para muchos corredores, porque se requiere de muchos factores para superarlas. Primero, una cuesta necesita concentración, canalizar energía en los brazos y piernas, relajación, técnica pero sobre todo: <strong>determinación</strong>. Menciono esto porque el enfoque y la determinación son factores importantes cuando queremos concretar ideas, desarrollar proyectos y cumplir con nuestros objetivos.</p>
<p>Con el tiempo nuestra mente se satura, resulta curioso como nuestro cansancio al final del día no es físico, resulta mental y por lo tanto te olvidas de cualquier actividad física. Pero, quiero compartir contigo algunos tips que te ayudarán a despejar la mente:</p>
<ul>
<li><a href="http://www.maestrosdelweb.com/editorial/es-viernes-salgamos-a-correr-respirar-aire-fresco/">Correr:</a> Es mi favorito, sólo necesitas un par de tenis, ropa cómoda y la determinación para desconectarte de todo por 30 minutos, 40 o 1 hora. Mientras corres tu mente se relaja, tu corazón trabaja, tus músculos se activan y segregas substancias naturales como la endorfina que te produce felicidad.</li>
<li><strong>Nadar:</strong> Recomendable para las personas con sobrepeso, que tienen lesiones o dolores en las articulaciones. Es un ejercicio muy noble y de cero impacto, puedes empezar con 100mts, luego 300mts y así hasta dedicarle 1 hora al día. Con la natación mejoras tu circulación, tienes más aire, mueves todos los músculos de tu cuerpo y te llenas de energía.</li>
<li> <a href="http://www.maestrosdelweb.com/editorial/es-viernes-que-tal-si-empiezas-a-ejercitarte-un-poco/">Yoga:</a> Quizás has escuchado muchas veces sobre las bondades del Yoga, pero aunque parece un ejercicio fácil de hacer y en el que sólo debes respirar. El reto, precisamente se encuentra en cómo logras despejar la mente para respirar adecuadamente, tu concentración se incrementa, tu capacidad de sentir tu entorno y oxigenas tu cuerpo de una forma sorprendente. </li>
</ul>
<h3>Con esfuerzo y automotivación</h3>
<p>La vida esta llena de obstáculos, dificultades y limitaciones. Pero, también está llena de soluciones, apoyo y oportunidades que llegan a uno de diferentes formas. La educación recibida en la escuela, los valores inculcados en casa y el entorno en el que nos desarrollamos, pueden ser factores a favor o en contra de nuestra capacidad de automotivación y determinación. Lo mejor es ver primero hacia dentro, escudriñar nuestras limitaciones y defectos; pero también evaluar nuestras virtudes y características que nos permiten enfrentar el día a día.</p>
<p>Luego de despejar la mente, la pregunta es ¿cómo concreto mis ideas? considero que lo más importante para ello es establecer prioridades, buscar un esquema, pedir ayuda si es necesario, utilizar métodos o herramientas que nos permitan no perder el enfoque. </p>
<ul>
<li><a href="http://www.maestrosdelweb.com/editorial/es-viernes-tecnica-pomodoro-productividad/">Técnica para concretar:</a> Empecemos hablando de técnicas que te permiten optimizar el tiempo, evaluar cuánto tiempo inviertes en tus sueños, las prioridades y se pone a prueba tu disciplina.</li>
<li><a href="http://www.maestrosdelweb.com/editorial/piensa-o-realizas-tus-suenos/">Metas a plazos:</a> Define tus metas a corto, mediano y largo plazo. Incluso toma un calendario, asigna fechas y tiempo de desarrollo de cada meta. Al final, procura evaluar tus resultados y los factores que no te permitieron cumplir con lo propuesto para volverlo a intentar.</li>
<li><a href="http://www.maestrosdelweb.com/editorial/crea-nuevos-habitos-de-productividad/">Crea nuevos hábitos:</a> Como sabrás son todas aquellas acciones que realizamos de forma automática, porque la hemos realizado por tanto tiempo que están instaladas en nuestro disco duro. Pero, tenemos buenos y malos hábitos por ello, trabajemos en crear nuevos que aún no están incorporados en nosotros.</li>
</ul>
<p>Hace unos días un amigo en Twitter me pidió que escribiera sobre este tema, precisamente porque me expresaba su dificultad en concretar proyectos, ideas o simples acciones de beneficio para su vida. Espero que estas ideas y referencias a otros artículos en donde reflexiono más sobre temas similares a este sirvan de apoyo y los motiven a saber que no están solos en este proceso de la superación personal, hacer sus sueños realidad y los fracasos en el intento. Feliz fin de semana. Enjoy!</p>
<hr /><p style="height: 64px;"><img alt='Stephanie Falla Aroche' src='http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Stephanie Falla Aroche</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/como-despejar-la-mente-y-concretar-ideas/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/como-despejar-la-mente-y-concretar-ideas/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/como-despejar-la-mente-y-concretar-ideas/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/05/yoga.png" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/05/yoga.png" medium="image">
			<media:title type="html">Despejar la mente</media:title>
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Stephanie Falla Aroche</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Curso Symfony 2: Integrando AJAX</title>
		<link>http://www.maestrosdelweb.com/editorial/curso-symfony2-integrando-ajax/</link>
		<comments>http://www.maestrosdelweb.com/editorial/curso-symfony2-integrando-ajax/#comments</comments>
		<pubDate>Wed, 02 May 2012 14:11:43 +0000</pubDate>
		<dc:creator>Maycol Alvarez</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[capitulo11]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[guia]]></category>
		<category><![CDATA[symfony 2]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=20141</guid>
		<description><![CDATA[En la actualidad muchos de nuestros proyectos están orientados hacia la web 2.0, y es por esto que la necesidad de implementar AJAX (XmlHttpRequest) es cada vez más grande, desde su versión 1.3 el proyecto Symfony a optado por no apoyar (ni integrar) ningún framework de desarrollo Frontend (básicamente en lo que se refiere Javascript), [...]]]></description>
			<content:encoded><![CDATA[<p>En la actualidad muchos de nuestros proyectos están orientados hacia la <a href="http://www.maestrosdelweb.com/editorial/web2/">web 2.0</a>, y es por esto que la necesidad de implementar <a href="http://www.maestrosdelweb.com/editorial/ajax/">AJAX</a> (XmlHttpRequest) es cada vez más grande, desde su versión 1.3 el proyecto Symfony a optado por no apoyar (ni integrar) ningún framework de desarrollo Frontend (básicamente en lo que se refiere Javascript), pero eso no impide que puedas utilizar cualquier framework Javascript en tu proyecto, de hecho Symfony2 es compatible con Assetic y te permite, entre otras cosas, utilizar el YUI-compressor para optimizar los assets de tu proyecto web.</p>
<p>Entrando de nuevo en el tema, en este capítulo nos concentraremos en las herramientas básicas que provee Symfony2 para manipular y detectar peticiones AJAX, las cuales son completamente transparentes para el cliente web (o framework que utilices), de esta forma podrás implementar AJAX de la forma que quieras y con el Framework JS que desees.</p>
<h3>Detectando peticiones XmlHttpRequest desde el controlador</h3>
<p>La clase Request contiene un función para verificar si la petición HTTP fue enviada por AJAX, es decir por medio del XmlHttpRequest:</p>
<pre class="brush: php; title: ; notranslate">
// retorna true o false
$this-&gt;getRequest()-&gt;isXmlHttpRequest();
</pre>
<p>¡Así de simple!, con ello puedes comprobar de forma efectiva desde tus controladores si la petición fue enviada por AJAX, lo que te permite, entre otras cosas, renderizar una plantilla específica, crear un objeto Response y controlar una salida personalizada como por ejemplo un JSON o XML.</p>
<h3>Detectando peticiones AJAX desde la Vista</h3>
<p>Controlar AJAX desde el controlador es muy efectivo, pero a veces por la estructura interna de nuestras plantillas (las que usas como layout y las que heredan un layout con la estructura HTML) puede resultar tedioso modificar cada controlador para devolver una plantilla específica, y ¿si dicha plantilla extiende un layout HTML (&lt;html&gt;, &lt;head&gt; y &lt;body&gt;)?: sabemos muy bien que en el caso de AJAX solo necesitamos <strong>el fragmento HTML específico</strong>, no un árbol HTML completo, por suerte en <a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-la-vista-twig/">TWIG</a> podremos hacer esto:</p>
<div class="codigo">
<pre>{% extends app.request.isXmlHttpRequest ? "MDWDemoBundle::layout_ajax.html.twig" : "::base.html.twig" %}</pre>
</div>
<p>De esta forma Twig nos permite comprobar si la petición es AJAX y de este modo tener un layout específico para cada situación.</p>
<p>En el caso de plantillas con PHP, simplemente podemos acceder al objeto Request gracias al contenedor de Inyección de Dependencias (DI) en nuestras vistas:</p>
<pre class="brush: php; title: ; notranslate">
$this-&gt;container-&gt;get('request')-&gt;isXmlHttpRequest()
</pre>
<p>Note que se hace una llamada a <strong>$this-&gt;container</strong> esto motivado a que en las plantillas $this-&gt;get() intentará cargar los Helpers, con ello especificamos que queremos cargar explícitamente un servicio, en nuestro caso el “Request”.</p>
<p>Esto es todo lo básico que necesitas conocer para implementar AJAX con Symfony 2. ¡Fue muy simple, corto y rápido!, ¿lo querías más difícil? <img src='http://www.maestrosdelweb.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' />  <strong>Simplicidad: ése es el objetivo</strong>, con esto puedes integrar perfectamente cualquier código JS AJAX, frameworks como jQuery, MooTools, Prototype, ExtJS, Dojo, YUI, etc.</p>
<hr /><p style="height: 64px;"><img alt='Maycol Alvarez' src='http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Maycol Alvarez</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-integrando-ajax/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-integrando-ajax/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/curso-symfony2-integrando-ajax/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
	
		<media:thumbnail url="http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" />
		<media:content url="http://0.gravatar.com/avatar/0457a9460a25fb50aca9a46f561f37c9?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Maycol Alvarez</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Curso Django: Entendiendo como trabaja Django</title>
		<link>http://www.maestrosdelweb.com/editorial/curso-django-entendiendo-como-trabaja-django/</link>
		<comments>http://www.maestrosdelweb.com/editorial/curso-django-entendiendo-como-trabaja-django/#comments</comments>
		<pubDate>Mon, 30 Apr 2012 13:28:50 +0000</pubDate>
		<dc:creator>Sergio Infante Montero</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[Editorial]]></category>
		<category><![CDATA[archivos]]></category>
		<category><![CDATA[curso django]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[guia python]]></category>
		<category><![CDATA[modelo]]></category>
		<category><![CDATA[mtv]]></category>
		<category><![CDATA[plantillas]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rutas]]></category>
		<category><![CDATA[vista]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24085</guid>
		<description><![CDATA[La semana pasada vimos lo fácil que fue crear un proyecto y ejecutarlo en unos cuantos pasos, sin embargo esa simplicidad debe ir acompañada de una fuerte lógica para poder aplicar Django a proyectos reales, es por eso que esta semana nos dedicaremos a entender como es que Django hace toda esa magia. Antes de [...]]]></description>
			<content:encoded><![CDATA[<p>La semana pasada vimos lo fácil que fue crear un proyecto y ejecutarlo en unos cuantos pasos, sin embargo esa simplicidad debe ir acompañada de una fuerte lógica para poder aplicar Django a proyectos reales, es por eso que esta semana nos dedicaremos a entender como es que Django hace toda esa magia.</p>
<div class="tipexperto"><h3>Nota</h3> <div class="tipcont">Para tener una estupenda experiencia con Django, el orden de los archivos y directorios deben respetarse, caso contrario el caos llegará rápidamente a nuestro proyecto y fracasará al momento de hacerlo crecer con mas personas o requerimientos.</div></div>
<p>Antes de iniciar con la explicación de como funciona Django, dale un vistazo a este vídeo:</p>
<span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='640' height='390' src='http://www.youtube.com/embed/c6JLEsXhEEc?version=3&amp;rel=1&amp;fs=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;wmode=transparent' frameborder='0'></iframe></span>
<p>Ahora que ya entiendes el contexto, empezamos!</p>
<h2>MTV y Django</h2>
<p>Se podría clasificar a Django como parte de la tercera generación del desarrollo web:</p>
<div id="attachment_24087" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/desarrolloweb.png"><img src="http://www.maestrosdelweb.com/images/2012/04/desarrolloweb-450x193.png" alt="Generaciones del desarrollo web" width="450" height="193" class="size-medium wp-image-24087" /></a><p class="wp-caption-text">Generaciones del desarrollo web</p></div>
<p>Sin embargo más alla de las clasificaciones que podrían existir, está el entender como funciona realmente, al entenderlo se puede llegar a dominarlo.</p>
<p><a href="http://www.maestrosdelweb.com/editorial/curso-django-introduccion/">Al principio del curso</a> de Django, les dije que era un framework MTV (una modificación de MVC, nada que ver con música), esto se debe a que los desarrolladores no tuvieron la intención de seguir algún patron de desarrollo, sino hacer el framework lo más funcional posible.</p>
<p>Para empezar a entender MTV debemos fijarnos en la analogía con MVC.</p>
<ul>
<li>El <em>modelo</em> en Django sigue siendo <strong>modelo</strong></li>
<li>La <em>vista</em> en Django se llama <strong>Plantilla (Template)</strong></li>
<li>El <em>controlador</em> en Django se llama <strong>Vista</strong></li>
</ul>
<p>Una imagen nos hará entender mejor esta relación:</p>
<div id="attachment_24088" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/esquema-mtv.png"><img src="http://www.maestrosdelweb.com/images/2012/04/esquema-mtv-450x121.png" alt="Funcionamiento del MTV de Django" width="450" height="121" class="size-medium wp-image-24088" /></a><p class="wp-caption-text">Funcionamiento del MTV de Django</p></div>
<p>Veamos que hace cada uno de ellos con un poco más de detalle y algunos conceptos adicionales.</p>
<h3>El modelo</h3>
<p>El modelo define los datos almacenados, se encuentra en forma de clases de Python, cada tipo de dato que debe ser almacenado se encuentra en una variable con ciertos parámetros, posee métodos también. Todo esto permite indicar y controlar el comportamiento de los datos.</p>
<h3>La vista</h3>
<p>La vista se presenta en forma de funciones en Python, su propósito es determinar que datos serán visualizados, entre otras cosas más que iremos viendo conforme avanzamos con el curso. El <a href="http://es.wikipedia.org/wiki/Mapeo_objeto-relacional" title="ORM en la wikipedia">ORM</a> de Django permite escribir código Python en lugar de SQL para hacer las consultas que necesita la vista. La vista también se encarga de tareas conocidas como el envío de correo electrónico, la autenticación con servicios externos y la validación de datos a través de formularios. Lo mas importante a entender con respecto a la vista es que no tiene nada que ver con el estilo de presentación de los datos, sólo se encarga de los datos, la presentación es tarea de la plantilla.</p>
<h3>La plantilla</h3>
<p>La plantilla es básicamente una página HTML con algunas etiquetas extras propias de Django, en si no solamente crea contenido en HTML (también XML, CSS, Javascript, CSV, etc). </p>
<p>Por ahora nos enfocaremos a lo básico el HTML. La plantilla recibe los datos de la vista y luego los organiza para la presentación al navegador web. Las etiquetas que Django usa para las plantillas permiten que sea flexible para los diseñadores del frontend, incluso tiene estructuras de datos como if, por por si es necesaria una presentación lógica de los datos, estas estructuras son límitadas para evitar un desorden poniendo cualquier tipo de código Python. </p>
<p>Esto permite que la lógica del sistema siga permaneciendo en la vista.</p>
<h3>La configuración de las rutas</h3>
<p>Django posee un mapeo de URLs que permite controlar el despliegue de las vistas, esta configuración es conocida como URLConf. El trabajo del URLConf es leer la URL que el usuario solicitó, encontrar la vista apropiada para la solicitud y pasar cualquier variable que la vista necesite para completar su trabajo. El URLConf esta construido con expresiones regulares en <a href="http://www.maestrosdelweb.com/editorial/guia-python/">Python</a> y sigue la filosofia de Python: <a href="http://www.python.org/dev/peps/pep-0020/" title="El PEP 20 de Python">Explicito es mejor que implícito.</a> Este URLConf permite que las rutas que maneje Django seán agradables y entendibles para el usuario.</p>
<p>Si consideramos al URLConf en el esquema anterior tendríamos este resultado más completo.</p>
<div id="attachment_24089" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/esquema-mtv-urlconf.png"><img src="http://www.maestrosdelweb.com/images/2012/04/esquema-mtv-urlconf-450x126.png" alt="Funcionamiento del MTV de Django y su URLConf" width="450" height="126" class="size-medium wp-image-24089" /></a><p class="wp-caption-text">Funcionamiento del MTV de Django y su URLConf</p></div>
<h2>Los archivos predeterminados</h2>
<p>Otra parte importante es entender el propósito de los archivos que se crean de manera predeterminada, estos son:</p>
<h3>Archivos del proyecto</h3>
<ul>
<li><strong>__init__.py</strong>: Este es un archivo vacío que le dice a Python que debe considerar este directorio como un paquete de Python. Si se desea saber más, se puede consultar <a href="http://docs.python.org/tutorial/modules.html#packages" title="Paquetes en Python"> la documentación sobre los paquetes.</a></li>
<li><strong>manage.py</strong>: Este archivo contiene una porción de código que permite interactuar con el proyecto de Django de muchas formas. Si se desea mayor detalle se encuentra la <a href="https://docs.djangoproject.com/en/dev/ref/django-admin/#ref-django-admin" title="Django y el manage.py">documentación oficial con respecto a manage.py.</a></li>
<li><strong>settings.py</strong>: Este archivo contiene todas las configuraciones para el proyecto, la documentación al respecto puede darnos mas detalles de la <a href="https://docs.djangoproject.com/en/dev/topics/settings/#topics-settings" title="Django y el settings.py">configuración de un proyecto en Django.</a></li>
<li><strong>urls.py</strong>: Contiene las rutas que están disponibles en el proyecto, manejado por URLConf, los detalles completos como siempre en la documentación oficial nos da mas detalles sobre las <a href="https://docs.djangoproject.com/en/dev/topics/http/urls/#topics-http-urls" title="Django y sus urls">urls y Django.</a></li>
</ul>
<h3>Archivos de la aplicación</h3>
<ul>
<li><strong>__init__.py</strong>: La misma descripción anterior (líneas arriba).</li>
<li><strong>models.py</strong>: En este archivo se declaran las clases del modelo.</li>
<li><strong>views.py</strong>: En este archivo se declaran las funciones de la vista.</li>
<li><strong>test.py</strong>: En este archivo se declaran las pruebas necesarias para la aplicación, para mayor detalle sobre las <a href="https://docs.djangoproject.com/en/dev/topics/testing/" title="Pruebas con Django">pruebas y Django</a> se puede consultar la documentación del proyecto.</li>
</ul>
<p>Una vez que tenemos claro el funcionamiento básico de Django, desarrollemos un ejemplo dentro del <a href="http://www.maestrosdelweb.com/editorial/curso-django-instalacion-y-primera-aplicacion/">proyecto que iniciamos la semana pasada</a>, para experimentar por nuestra cuenta. </p>
<h3>Modelo, Vista y Plantilla en 15 minutos</h3>
<p>Antes de continuar, deben entender que esto solamente es un pequeño ejemplo, el modelo, vista y plantillas serán desarrolladas a detalle en las próximas semanas. Si existen dudas del porque de las instrucciones, estas serán resueltas a detalle en los siguientes capítulos. Si eres muy impaciente siempre tienes a disposición <a href="https://docs.djangoproject.com/" title="Documentación oficial de Django">la documentación oficial del proyecto</a>.</p>
<p>Nuestro proyecto debe tener una estructura similar a esta:<br />
<div id="attachment_24317" class="wp-caption aligncenter" style="width: 175px"><a href="http://www.maestrosdelweb.com/images/2012/04/django_estructura_proyecto.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django_estructura_proyecto-165x450.png" alt="Árbol de ficheros de un proyecto en Django" width="165" height="450" class="size-medium wp-image-24317" /></a><p class="wp-caption-text">Árbol de ficheros de un proyecto en Django</p></div></p>
<p>Tendremos que manejar para este proyecto 6 archivos:</p>
<ul>
<li><strong>models.py</strong> (ya existe dentro de la carpeta principal).</li>
<li><strong>views.py</strong> (ya existe dentro de la carpeta principal).</li>
<li><strong>admin.py</strong> (aún no existe, pero estará dentro de la carpeta principal).</li>
<li><strong>urls.py</strong> (ya existe dentro de la carpeta recetario).</li>
<li><strong>settings.py</strong> (ya existe dentro de la carpeta recetario).</li>
<li><strong>lista_bebidas.html</strong> (aún no existe, estará dentro de una carpeta en la carpeta recetario).</li>
</ul>
<h4>models.py</h4>
<p>Al principio <em>models.py</em> luce asi:<br />
<div id="attachment_24318" class="wp-caption aligncenter" style="width: 386px"><a href="http://www.maestrosdelweb.com/images/2012/04/django_models_inicio.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django_models_inicio.png" alt="models.py predeterminado" width="376" height="159" class="size-full wp-image-24318" /></a><p class="wp-caption-text">models.py predeterminado</p></div></p>
<p>Usamos nuestro editor de texto favorito para editar models.py y redactamos lo siguiente:</p>
<div class="codigo">
<pre>
from django.db import models

class Bebida(models.Model):
	nombre = models.CharField(max_length=50)
	ingredientes = models.TextField()
	preparacion = models.TextField()

	def __unicode__(self):
		return self.nombre
</pre>
</div>
<h4>views.py</h4>
<p><em>views.py</em> luce así al principio:<br />
<div id="attachment_24321" class="wp-caption aligncenter" style="width: 416px"><a href="http://www.maestrosdelweb.com/images/2012/04/django_views_inicio.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django_views_inicio.png" alt="views.py predeterminado" width="406" height="119" class="size-full wp-image-24321" /></a><p class="wp-caption-text">views.py predeterminado</p></div></p>
<p>Igualmente con nuestro editor favorito abrimos views.py y lo dejamos de la siguiente forma:</p>
<div class="codigo">
<pre>
from principal.models import Bebida
from django.shortcuts import render_to_response

def lista_bebidas(request):
	bebidas = Bebida.objects.all()
	return render_to_response('lista_bebidas.html',{'lista':bebidas})
</pre>
</div>
<h4>admin.py</h4>
<p>Este archivo no existe, así que lo creamos manualmente dentro de nuestro directorio de la aplicación, en este caso dentro del directorio principal. Lo debemos dejar de esta manera:</p>
<div class="codigo">
<pre>
from principal.models import Bebida
from django.contrib import admin

admin.site.register(Bebida)
</pre>
</div>
<h4>urls.py</h4>
<p>Este archivo ya existe, se encuentra dentro del directorio recetario, así que lo único que debemos hacer es modificarlo para dejarlo de la siguiente manera:</p>
<div class="codigo">
<pre>
from django.conf.urls import patterns, include, url
from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns('',
    url(r'^$','principal.views.lista_bebidas'),
    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    url(r'^admin/', include(admin.site.urls)),
)
</pre>
</div>
<h4>settings.py</h4>
<p>Este archivo lo modificamos la semana pasada, se encuentra dentro de recetario. Debemos buscar la directiva TEMPLATE_DIRS (Debe encontrarse en la línea 113 aproximadamente). Debemos dejar esta sección de esta forma:</p>
<div class="codigo">
<pre>
TEMPLATE_DIRS = (
    os.path.join(RUTA_PROYECTO,'plantillas'),
)
</pre>
</div>
<p>En esta sección le estamos diciendo que debe buscar las plantillas dentro de la carpeta del proyecto, en una carpeta llamada plantillas, como esta carpeta aún no existe debemos crearla manualmente dentro de recetario.</p>
<h4>lista_bebidas.html</h4>
<p>Este archivo no existe, lo crearemos manualmente dentro de la carpeta plantillas (si, esa que acabas de crear dentro de recetario). </p>
<p>Debes finalizar con una estructura similar a esta:<br />
<div id="attachment_24316" class="wp-caption aligncenter" style="width: 181px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-estructura-plantillas.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-estructura-plantillas-171x450.png" alt="Árbol de ficheros del proyecto recetario" width="171" height="450" class="size-medium wp-image-24316" /></a><p class="wp-caption-text">Árbol de ficheros del proyecto recetario</p></div></p>
<p>Una vez creado le ponemos la etiquetación HTML que nos permita visualizar la lista de bebidas. Podría quedarse de esta manera:</p>
<div class="codigo">
<pre>
&lt;!DOCTYPE html&gt;
&lt;html lang='es'&gt;
  &lt;head&gt;
	&lt;title&gt;Lista de bebidas de ejemplo&lt;/title&gt;
	&lt;meta charset='utf-8'&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;Recetario de Bebidas&lt;/h1&gt;
	{% for elemento in lista %}
	&lt;ul&gt;
	  &lt;li&gt;&lt;strong&gt;{{elemento.nombre}}&lt;/strong&gt;&lt;/li&gt;
	  &lt;li&gt;{{elemento.ingredientes}}&lt;/li&gt;
	  &lt;li&gt;{{elemento.preparacion}}&lt;/li&gt;
	&lt;/ul&gt;
	{% endfor %}
  &lt;/body&gt;
&lt;/html&gt;
</pre>
</div>
<div class='tipexperto'>
<h3>Nota: Python es sensible a las mayúsculas y minúsculas</h3>
<div>Tener precaución al momento de digitar el código en Python, las mayúsculas y minúsculas importan y mucho.</div>
</div>
<h4>Poner en funcionamiento todo</h4>
<p>Listo, tenemos todo listo para ver funcionando nuestro ejemplo, para ello debemos de sincronizar nuevamente nuestra base de datos, para ello, nos ubicamos en la carpeta principal del proyecto (aquella donde se encuentra el archivo manage.py). Una vez en la carpeta principal, desde una terminal digitamos:</p>
<div class="codigo">
<pre>
python manage.py syncdb
</pre>
</div>
<p>Esto nos dará el siguiente resultado: (prestar atención a la segunda línea que nos indica la creación de una nueva tabla):<br />
<div id="attachment_24320" class="wp-caption aligncenter" style="width: 408px"><a href="http://www.maestrosdelweb.com/images/2012/04/django_syncdb_nuevo_modelo.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django_syncdb_nuevo_modelo.png" alt="Creación de tabla principal_bebidas" width="398" height="94" class="size-full wp-image-24320" /></a><p class="wp-caption-text">Creación de tabla principal_bebidas</p></div></p>
<p>Una vez realizado esto, lanzamos nuestro servidor de desarrollo:</p>
<div class="codigo">
<pre>
python manage.py runserver
</pre>
</div>
<p>Nos ubicamos en <strong>http://127.0.0.1:8000/admin</strong>, ingresamos con nuestros datos configurados en la primera vez que sincronizamos la base de datos (si no recuerdas los datos que pusiste, puedes borrar el archivo recetario.db y volver a digitar: python manage.py syncdb para resincronizar).</p>
<p>Una vez dentro de la interfaz administrativa veremos: (notar que aparece una opción Bebidas).<br />
<div id="attachment_24314" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django_admin_models.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django_admin_models-450x216.png" alt="Interfaz administrativa de Django + Bebidas" width="450" height="216" class="size-medium wp-image-24314" /></a><p class="wp-caption-text">Interfaz administrativa de Django + Bebidas</p></div></p>
<p>Podemos seguir intuitivamente la interfaz e ingresar datos:<br />
<div id="attachment_24319" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-recetario-bebida-admin-add.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-recetario-bebida-admin-add-450x216.png" alt="Interfaz inicial de bebidas" width="450" height="216" class="size-medium wp-image-24319" /></a><p class="wp-caption-text">Interfaz inicial de bebidas</p></div><br />
<div id="attachment_24312" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-admin-bebida-save.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-admin-bebida-save-450x371.png" alt="Formulario para ingreso de datos" width="450" height="371" class="size-medium wp-image-24312" /></a><p class="wp-caption-text">Formulario para ingreso de datos</p></div><br />
<div id="attachment_24315" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-ejemplo-add-admin.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-ejemplo-add-admin-450x371.png" alt="Ingreso de contenido" width="450" height="371" class="size-medium wp-image-24315" /></a><p class="wp-caption-text">Ingreso de contenido</p></div><br />
<div id="attachment_24313" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-admin-ejemplo.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-admin-ejemplo-450x227.png" alt="Lista de elementos ingresados" width="450" height="227" class="size-medium wp-image-24313" /></a><p class="wp-caption-text">Lista de elementos ingresados</p></div></p>
<p>Una vez guardados podemos ir a <strong>http://127.0.0.1:8000/</strong> y veremos lo que acabamos de ingresar. De esta manera ya tienes una interfaz rápida de ingreso y visualización de datos.</p>
<div id="attachment_24323" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-ejemplo-resultado.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-ejemplo-resultado-450x227.png" alt="Ejemplo de plantilla con Django" width="450" height="227" class="size-medium wp-image-24323" /></a><p class="wp-caption-text">Ejemplo de plantilla con Django</p></div>
<p>Hay muchos puntos que en este capítulo he tenido que tocar superficialmente, esto no debe preocuparte, porque en los siguientes capítulos desarrollaré a detalle esos puntos, deseo recordarte que el objetivo de este pequeño ejemplo, es disfrutar la experiencia de la velocidad de Django, para el desarrollo de aplicaciones.</p>
<p>Si desean ver los archivos oficiales del proyecto, no olviden que pueden acceder al <a href="http://neosergio.github.com/recetario_mdw" title="Recetario para maestros del web con Django">repositorio del mismo en github</a>. Los datos de acceso para la interfaz administrativa del ejemplo del repositorio son los siguientes:</p>
<ul>
<li>usuario:sergio</li>
<li>clave:maestros</li>
</ul>
<p>La próxima semana tendremos el capítulo dedicado a <strong>El Modelo</strong>. Muchas gracias por sus comentarios en el capítulo anterior, eso enriquece mucho más cada capítulo.</p>
<hr /><p style="height: 64px;"><img alt='Sergio Infante Montero' src='http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Sergio Infante Montero</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/curso-django-entendiendo-como-trabaja-django/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/curso-django-entendiendo-como-trabaja-django/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/curso-django-entendiendo-como-trabaja-django/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/desarrolloweb-150x150.png" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/desarrolloweb.png" medium="image">
			<media:title type="html">Generaciones del desarrollo web</media:title>
			<media:description type="html">Generaciones del desarrollo web</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/desarrolloweb-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/esquema-mtv.png" medium="image">
			<media:title type="html">Funcionamiento del MTV de Django</media:title>
			<media:description type="html">Funcionamiento del MTV de Django</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/esquema-mtv-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/esquema-mtv-urlconf.png" medium="image">
			<media:title type="html">Funcionamiento del MTV de Django y su URLConf</media:title>
			<media:description type="html">Funcionamiento del MTV de Django y su URLConf</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/esquema-mtv-urlconf-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django_estructura_proyecto.png" medium="image">
			<media:title type="html">Árbol de ficheros de un proyecto en Django</media:title>
			<media:description type="html">Árbol de ficheros de un proyecto en Django</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django_estructura_proyecto-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django_models_inicio.png" medium="image">
			<media:title type="html">models.py predeterminado</media:title>
			<media:description type="html">models.py predeterminado</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django_models_inicio-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django_views_inicio.png" medium="image">
			<media:title type="html">views.py predeterminado</media:title>
			<media:description type="html">views.py predeterminado</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django_views_inicio-150x119.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-estructura-plantillas.png" medium="image">
			<media:title type="html">Árbol de ficheros del proyecto recetario</media:title>
			<media:description type="html">Árbol de ficheros del proyecto recetario</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-estructura-plantillas-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django_syncdb_nuevo_modelo.png" medium="image">
			<media:title type="html">Creación de tabla principal_bebidas</media:title>
			<media:description type="html">Creación de tabla principal_bebidas</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django_syncdb_nuevo_modelo-150x94.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django_admin_models.png" medium="image">
			<media:title type="html">Interfaz administrativa de Django + Bebidas</media:title>
			<media:description type="html">Interfaz administrativa de Django + Bebidas</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django_admin_models-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-recetario-bebida-admin-add.png" medium="image">
			<media:title type="html">Interfaz inicial de bebidas</media:title>
			<media:description type="html">Interfaz inicial de bebidas</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-recetario-bebida-admin-add-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-admin-bebida-save.png" medium="image">
			<media:title type="html">Formulario para ingreso de datos</media:title>
			<media:description type="html">Formulario para ingreso de datos</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-admin-bebida-save-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-ejemplo-add-admin.png" medium="image">
			<media:title type="html">Ingreso de contenido</media:title>
			<media:description type="html">Ingreso de contenido</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-ejemplo-add-admin-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-admin-ejemplo.png" medium="image">
			<media:title type="html">Lista de elementos ingresados</media:title>
			<media:description type="html">Lista de elementos ingresados</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-admin-ejemplo-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-ejemplo-resultado.png" medium="image">
			<media:title type="html">Ejemplo de plantilla con Django</media:title>
			<media:description type="html">Ejemplo de plantilla con Django</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-ejemplo-resultado-150x150.png" />
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Sergio Infante Montero</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Es viernes: “No comparto mi idea porque me la pueden robar”</title>
		<link>http://www.maestrosdelweb.com/editorial/me-pueden-robar-mi-idea/</link>
		<comments>http://www.maestrosdelweb.com/editorial/me-pueden-robar-mi-idea/#comments</comments>
		<pubDate>Fri, 27 Apr 2012 18:51:08 +0000</pubDate>
		<dc:creator>Stephanie Falla Aroche</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Negocios]]></category>
		<category><![CDATA[Productividad]]></category>
		<category><![CDATA[emprendimiento]]></category>
		<category><![CDATA[es viernes!]]></category>
		<category><![CDATA[Freelancer]]></category>
		<category><![CDATA[ideas]]></category>
		<category><![CDATA[latinoamérica]]></category>
		<category><![CDATA[oportunidades]]></category>
		<category><![CDATA[proyectos]]></category>
		<category><![CDATA[trabajo en equipo]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24290</guid>
		<description><![CDATA[¿Cuántos de ustedes en algún momento han pensado lo mismo? no compartimos nuestra idea en un evento, porque me la pueden copiar y no me darán crédito. No presento mi proyecto en ningún evento de emprendimiento porque si no gano, otros con los recursos sí lo llevarán a cabo. No publico mi propuesta en ningún [...]]]></description>
			<content:encoded><![CDATA[<p><strong>¿Cuántos de ustedes en algún momento han pensado lo mismo? </strong>no compartimos nuestra idea en un evento, porque me la pueden copiar y no me darán crédito. No presento mi proyecto en ningún evento de emprendimiento porque si no gano, otros con los recursos sí lo llevarán a cabo. No publico mi propuesta en ningún medio de financiamiento colectivo porque corro el riesgo de que otro la tome. Entonces, como no hago nada de esto, mi proyecto lleva 5 años en el disco duro porque estoy esperando el momento preciso, la gran oportunidad, la gente adecuada y entonces el mundo sabrá de lo que soy capaz.</p>
<p><img src="http://www.maestrosdelweb.com/images/2012/04/ideas-latinoamerica.jpeg" alt="Webprendedor" /></p>
<p>Existen muchos factores que nos hacen pensar de esa manera, principalmente en Latinoamérica en donde nuestros países son tan peligrosos, no existe cultura de respeto, carecemos de oportunidades y en el momento menos esperado alguien se aprovecha de nosotros ¿cierto?. Yo amo mi país, pero, vivimos a la defensiva, no confiamos en la gente, creemos en la estafa, en un abrir y cerrar de ojos nos despojan de lo que es nuestro. En un contexto como este ¿cómo no vamos a pensar de esta manera? creo que es justificable y necesitamos el escepticismo como arma de defensa.</p>
<h3>Canalizar el escepticismo hacia las oportunidades</h3>
<p>Sin embargo, porque siempre debe existir una manera diferente de ver las cosas, podemos aprovechar todas esas alertas que tenemos y canalizarlas de forma positiva. Si somos tan hábiles para saber cuando alguien nos &#8220;miente o nos quiere ver la cara&#8221; por qué no utilizamos ese sentido agudo para detectar personas con talento y capaces de formar parte de nuestro proyecto. Por qué, si somos tan capaces de elevar la voz para denunciar un abuso, un robo o asalto. No utilizamos ese valor para felicitar a otros que con esfuerzo están logrando proyectos interesantes y aprendemos de ellos.</p>
<p>En este medio, <strong>compartir tus ideas no es un riesgo de perdida</strong>, al contrario es una oportunidad para que más personas con tus mismos intereses te descubran y puedan construir algo en conjunto. Tenemos muchas herramientas de comunicación, el compartir y aprender de alguien extranjero, ya no es un lujo que sólo tienen quienes salen del país a cursar un posgrado o de quienes tienen suficiente dinero para pagar estudios fuera del país. Los medios sociales y las herramientas de comunicación nos permiten armar equipos múltidisciplinarios entorno al Interne sin importar el espacio geográfico.</p>
<h3>Comparte tus ideas y proyectos</h3>
<p>Debemos aprender a ser proactivos, independientes de los recursos, libres y seguros de las cosas que deseamos alcanzar. Nos decimos freelancer, emprendedores, trabajadores independientes, pero seguimos dependiendo de que la oportunidad, las personas indicadas y el momento preciso llame a nuestra puerta. Cuando en realidad todo eso que buscamos está allá, afuera, en Internet, los eventos, en la calle, la universidad, las redes sociales y hasta en este espacio. ¿Entonces, por qué nuestra idea se sigue llenando de polvo? ¿qué necesitamos? ¿cómo empezar?</p>
<p>No existen fórmulas para lograrlo, pero algo sí te aseguro, existen muchos caminos y muchas oportunidades para hacerlo. Pero, no llegarán a tí, tu debes buscar, trabajar y (des)aprender de las experiencias que no te han permitido lograrlo hasta el momento. Hace una semanas en <a href="http://mejorando.la">mejorando.la</a> con @freddier y @cvander hablamos sobre proyectos de financiamiento colectivo, en especial hablamos de <a href="http://mejorando.la/videos/crowdfunding-kickstarter-geeks-espacio/">Crowdfunding con Kickstarter</a>. Además, hablamos de proyectos similares como: </p>
<ul>
<li><a href="http://www.idea.me">Idea.me</a>: Ayuda para creadores latinos para realiar sus proyectos  través del financiamiento colectivo.</li>
<li><a href="http://www.lanzamos.com">Lanzanos.com</a>: Iniciativa española de Público.es donde puedes enviar tus proyectos y obtener el finamiento que necesitas.</li>
<li><a href="http://www.goteo.org/">Goteo.org</a>: Red social para cofinanciar y colaborar con proyectos creativos. </li>
<li><a href="http://Kickstarter.com">Kickstarter.com</a>: Proyecto en inglés que permite el financiamiento colectivo para proyectos.</li>
</ul>
<p>Existen muchas formas de lograr que tu proyecto sea conocido, empieza leyendo blogs sobre el tema, <a href="http://www.maestrosdelweb.com/guias/#guia-startup">Guías de emprendimiento</a>, participa en comunidades, procura ir a eventos sobre temáticas similares. Invierte, participa y cree en otros proyectos latinos como el tuyo y construye ese buen karma. Pero sobre todo, no tengas temor de hablar sobre tu idea porque sólo será  una limitante en la búsqueda de llevarla a cabo con éxito. Feliz fin de semana. Enjoy!</p>
<hr /><p style="height: 64px;"><img alt='Stephanie Falla Aroche' src='http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Stephanie Falla Aroche</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/me-pueden-robar-mi-idea/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/me-pueden-robar-mi-idea/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/me-pueden-robar-mi-idea/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/ideas-latinoamerica.jpeg" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/ideas-latinoamerica.jpeg" medium="image">
			<media:title type="html">Webprendedor</media:title>
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Stephanie Falla Aroche</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Curso Symfony 2: Validación de datos y creación de formularios</title>
		<link>http://www.maestrosdelweb.com/editorial/curso-symfony2-validacion-de-datos-y-creacion-de-formularios/</link>
		<comments>http://www.maestrosdelweb.com/editorial/curso-symfony2-validacion-de-datos-y-creacion-de-formularios/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 07:00:52 +0000</pubDate>
		<dc:creator>Juan Ardissone</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Guías]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[@asserts]]></category>
		<category><![CDATA[curso]]></category>
		<category><![CDATA[datos]]></category>
		<category><![CDATA[entidades]]></category>
		<category><![CDATA[entities]]></category>
		<category><![CDATA[fomularios]]></category>
		<category><![CDATA[sql injection]]></category>
		<category><![CDATA[symfony2]]></category>
		<category><![CDATA[validación]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24217</guid>
		<description><![CDATA[Ahora que ya hemos trabajado con la base de datos y con los datos en sí vamos a tocar dos temas que serán de mucha ayuda. El primero es como el framework nos ayuda a validar los datos que vamos a grabar en nuestra base de datos y el segundo es como crear los formularios [...]]]></description>
			<content:encoded><![CDATA[<p>Ahora que ya hemos trabajado con la <a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-configurando-bases-de-datos/">base de datos</a> y con los <a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-manipulando-datos-con-doctrine/">datos en sí</a> vamos a tocar dos temas que serán de mucha ayuda. El primero es como el framework nos ayuda a validar los datos que vamos a grabar en nuestra base de datos y el segundo es como crear los formularios para que los usuarios finales ingresen los datos en la aplicación.</p>
<h3>Validación de datos</h3>
<p>Como ya hemos visto cada tabla de nuestra base de datos es representada por medio de un Entity en el que usamos annotations para definir los metadatos. Para usar estos annotations importamos el paquete &#8220;use Doctrine\ORM\Mapping as ORM;&#8221; arriba del archivo y usamos los mismos por medio del alias ORM de esta manera &#8220;@ORM\Id&#8221;.</p>
<p>Para la validación de los datos importaremos otro namespace: &#8220;use Symfony\Component\Validator\Constraints as Assert;&#8221; y por medio del alias Assert, utilizando annotations definiremos los validadores para los campos que queramos. El listado completo de validadores o también llamados constraints los puedes ver en la <a href="http://symfony.com/doc/current/book/validation.html#constraints">documentación oficial</a>.</p>
<p>Algo que resulta muy importante entender es que la definición de los metadatos que escribimos usando el alias @ORM no tiene el mismo propósito que cuando usamos el @Assert. Por ejemplo, en el caso de nuestro Entity Article, hemos definido que la propiedad (campo/columna) $title no permite nulos. Esto lo hicimos porque dejamos su mapeo como @ORM\Column(name=&#8221;title&#8221;, type=&#8221;string&#8221;, length=255) donde por defecto es not null pero esto no implica la validación de los datos ya que lo que acabamos de escribir es que para la creación de la tabla se debe tener en cuenta que no es nulo y esto sirve para generar correctamente el CREATE TABLE necesario.</p>
<p>Para asegurarnos de que no sea nulo a la hora de ingresar los datos debemos usar el @Assert\NotNull() cuyo objetivo es realmente decirle al validador de datos que efectivamente al intentar grabar datos por medio del entity este debe ser validado como que no permite valores nulos.</p>
<p>Estos annotations tienen la misma forma que los anteriores. Son llamadas a métodos que pueden recibir parámetros opcionales. Por ejemplo, si ponemos:</p>
<pre>/**
* @var string $title
*
* @ORM\Column(name="title", type="string", length=255)
* @Assert\NotNull()
*/
private $title;</pre>
<p>estamos diciendo que la propiedad title no debe permitir valores nulos y al momento de validarlos saldrá una mensaje diciendo eso en ingles, si queremos cambiar el mensaje por defecto lo hacemos agregando el argumento a la invocación de esta manera:</p>
<pre>/**
 * @var string $title
 *
 * @ORM\Column(name="title", type="string", length=255)
 * @Assert\NotNull(message="Debe escribir un titulo")
 */
 private $title;</pre>
<p>Si quisiéramos validar que un campo debe ser de tipo email usaremos el annotation @Assert\Email() de esta manera:</p>
<pre>/**
 * @Assert\Email(
 *     message = "El mail '{{ value }}' ingresado no tiene el formato correcto.",
 * )
 */
 protected $email;</pre>
<p>Haciendo referencia a {{ value }} va a mostrar el valor ingresado como parte del mensaje.</p>
<p>Como último ejemplo, si quisiéramos validar la máxima cantidad de caracteres ingresados, podríamos usar el @Assert\MaxLength():</p>
<pre>/**
 * @var string $title
 *
 * @ORM\Column(name="title", type="string", length=255)
 * @Assert\NotNull(message="Debe escribir un titulo")
 * @Assert\MaxLength(255)
 */
 private $title;</pre>
<p>Y si quisiéramos además de la máxima cantidad de caracteres, controlar la mínima cantidad simplemente lo agregamos también:</p>
<pre>/**
 * @var string $title
 *
 * @ORM\Column(name="title", type="string", length=255)
 * @Assert\NotNull(message="Debe escribir un titulo")
 * @Assert\MaxLength(255)
 * @Assert\MinLength(5)
 */
 private $title;</pre>
<p>Con esto ya estamos controlando que mínimamente debemos escribir 5 caracteres en el título y como máximo 255.<br />
<div class="tipexperto"><h3>Nota</h3> <div class="tipcont">Cuando usamos el @Assert\MaxLength(), la cantidad de caracteres que permitimos debe ser menor o igual al length definido en el @ORM\Column() ya que de lo contrario la aplicación dejaría pasar valores mayores y al llegar a la base de datos nos devolvería un error pero del motor de datos.</div></div></p>
<p>Como ya había mencionado más arriba, en la <a href="http://symfony.com/doc/current/book/validation.html#constraints">documentación oficial</a> tenemos los constraints soportados y si damos click sobre cada uno de ellos veremos como  se utilizan con un ejemplo. Entre ellos encontrarán NotNull, NotBlank, Email, MinLength y MaxLength (para cantidad de caracteres), Max y Min (para valores numéricos), Date, DateTime, Time, Choice (para campos que serán ingresados por medio de un combo de valores por ejemplo).</p>
<p>Al escribir los Asserts en realidad estamos configurando las validaciones que queremos tener pero para validar los datos debemos invocar al validador. Para esto usemos como base el ejemplo que teníamos para la inserción de artículos del <a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-manipulando-datos-con-doctrine/">capítulo anterior</a>:</p>
<pre>public function crearAction()
{
    $articulo = new Articles();
    $articulo-&gt;setTitle('Articulo de ejemplo 1');
    $articulo-&gt;setAuthor('John Doe');
    $articulo-&gt;setContent('Contenido');
    $articulo-&gt;setTags('ejemplo');
    $articulo-&gt;setCreated(new \DateTime());
    $articulo-&gt;setUpdated(new \DateTime());
    $articulo-&gt;setSlug('articulo-de-ejemplo-1');
    $articulo-&gt;setCategory('ejemplo');

    $em = $this-&gt;getDoctrine()-&gt;getEntityManager();
    $em-&gt;persist($articulo);
    $em-&gt;flush();

    return $this-&gt;render('MDWDemoBundle:Articulos:articulo.html.twig', array('articulo' =&gt; $articulo));
 }</pre>
<p>En código anterior, sin validar nada y pasando por alto los constraints de nuestro Entity intenta grabar los datos y si por ejemplo no cargamos un dato obligatorio como el título, el error devuelto será el que la misma base de datos valida ya que la columna fue creada como not null pero lo que queremos es poder obtener la validación en la aplicación, antes que llegue el insert a la base de datos, y esto lo haremos por medio del validador agregando el siguiente código antes de la invocación al EntityManager:</p>
<pre>$errores = $this-&gt;get('validator')-&gt;validate($articulo);</pre>
<p>Por medio del objeto $this-&gt;get(&#8216;validator&#8217;) le decimos que valide la entidad $articulo, quién ya sabe como validarse por si misma ya que los annotations están dentro de la misma. Este método validate() nos devolverá un array de errores que podemos iterar y obtenerlos por medio del método getMessage():</p>
<pre>public function crearAction()
{
    $articulo = new Articles();
    //-- No cargamos el dato para title
    $articulo-&gt;setAuthor('John Doe');
    $articulo-&gt;setContent('Contenido');
    $articulo-&gt;setTags('ejemplo');
    $articulo-&gt;setCreated(new \DateTime());
    $articulo-&gt;setUpdated(new \DateTime());
    $articulo-&gt;setSlug('articulo-de-ejemplo-1');
    $articulo-&gt;setCategory('ejemplo');

    $errores = $this-&gt;get('validator')-&gt;validate($articulo);

    if(!empty($errores))
    {
        foreach($errores as $error)
        echo $error-&gt;getMessage();

        return new Response();
    }

    $em = $this-&gt;getDoctrine()-&gt;getEntityManager();
    $em-&gt;persist($articulo);
    $em-&gt;flush();

    return $this-&gt;render('MDWDemoBundle:Articulos:articulo.html.twig', array('articulo' =&gt; $articulo));
 }</pre>
<p>En el código de arriba hemos borrado la línea del setTitle(). Esto nos mostrará en pantalla el mensaje &#8220;Debe escribir un titulo&#8221; y si tenemos más errores los mensajes por cada error.</p>
<p>Ahora bien, realmente no tiene mucho sentido mostrar de esta manera los mensajes de errores ya que finalmente ni siquiera cargamos los datos a mano como lo estamos haciendo, sino que son ingresados por un formulario y es aquí donde pasamos al siguiente tema, la creación de formularios.</p>
<h3>Creación de Formularios</h3>
<p>La posibilidad de crear formularios es uno de los temas que más me gusta de Symfony ya que los mismos no se escriben en HTML sino que son programados como objetos y el mismo framework se encarga de hacer render del HTML necesario y asegurándonos que serán escritos de la mejor manera posible incluso utilizando las validaciones de <a href="http://www.maestrosdelweb.com/guias/#guia-html5">HTML5</a>.</p>
<p>Un formulario siempre debería ser representado por un objeto que se lo conoce como <strong>Type</strong>. Este objeto hace referencia a otro que puede ser un Entity (del que ya hablamos en los capítulos anteriores) o un POPO (Plain Old PHP Object).<br />
<div class="tipexperto"><h3>Nota</h3> <div class="tipcont">Un POPO (Plain Old PHP Object) es simplemente una clase con propiedades y métodos tradicionales, es decir que es muy parecido a los Entities pero sin los annotations. Por ejemplo en caso de ser una clase que representará a un formulario para contacto donde tendremos simplemente una propiedad asunto, email, nombre y texto con sus respectivos setters y getters.</div></div></p>
<p>Un objeto <strong>Type</strong> se debe tomar como la definición del formulario. Este objeto recibirá cual es el Entity o POPO en el cual se almacenan los datos cargados en el formulario. Podríamos tener más de un Type para un mismo objeto ya que dependiendo de ciertos perfiles por ejemplo, podríamos querer mostrar algunos campos u otros dependiendo de que el usuario sea operador normal o administrador.</p>
<h4>Definición de nuestro formulario</h4>
<p>Para nuestro ejemplo tomaremos en cuenta el Entity Article que venimos usando y crearemos un objeto Type para representar a este formulario. Los formularios se deben crear dentro de nuestro Bundle en una carpeta Form por lo que crearemos el archivo <strong>ArticleType</strong> dentro de nuestra carpeta <strong>src/MDW/DemoBundle/Form</strong>:</p>
<pre>&lt;?php
namespace MDW\DemoBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class ArticleType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder-&gt;add('title')
                -&gt;add('author')
                -&gt;add('created');
    }
    public function getName()
    {
        return 'article_form';
    }
}</pre>
<p>Como podemos ver en el ejemplo, el nombre de la clase esta formado por un nombre que yo he elegido concatenado con el sufijo Type y debe heredar de AbstractType para contener las funcionalidades base.</p>
<p>En el método <strong>buildForm()</strong>, por medio del $builder, que se recibe como argumento, agregamos los campos que vamos a usar. Estos campos son los nombres de los campos que tendrá el formulario y deben coincidir con las propiedades de nuestro Entity Article aunque todavía no hemos dicho que el formulario representará a Article ya que eso lo hacemos en la invocación desde el controller. El argumento options nos servirá para crear el formulario con otras opciones de personalización.</p>
<p>El método <strong>getName()</strong> deberá retornar el identificador de nuestro formulario y este String puede tomar el nombre que queramos siempre y cuando sea único. Tenemos que tener en cuenta que este nombre será usado para los atributos &#8220;name&#8221; de los componentes de formularios. Por ejemplo vemos que tenemos un componente llamado &#8220;title&#8221; que hemos agregado en el método buildForm() por lo que la etiqueta creada será:</p>
<pre>&lt;input type="text" name="article_form[title]" /&gt;</pre>
<p>Hay que notar que esta es la sintaxis para cargar datos en un array (usando los corchetes) por lo que &#8220;article_form&#8221; será simplemente un array con una clave asociativa &#8220;title&#8221; que contendrá el valor ingresado por el usuario. Esta sintaxis nos permite tener en un array todos los datos del formulario al hacer el submit.</p>
<p>Con esto lo que hemos hecho es crear la representación básica de nuestro formulario, diciéndole cual es el identificador del formulario y los campos que deberá contener.</p>
<div class="tipexperto"><h3>Nota</h3> <div class="tipcont">Escribiendo los objetos Type NO definimos como será <span style="text-decoration: underline;">visualmente</span> el formulario sino como será <span style="text-decoration: underline;">CONCEPTUALMENTE</span>.</div></div>
<h4>Invocación y Visualización del formulario</h4>
<p>Para poder mostrar el formulario HTML en nuestra página debemos invocar a nuestra clase <strong>ArticleType</strong> desde nuestro controlador, o más específicamente desde el action que llama a nuestra página, para esto vamos a crear un action nuevo dentro de nuestro ArticulosController al que vamos a llamar newAction.</p>
<p>Primeramente creamos nuestra ruta en el archivo routing.yml</p>
<pre>articulo_new:
 pattern: /articulo/new
 defaults: { _controller: MDWDemoBundle:Articulos:new }</pre>
<p>Una vez creada nuestra ruta iremos a crear nuestro <strong>newAction</strong> en src\MDW\DemoBundle\Controller\ArticulosController.php (MDWDemoBundle:Articulos:new). Para esto agregamos el siguiente código:</p>
<pre>//--  Al estar utilizando la clase ArticleType dentro de nuestro método no debemos olvidar importar el namespace al principio del archivo
use MDW\DemoBundle\Form\ArticleType; 
//-- Agregar este método como uno nuevo
public function newAction()
{
    $articulo = new Articles();
    $form = $this-&gt;createForm(new ArticleType(), $articulo);
    return $this-&gt;render('MDWDemoBundle:Articulos:new.html.twig', array(
        'form' =&gt; $form-&gt;createView(),
    ));
}</pre>
<div class="tipexperto"><h3>Nota</h3> <div class="tipcont">Un dato importante es que en el código de arriba hemos creado un nuevo <strong>$articulo</strong> desde un <span style="text-decoration: underline;">objeto vacío</span> lo cual hará que el formulario se muestre vacío. Si queremos, por ejemplo en un formulario de modificación de registro, mostrar ya los datos del artículo a modificar esto simplemente implicaría obtener los datos desde la base de datos utilizando un DQL o el método find() que vimos en el capítulo anterior antes de pasarlo al método createForm().</div></div>
<p>El código que debe contener nuestro action es muy sencillo. Primeramente creamos un objeto Article y luego, por medio del método <strong>$this-&gt;createForm()</strong> invocamos a nuestro objeto <span style="text-decoration: underline;">ArticleType</span> pasándole nuestro objeto recién creado <span style="text-decoration: underline;">$articulo,</span> devolviéndonos un objeto de tipo formuario. Finalmente invocamos a la vista <span style="text-decoration: underline;">como siempre hacemos</span> y pasamos como parámetro el resultado de ejecutar $form-&gt;createView().</p>
<p>Con esto ya seremos capaces de ver el código de nuestra vista  <strong>MDWDemoBundle:Articulos:new.html.twig</strong> que de acuerdo a este nombre lógico debemos crear el archivo new.html.twig dentro de la carpeta src/MDW/DemoBundle/Resources/views/Articulos/ con el siguiente código:</p>
<pre>&lt;form action="{{ path('articulo_new') }}" method="post"&gt;
    {{ form_widget(form) }}
    &lt;input type="submit" /&gt;
&lt;/form&gt;</pre>
<p>La creación de la etiqueta formulario la hacemos normalmente así como también el botón de submit. Lo único importante aquí es que el action del form debe apuntar a la misma página por lo que creamos el link por medio de path(&#8216;articulo_new&#8217;).</p>
<p>La parte mágica está en {{ form_widget(form) }} donde, por medio de form_widget y Twig, pasamos como argumento la variable que nuestro action nos ha enviado y se imprime en la página el código necesario para nuestro formulario. Es decir que veremos el formulario al ingresar a la dirección:  <a href="http://localhost/Symfony/web/app_dev.php/articulo/new" target="_blank">http://localhost/Symfony/web/app_dev.php/articulo/new</a></p>
<p><img class="aligncenter" src="https://lh3.googleusercontent.com/-6AqVL9JpQ6s/T5b-A-i1DyI/AAAAAAAAAVU/NW5ePFHP_YE/s800/form1.png" alt="" width="198" height="122" /></p>
<p>Si miramos el código HTML veremos lo siguiente:</p>
<pre>&lt;form action="/Symfony/web/app_dev.php/articulo/new" method="post"&gt;
    &lt;div id="article_form"&gt;
        &lt;input type="hidden" id="article_form__token" name="article_form[_token]" value="62bc1a503b32de46b8755e9a5f5d8855bc8eb877" /&gt;
        &lt;div&gt;
            &lt;label for="article_form_title" class=" required"&gt;Title&lt;/label&gt;
            &lt;input type="text" id="article_form_title" name="article_form[title]" required="required" maxlength="20" /&gt;
        &lt;/div&gt;
       &lt;div&gt;
            &lt;label for="article_form_author" class=" required"&gt;Author&lt;/label&gt;
            &lt;input type="text" id="article_form_author" name="article_form[author]" required="required" maxlength="255" /&gt;
       &lt;/div&gt;
       &lt;div&gt;
             &lt;label class=" required"&gt;Created&lt;/label&gt;
             &lt;div id="article_form_created"&gt;
                 &lt;select id="article_form_created_year" name="article_form[created][year]" required="required"&gt;
                     &lt;option value="2007"&gt;2007&lt;/option&gt;
                     &lt;option value="2008"&gt;2008&lt;/option&gt;
                     ...
                 &lt;/select&gt;
             &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;input type="submit" /&gt;

&lt;/form&gt;</pre>
<div class="tipexperto"><h3>Nota</h3> <div class="tipcont">Muy importante es notar que a parte de los campos que hemos agregado para que sean mostrados en el $builder, también se muestra un campo article_form[_token] con un valor aleatorio. Esto lo hace automáticamente para luchar contra uno de los ataques más usados por los hackers llamado <a href="http://es.wikipedia.org/wiki/Cross_Site_Request_Forgery" target="_blank">CSRF</a>. Con eso ya vemos como Symfony nos propone ya un estándar de seguridad. A esta seguridad también se suma que por medio de Doctrine también tenemos validado los problemas de SQL Injection.</div></div>
<p>Si miramos el código podemos notar los atributos &#8220;name&#8221; como los explicamos arriba y también vemos que mágicamente el campo &#8220;created&#8221; se muestra como un campo para seleccionar una fecha. Esto es debido a que el framework reconoce el tipo de input a mostrar ya que sabe, por medio del objeto Articles, que esa propiedad es una fecha. Esto es tremendamente útil ya que muchas veces podría ya reconocer que type agregarle a las etiquetas input, pero si necesitamos definir por nosotros mismos el atributo type lo hacemos agregando un segundo argumento al momento de agregar el campo al $builder:</p>
<pre>public function buildForm(FormBuilder $builder, array $options)
{
    $builder-&gt;add('title')
        -&gt;add('author', 'checkbox')
        -&gt;add('created');
}</pre>
<p>Mientras que si necesitamos hacer que un campo no sea obligatorio lo hacemos enviando un array como tercer argumento ya que por defecto todos los campos son puestos como requeridos con validaciones HTML5:</p>
<pre>public function buildForm(FormBuilder $builder, array $options)
{
    $builder-&gt;add('title')
        -&gt;add('author', 'text', array('required' =&gt; false))
        -&gt;add('created');
}</pre>
<p>Como vemos el formulario HTML es impreso directamente en la página usando el {{ form_widget(form) }} incluyendo divs que nos ayudarán a formatear por medio de CSS y mejorar la estructura de mismo pero en caso de querer crear formularios más complejos en diseño también se cuentan con las siguientes opciones que para no extender mucho este capítulo lo veremos quizá en otra entrega:</p>
<ul>
<li><strong>form_errors(form):</strong> Renderiza lo errores que se encuentren en el formulario.</li>
<li><strong>form_rest(form):</strong> Renderiza los campos de formulario que no hayan sido agregados manualmente con el form_row.</li>
<li><strong>form_row(form.field):</strong> Renderiza un campo específico dentro de un div.</li>
<li><strong>form_errors(form.field):</strong> Renderiza el error para un campo específico.</li>
<li><strong>form_label(form.field):</strong> Renderiza la etiqueta label para un campo específico.</li>
<li><strong>form_widget(form.field):</strong> Renderiza un campo específico.</li>
</ul>
<h4>Procesamiento del Formulario</h4>
<p>Ahora que ya vimos como mostrar el formulario en la página y habiendo dicho el action de un form va al mismo action para ser procesado, entremos en detalle de las modificaciones que tenemos que tener en cuenta en el código original dentro del método newAction().</p>
<p>Lo primero que tenemos que pensar es que si para procesar el formulario llamamos al mismo action, ¿Cómo sabemos cuándo mostrar el formulario y cuándo procesarlo?. La respuesta es bien sencilla, cuando el request fue de tipo GET lo deberíamos de mostrar pero en caso de que se haya dado click en el botón submit se ejecuta un request de tipo POST y por lo tanto se debería procesar. Veamos el código modificado de nuestro newAction():</p>
<pre>public function newAction()
{
    //-- Obtenemos el request que contendrá los datos
    $request = $this-&gt;getRequest();

    $articulo = new Articles();
    $form = $this-&gt;createForm(new ArticleType(), $articulo);

    //-- En caso de que el request haya sido invocado por POST
    //   procesaremos el formulario
    if($request-&gt;getMethod() == 'POST')
    {
        //-- Pasamos el request el método bindRequest() del objeto 
        //   formulario el cual obtiene los datos del formulario
        //   y los carga dentro del objeto Article que está contenido
        //   también dentro del objeto Type
        $form-&gt;bindRequest($request);

        //-- Con esto nuestro formulario ya es capaz de decirnos si
        //   los dato son válidos o no y en caso de ser así
        if($form-&gt;isValid())
        {
            //-- Procesamos los datos que ya están automáticamente
            //   cargados dentro de nuestra variable $articulo, ya sea
            //   grabándolos en la base de datos, enviando un mail, etc

            //-- Finalmente, al finalizar el procesamiento, siempre es
            //   importante realizar una redirección para no tener el
            //   problema de que al intentar actualizar el navegador
            //   nos dice que lo datos se deben volver a reenviar. En
            //   este caso iremos a la página del listado de artículos
            return $this-&gt;redirect($this-&gt;generateURL('articulos'));
        }
    }
    return $this-&gt;render('MDWDemoBundle:Articulos:new.html.twig', array(
        'form' =&gt; $form-&gt;createView(),
    ));
}</pre>
<p>Como vemos en las explicaciones del código casi todo es automáticamente realizado por el objeto ArticleType quién al conocer el request ya nos devuelve el mismo objeto original $articulo que le fue entregado en el createForm(new ArticleType(), $articulo);.</p>
<p>En caso de que los datos no sean válidos y el método isValid() retorne false seguirá el hasta mostrar nuevamente el formulario llamando al método $this-&gt;render() y el {{ form_widget(form) }} puesto en nuestra misma vista se encargará de mostrar los errores de validación.</p>
<div class="tipexperto"><h3>Nota</h3> <div class="tipcont">Symfony2 agrega las validaciones de los formularios en HTML5 y del lado del servidor. Si el navegador no soporta las validaciones por medio de HTML5 el método isValid() lo valida en el servidor y al retornar la respuesta por el método render() se mostrarán los mensajes de validación del servidor. Puede que tu navegador ya acepte las validaciones HTML5 por lo que al intentar enviar los datos no notes la validación del lado del servidor aunque lo mismo se están realizando.</p>
<p>Por ejemplo el campo $title está puesto como &lt;input type=&#8221;text&#8221; id=&#8221;article_form_title&#8221; name=&#8221;article_form[title]&#8221; <strong>required=&#8221;required&#8221;</strong> <strong>maxlength=&#8221;255&#8243;</strong> <strong>pattern=&#8221;.{10,255}&#8221;</strong> /&gt; donde se puede ver que las validaciones de HTML5 fueron ya puestas.</p>
<p>Si no tienes un navegador que NO soporte HTML5 para probar como se muestran los mensajes de validación del servidor puedes, utilizando el Firebug del Firefox, eliminar el texto <strong>required=&#8221;required&#8221;</strong> <strong>maxlength=&#8221;255&#8243;</strong> <strong>pattern=&#8221;.{10,255}&#8221;</strong> de la etiqueta input y luego presionar el botón de submit <img src='http://www.maestrosdelweb.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Como verás, los hackers que quieren usar esta técnica también serán detenidos por las validaciones del servidor.</div></div>
<h3>Resumen Final</h3>
<p>En este capítulo hemos trabajado muchísimo viendo dos temas sumamente importantes: la validación de los Entities y los formularios.</p>
<p>Para las validaciones hemos hablado sobre los @Asserts, simples anotaciones que realizan validaciones poderosas con poco código y vemos que Symfony2 ya nos provee de la gran mayoría que necesitaremos usar.</p>
<p>Hablando sobre los formularios hemos notado la gran diferencia de diseñar los formularios y programar los formularios por medio de clases. Me gusta decir que en Symfony, el concepto de un formulario NO es simplemente introducción de texto sino introducción de texto VÁLIDO para la aplicación, libre de los problemas que hoy se tienen al crear un formulario a mano y tener que recordar pelear con ataques CSRF, XSS, SQL Injection y cambios en caliente con herramientas como Firebug.</p>
<p>El sub-framework de formularios es uno de los que más me hicieron sentir la diferencia entre usar un framework y no hacerlo y todavía hay muchas otras herramientas que nos permite usar como los formularios embebidos.</p>
<p>En el primer capítulo de esta guía hablamos sobre que uno de los objetivos de Symfony es plantear que cada cosa debe ir en su lugar, respetando el concepto del MVC. Con esto podemos ver que no solo podríamos tener un equipo de desarrollo, con personas expertas en cada área, trabajando con el modelado, otras con los controladores y a los diseñadores en la vista, sino que también podríamos hablar de personas que trabajen netamente en la creación de los formularios de la aplicación.</p>
<p>En el siguiente capítulo hablaremos sobre la integración de Ajax en nuestras aplicaciones hechas con Symfony2.</p>
<hr /><p style="height: 64px;"><img alt='Juan Ardissone' src='http://0.gravatar.com/avatar/2b99c333759f4f7f2fa8b1b1e1ca4804?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Juan Ardissone</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-validacion-de-datos-y-creacion-de-formularios/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-validacion-de-datos-y-creacion-de-formularios/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/curso-symfony2-validacion-de-datos-y-creacion-de-formularios/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com//lh3.googleusercontent.com/-6AqVL9JpQ6s/T5b-A-i1DyI/AAAAAAAAAVU/NW5ePFHP_YE/s800/form1.png" />
		<media:content url="http://www.maestrosdelweb.com//lh3.googleusercontent.com/-6AqVL9JpQ6s/T5b-A-i1DyI/AAAAAAAAAVU/NW5ePFHP_YE/s800/form1.png" medium="image" />
		<media:content url="http://0.gravatar.com/avatar/2b99c333759f4f7f2fa8b1b1e1ca4804?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Juan Ardissone</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Curso Django: Instalación y primera aplicación</title>
		<link>http://www.maestrosdelweb.com/editorial/curso-django-instalacion-y-primera-aplicacion/</link>
		<comments>http://www.maestrosdelweb.com/editorial/curso-django-instalacion-y-primera-aplicacion/#comments</comments>
		<pubDate>Mon, 23 Apr 2012 07:00:50 +0000</pubDate>
		<dc:creator>Sergio Infante Montero</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[Editorial]]></category>
		<category><![CDATA[curso django]]></category>
		<category><![CDATA[descarga django]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[instalación django]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24036</guid>
		<description><![CDATA[Requisitos para su instalación Django es un framework hecho en Python, por lo tanto se necesita que hayas previamente instalado Python (2.6 o 2.7) y tengas a la mano tu editor de texto favorito. Si no sabes que editores de texto usar, o como instalar Python lee la primera parte de la Guia Python, con [...]]]></description>
			<content:encoded><![CDATA[<h2>Requisitos para su instalación</h2>
<p>Django es un framework hecho en Python, por lo tanto se necesita que hayas previamente instalado <a href="http://www.maestrosdelweb.com/editorial/guia-python/">Python</a> (2.6 o 2.7) y tengas a la mano tu editor de texto favorito. Si no sabes que editores de texto usar, o como instalar Python lee la <a href="http://www.maestrosdelweb.com/editorial/guia-python/">primera parte de la Guia Python</a>, con esto es suficiente para empezar a trabajar.</p>
<div class="tipexperto"><h3>Nota: Django y Python 3.0</h3> <div class="tipcont"> Django no funciona con Python 3.0 actualmente, debido a incompatibilidades con el intérprete de Python.</div></div>
<p>Al estar hecho en Python, sería bueno tener en cuenta la sintaxis y fundamentos de este lenguaje, así que si aún no lo sabes y quieres reforzar tus conocimientos, revisa <a href="http://www.maestrosdelweb.com/guias/#guia-python" title="Guía de Python en Maestros del Web">la guía de Python</a> primero antes de continuar con esta, o da un vistazo a este video de <a href="http://mejorando.la/" title="Mejorando la Web">mejorando.la</a></p>
<span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='640' height='390' src='http://www.youtube.com/embed/wp4DgNbGAUI?version=3&amp;rel=1&amp;fs=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;wmode=transparent' frameborder='0'></iframe></span>
<h2>Obtener Django</h2>
<p>Para obtener Django se puede:</p>
<ul>
<li><strong>Descargar la versión estable oficial más reciente</strong>, desde el <a href="https://www.djangoproject.com/download/">sitio oficial de Django</a> y descomprimir el archivo, debe aparecer una carpeta con el nombre de Django seguido del número de la versión bajada. (Para esta guía usaremos la versión 1.4)</li>
<li><strong>Obtener la versión de desarrollo desde el repositorio de Django</strong>, para ello se debe usar Subversión, de esta manera:
<div class="codigo">
<pre>
svn co http://code.djangoproject.com/svn/django/trunk/</pre>
</div>
<p>Una vez que se ha obtenido Django, es momento de instalarlo.</li>
</ul>
<h3>Python y las variables de entorno en Windows</h3>
<p>Los usuarios de Windows deben asegurarse de tener Python dentro de las variables de entorno, esto servirá para poder instalar Django y usarlo fácilmente. Si no sabes como hacerlo, mira el siguiente vídeo:</p>
<span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='640' height='390' src='http://www.youtube.com/embed/ciYoJPw9ORg?version=3&amp;rel=1&amp;fs=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;wmode=transparent' frameborder='0'></iframe></span>
<h2>Instalar Django</h2>
<p>Una vez que se descomprime el archivo descargado, debemos acceder a la carpeta desde una terminal o ventana de comandos (en caso de los usuarios de Windows). Suponiendo que la versión que elegimos es la 1.4, se tendría que digitar:</p>
<div class="codigo">
<pre> cd Django-1.4</pre>
</div>
<p>Ya en la carpeta de instalación de Django, se debe digitar la siguiente instrucción: (Debes de tener permisos de administrador)</p>
<div class="codigo">
<pre> python setup.py install</pre>
</div>
<p>Si usas Ubuntu GNU/Linux, sería algo así:</p>
<div class="codigo">
<pre>sudo python setup.py install</pre>
</div>
<p>Listo eso es todo, ya tienes Django instalado. Si se desea mayor información de como instalarlo o quizás algunas otras opciones, siempre está la documentación del mismo proyecto para guiarnos. Aquí pueden encontrar la<a href="https://docs.djangoproject.com/en/1.4/topics/install/"> Guía completa de instalación de Django</a>.</p>
<p>Si usas OS X Lion, quizás lo más recomendado sería instalar Django usando pip:<br />
Primero, debemos tener Setup Tools para instalarlo, lo descargamos, lo descomprimimos y dentro del directorio (via el terminal)</p>
<div class='codigo'>
<pre> sudo python setup.py install </pre>
</div>
<p>Una vez con Setup Tools instalado usamos pip:</p>
<div class='codigo'>
<pre> sudo pip install Django </pre>
</div>
<h2>Primer proyecto</h2>
<p>Antes de empezar es bueno aclarar que la versión que vamos a utilizar en esta guía es la más reciente (1.4), y varias cosas han cambiado, la información que podrían encontrar en Internet probablemente se encuentre desactualizada.</p>
<p>Para crear nuestro primer proyecto, abrimos una terminal (o ventana de comandos si asi lo conoces en windows), nos ubicamos en la carpeta en donde queremos crear nuestro proyecto y digitamos:</p>
<div class="codigo">
<pre>django-admin.py startproject recetario</pre>
</div>
<p>Esta instrucción creará dos directorios con el nombre del proyecto (en este caso: recetario) y 5 archivos distribuidos de la siguiente manera:</p>
<ul>
<li>manage.py</li>
<li>recetario
<ul>
<li>__init__.py</li>
<li>settings.py</li>
<li>urls.py</li>
<li>wsgi.py</li>
</ul>
</li>
</ul>
<p>Para ver que el proyecto está funcionando en la terminal debemos escribir:</p>
<div class="codigo">
<pre>python manage.py runserver</pre>
</div>
<p>Al ejecutar esa instrucción debemos visualizar un resultado como el siguiente:</p>
<div id="attachment_24070" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-runserver.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-runserver-450x113.png" alt="python manage.py runserver" width="450" height="113" class="size-medium wp-image-24070" /></a><p class="wp-caption-text">python manage.py runserver</p></div>
<p>Abrimos el navegador web la dirección <strong>http://127.0.0.1:8000/</strong> y debemos ver lo siguiente:</p>
<div id="attachment_24069" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-primer-web.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-primer-web-450x226.png" alt="Django http://127.0.0.1:8000" width="450" height="226" class="size-medium wp-image-24069" /></a><p class="wp-caption-text">Django http://127.0.0.1:8000</p></div>
<p>Ya tenemos nuestro proyecto creado. <img src='http://www.maestrosdelweb.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>En el caso de que nos salga un error porque el puerto asignado esta en uso como la siguiente imagen:</p>
<div id="attachment_24066" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-error-port.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-error-port-450x108.png" alt="Django en puertos en uso" width="450" height="108" class="size-medium wp-image-24066" /></a><p class="wp-caption-text">Django en puertos en uso</p></div>
<p>sólo debemos indicar que puerto usaremos para lanzar el servicio, por ejemplo si se desea usar el puerto 8888 entonces se tendría que digitar:</p>
<div class="codigo">
<pre>python manage.py runserver 8888</pre>
</div>
<p>Usaríamos la dirección <strong>http://127.0.0.1:8888/</strong> y tendríamos como resultado lo siguiente: </p>
<div id="attachment_24062" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-8888.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-8888-450x116.png" alt="Django en un puerto 8888" width="450" height="116" class="size-medium wp-image-24062" /></a><p class="wp-caption-text">Django en un puerto 8888</p></div>
<p>Cada proyecto necesita de aplicaciones donde se puedan gestionar los modelos y las vistas. Un proyecto puede tener muchas aplicaciones:</p>
<h2>Primera aplicación</h2>
<p>Para crear nuestra primer aplicación, desde la terminal y en la carpeta del proyecto, debemos digitar:</p>
<div class="codigo">
<pre>python manage.py startapp principal</pre>
</div>
<p>Esto creará un directorio y cuatro archivos más, lo que nos dejaría con una estructura de archivos como esta:</p>
<ul>
<li>manage.py</li>
<li>recetario
<ul>
<li>__init__.py</li>
<li>settings.py</li>
<li>urls.py</li>
<li>wsgi.py</li>
</ul>
</li>
<li>principal
<ul>
<li>__init__.py</li>
<li>models.py</li>
<li>test.py</li>
<li>views.py</li>
</ul>
</li>
</ul>
<h2>El poderoso settings.py</h2>
<p>Una parte muy importante del proyecto es el archivo <strong>settings.py</strong>, este archivo permite configurar la conexión a la base de datos, la zona horaria, el idioma, los directorios principales del proyecto, las aplicaciones del proyecto, entre otras cosas.</p>
<p>Aprender a configurar este archivo permite optimizar el funcionamiento del proyecto, veremos las instrucciones principales a configurar:</p>
<h4>Codificación de caracteres</h4>
<p>Nuestro idioma esta lleno de caracteres especiales como las tildes y las eñes que son las más comunes, la primera sugerencia para manejar esto eficientemente en django debemos agregar la siguiente línea al archivo settings.py</p>
<div class="codigo">
<pre>#encoding:utf-8</pre>
</div>
<h4>Ruta del proyecto</h4>
<p>Una configuración importante es configurar la ruta del proyecto, esto permitirá lanzar la aplicación desde cualquier directorio y mover el proyecto a cualquier computador con Django instalado. Para ello debemos escribir las siguientes líneas en el archivo settings.py:</p>
<div class="codigo">
<pre>
# Identificando la ruta del proyecto
import os
RUTA_PROYECTO = os.path.dirname(os.path.realpath(__file__))
</pre>
</div>
<div class='tipexperto'>
<h3>Ruta del proyecto</h3>
<div class='tipcont'>Si no se configura la ruta del proyecto, cada vez que se cambia de directorio o de PC, se tendrá que cambiar las rutas de las plantillas, archivos estáticos y directorio de subida de contenido de los usuarios.</div>
</div>
<h4>Administradores</h4>
<p>Cuando Django tiene la opción de DEBUG=False, las notificaciones de error de código deben ser enviadas vía correo electrónico a los administradores, junto con<br />
los detalles completos del error. Para poner los datos de los administradores debemos buscar la siguiente porción:</p>
<div class="codigo">
<pre>
ADMINS = (
    # ('Your Name', 'your_email@example.com'),
)
</pre>
</div>
<p>Y modificarla para que quede con los nombres de los administradores en forma de tupla, en mi caso lo dejaré así:</p>
<div class="codigo">
<pre>ADMINS = (
    ('Sergio Infante Montero', 'raulsergio9@gmail.com'),
)
</pre>
</div>
<h4>Configuración de la base de datos</h4>
<p>También podemos configurar la conexión a la base de datos según nuestras necesidades, Django soporta de manera predeterminada la conexión con postgresql, mysql, sqlite3 y oracle. En nuestro proyecto usaremos sqlite3.</p>
<p>Debemos buscar la siguiente sección del archivo:</p>
<div class="codigo">
<pre>
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': '',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}
</pre>
</div>
<p>Y dejarla de la siguiente manera:</p>
<div class="codigo">
<pre>
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'recetario.db',          # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}
</pre>
</div>
<h4>Zona Horaria</h4>
<p>Django permite configurar la zona horaria del proyecto, <a href="http://en.wikipedia.org/wiki/List_of_tz_zones_by_name" title="Lista de zonas horarias">la lista de zonas horarias disponibles</a> se pueden encontrar en la wikipedia. Para configurar debemos buscar lo siguiente:</p>
<div class="codigo">
<pre>TIME_ZONE = 'America/Chicago'</pre>
</div>
<p>Yo lo configurare en la zona horaria de Lima/Perú, así que lo modificare de esta forma:</p>
<div class="codigo">
<pre>TIME_ZONE = 'America/Lima'</pre>
</div>
<h4>Configuración del idioma</h4>
<p>Django también permite configurar el idioma que usará de manera predeterminada para su funcionamiento, para configurar esto debemos buscar lo siguiente:</p>
<div class="codigo">
<pre>LANGUAGE_CODE = 'en-us'</pre>
</div>
<p>Se puede consultar la <a href="http://www.i18nguy.com/unicode/language-identifiers.html" title="Lista de idiomas disponibles">lista de idiomas disponibles</a> para adecuarlo a nuestras necesidades, yo lo configurare como español de Perú:</p>
<div class="codigo">
<pre>LANGUAGE_CODE = 'es-PE'</pre>
</div>
<h3>Aplicaciones instaladas</h3>
<p>Un proyecto en Django necesita de aplicaciones, algunas ya vienen configuradas de manera predeterminada. En nuestro proyecto usaremos la aplicación de administración y su documentación, estas ya vienen construidas, y también nuestra primera aplicación creada líneas arriba, llamada principal. Para habilitar estas aplicaciones debemos buscar la siguiente sección que se encuentra casi al final del archivo <strong>settings.py</strong></p>
<div class="codigo">
<pre>
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',
)
</pre>
</div>
<p>Y modificarlas de la siguiente manera:</p>
<div class="codigo">
<pre>
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'django.contrib.admindocs',
    'principal',
)
</pre>
</div>
<h3>Otras opciones de settings.py</h3>
<p>Existen otras configuraciones que iremos modificando durante el desarrollo del curso, como el directorio de plantillas, el contenido estático, los archivos cargados por los usuarios, entre otras. Por ahora con estas instrucciones tenemos lo básico para continuar con nuestro proyecto.</p>
<h2>Creación de la base de datos</h2>
<p>Hasta el momento no se ha creado la base de datos o las tablas predeterminadas del proyecto, solo se ha configurado los parametros de conexión. Para crear la base de datos, debemos digitar desde la terminal o ventana de comandos, la siguiente instrucción (recordar que debemos estar en la carpeta de proyecto para que todo se realice correctamente):</p>
<div class="codigo">
<pre>python manage.py syncdb</pre>
</div>
<p>Esta instrucción deberá mostrar el siguiente resultado:</p>
<div id="attachment_24068" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-primer-syncdb.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-primer-syncdb-450x135.png" alt="python manage.py syncdb" width="450" height="135" class="size-medium wp-image-24068" /></a><p class="wp-caption-text">python manage.py syncdb</p></div>
<p>Hay una pregunta que debemos responder, se refiere a la creación de un superusuario (un administrador del proyecto), para lo cual respondemos: yes (en caso de responder negativamente, no podremos usar inmediatamente el administrador predeterminado de Django). Luego de ello completamos la información que nos solicita.</p>
<div id="attachment_24071" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-superuser.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-superuser-450x94.png" alt="Django creación del super usuario" width="450" height="94" class="size-medium wp-image-24071" /></a><p class="wp-caption-text">Django creación del super usuario</p></div>
<p>Al finalizar ya estará creada la base de datos, como en este proyecto se usara sqlite3, debera aparecer un archivo nuevo llamado recetario.db, este contiene las tablas y los datos iniciales del proyecto.</p>
<h2>Las direcciones URL del proyecto</h2>
<p>Para poder visualizar los cambios que hicimos y la interfaz administrativa de Django, aún falta modificar un archivo mas, este es: urls.py (recordar que este archivo se encuentra dentro del directorio recetario). Este archivo contiene lo siguiente:</p>
<div class="codigo">
<pre>
from django.conf.urls import patterns, include, url

# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'recetario.views.home', name='home'),
    # url(r'^recetario/', include('recetario.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    # url(r'^admin/', include(admin.site.urls)),
)
</pre>
</div>
<p>Debemos dejarlo de esta manera:</p>
<div class="codigo">
<pre>
from django.conf.urls import patterns, include, url
from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns('',
    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    url(r'^admin/', include(admin.site.urls)),
)
</pre>
</div>
<h2>Ejecución del proyecto</h2>
<p>Una vez que tenemos todo listo y configurado, debemos nuevamente iniciar el servidor de desarrollo que tiene el proyecto. Ya hicimos esto al principio, solo debemos digitar desde la terminal nuevamente (dentro del directorio del proyecto):</p>
<div class="codigo">
<pre>python manage.py runserver</pre>
</div>
<p>Lucirá de esta manera:</p>
<div id="attachment_24067" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-first-web.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-first-web-450x226.png" alt="Django 404 predeterminado" width="450" height="226" class="size-medium wp-image-24067" /></a><p class="wp-caption-text">Django 404 predeterminado</p></div>
<p>Nos muestra un error 404, luego veremos el por qué. Para ingresar a la interfaz administrativa que ya viene construida con Django, ingresaremos a la dirección: <strong>http://127.0.0.1:8000/admin</strong>, en donde debemos poner el nombre del superusuario y su respectiva contraseña, creados anteriormente (líneas arriba) con la opción syncdb.</p>
<div id="attachment_24064" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-admin-login.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-admin-login-450x249.png" alt="Django admin login" width="450" height="249" class="size-medium wp-image-24064" /></a><p class="wp-caption-text">Django admin login</p></div>
<p>Si todo fue correcto debemos visualizar la interfaz administrativa:</p>
<div id="attachment_24063" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.maestrosdelweb.com/images/2012/04/django-admin-dashboard.png"><img src="http://www.maestrosdelweb.com/images/2012/04/django-admin-dashboard-450x255.png" alt="Interfaz administrativa predeterminada de Django" width="450" height="255" class="size-medium wp-image-24063" /></a><p class="wp-caption-text">Interfaz administrativa predeterminada de Django</p></div>
<p>Nuestro primer proyecto ya se encuentra configurado para continuar con la construcción de los modelos. Sin embargo antes de ello debemos entender como funciona Django, ese será nuestro próximo capítulo: <strong>Entendiendo como trabaja Django.</strong></p>
<div class='tipexperto'>
<h3>Repositorio del proyecto</h3>
<div class='tipcont'><a href="http://neosergio.github.com/recetario_mdw" title="Recetario para Maestros del Web en Github">El proyecto se encuentra en github</a> por si te perdiste de algo y deseas ver algún archivo del mismo.</div>
</div>
<p>Hasta la próxima semana <img src='http://www.maestrosdelweb.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<hr /><p style="height: 64px;"><img alt='Sergio Infante Montero' src='http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Sergio Infante Montero</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/curso-django-instalacion-y-primera-aplicacion/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/curso-django-instalacion-y-primera-aplicacion/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/curso-django-instalacion-y-primera-aplicacion/feed/</wfw:commentRss>
		<slash:comments>97</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-runserver-150x150.png" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-runserver.png" medium="image">
			<media:title type="html">django-runserver</media:title>
			<media:description type="html">python manage.py runserver</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-runserver-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-primer-web.png" medium="image">
			<media:title type="html">django-primer-web</media:title>
			<media:description type="html">Django http://127.0.0.1:8000</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-primer-web-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-error-port.png" medium="image">
			<media:title type="html">django-error-port</media:title>
			<media:description type="html">Django en puertos en uso</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-error-port-150x137.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-8888.png" medium="image">
			<media:title type="html">django-8888</media:title>
			<media:description type="html">Django en un puerto 8888</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-8888-150x146.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-primer-syncdb.png" medium="image">
			<media:title type="html">django-primer-syncdb</media:title>
			<media:description type="html">python manage.py syncdb</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-primer-syncdb-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-superuser.png" medium="image">
			<media:title type="html">django-superuser</media:title>
			<media:description type="html">Django creación del super usuario</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-superuser-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-first-web.png" medium="image">
			<media:title type="html">django-first-web</media:title>
			<media:description type="html">Django 404 predeterminado</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-first-web-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-admin-login.png" medium="image">
			<media:title type="html">django-admin-login</media:title>
			<media:description type="html">Django admin login</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-admin-login-150x150.png" />
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/django-admin-dashboard.png" medium="image">
			<media:title type="html">django-admin-dashboard</media:title>
			<media:description type="html">Interfaz administrativa predeterminada de Django</media:description>
			<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/django-admin-dashboard-150x150.png" />
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/3ca2b43e8aedb28a82fdca67e28281a1?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Sergio Infante Montero</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
		<item>
		<title>Es viernes: Educación en línea y cursos gratuitos</title>
		<link>http://www.maestrosdelweb.com/editorial/educacion-en-linea-curso-gratuitos/</link>
		<comments>http://www.maestrosdelweb.com/editorial/educacion-en-linea-curso-gratuitos/#comments</comments>
		<pubDate>Fri, 20 Apr 2012 16:53:37 +0000</pubDate>
		<dc:creator>Stephanie Falla Aroche</dc:creator>
				<category><![CDATA[Editorial]]></category>
		<category><![CDATA[Productividad]]></category>
		<category><![CDATA[Capacitación]]></category>
		<category><![CDATA[cursos gratuitos]]></category>
		<category><![CDATA[educacion]]></category>
		<category><![CDATA[es viernes!]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/?p=24178</guid>
		<description><![CDATA[En el mundo de la tecnología desarrolladores y diseñadores expresan su descontento con el contenido de los cursos que se imparte en las universidades. Señalan las carencias del sistema, los lenguajes de programación, herramientas y procesos obsoletos no aplicables a la vida real. Sin embargo, en la actualidad tenemos recursos en línea para aprender de [...]]]></description>
			<content:encoded><![CDATA[<p>En el mundo de la tecnología desarrolladores y diseñadores expresan su descontento con el contenido de los cursos que se imparte en las universidades. Señalan las carencias del sistema, los lenguajes de programación, herramientas y procesos obsoletos no aplicables a la vida real. Sin embargo, en la actualidad tenemos recursos en línea para aprender de forma independiente pero son pocos los autodidactas que ponen disciplina al proceso de aprendizaje colaborativo para ser competitivos en su campo.</p>
<p><a href="http://www.maestrosdelweb.com/guias/"><img src="http://www.maestrosdelweb.com/images/2012/04/cursos.jpg" alt="Cursos Maestros del Web" /></a></p>
<p>Quiero compartir con ustedes algunos de los recursos que he encontrado en la web para capacitarme y también compartir los nuevo cursos que hemos diseñado para satisfacer esas necesidades que la comunidad ha expresado. Es fácil criticar al sistema y justificar nuestra carencias por la educación poco vigente, pero considero que ante esa problemática que experimenta Latinoamérica en general, debemos aprovechar mejor las herramientas actuales y disciplinarnos para iniciar un proceso según nuestras necesidades y que nos llene de satisfacción.</p>
<h3>Cursos, Guías y Streaming</h3>
<p>En línea existen muchas opciones para actualizarnos, pero lo más importante es cómo logramos la disciplina necesaria para aprovechar esos recursos. Además, nuestros proyectos tienen el mismo objetivo de proveer de información y conocimiento, por ello me gustaría que revisen los cursos que tenemos disponibles. </p>
<ul>
<li><a href="http://www.maestrosdelweb.com/editorial/plataformas-educativas-web/">Plataformas educativas:</a> Existen muchas plataformas diseñadas para ofrecer nuevas alternativas de educación y muchas de ellas utilizan el vídeo como un recurso primario, además de ofrecer alternativas de evaluación y ejercicios.</li>
<li><a href="http://www.maestrosdelweb.com/editorial/universidades-latino-america-recursos-gratuito/">Recursos gratuitos:</a> Además, las universidades al rededor del mundo están ofreciendo desde sus sitios conocimiento abierto, recursos y hasta cursos. </li>
<li><a href="http://www.maestrosdelweb.com/editorial/curso-django-introduccion">Curso Django:</a> El framework para perfeccionista, un curso diseñado para agilizar el desarrollo, con muchas ventajas y características para un trabajo más simple y eficiente. El curso arranca esta semana y puedes revisar el contenido completo. </li>
<li><a href="http://www.maestrosdelweb.com/editorial/curso-symfony2-introduccion-instalacion">Curso Symfony:</a> El framework PHP orientado a objetos, fue diseñado para optimizar el desarrollo de aplicaciones Web y tienes un curso completo a tu disposición. </li>
<li><a href="http://www.maestrosdelweb.com/editorial/curso-android/">Curso Android:</a> Uno de nuestros cursos más famoso, con más de 100 mil lecturas y puedes descargarlo completo en diversos formatos. Además, puede hacer tus consultas en línea.</li>
<li><a href="http://www.maestrosdelweb.com/guias/">Guías:</a> Desde que arrancamos con nuestra sección de guías, nuestro catálogo sigue creciendo y lo que pretende es proveer de información y conocimiento para que los autodidactas sigan aprendiendo y creando contenido colaborativo a través de sus comentarios y sugerencias. Los invitamos a que descarguen nuestras guías en los hermosos formatos .PDF o los demás formatos.</li>
<li><a href="http://mejorando.la">Mejorando.la:</a> Finalmente quiero invitarte <strong>todos los jueves</strong> a que te conectes a mejorando.la el streaming en donde <a href="http://twitter.com/freddier">@freddier</a>, <a href="http://twitter.com/cvander">@cvander</a> y algunos invitados nos actualizan de las tendencias de la industria, imparten cursos, evaluan proyectos y nos muestran otras opciones de aprendizaje.</li>
</ul>
<p>Esperamos que estos recursos te sirvan como un primer paso para iniciar el proceso de aprendizaje. Recuerda que en ocasiones sólo depende de nosotros, los buenos hábitos y el aprovechar bien el tiempo para canalizar nuestra energía para mejorar y no para sólo quejarnos de lo que el sistema no nos puede proveer. Feliz fin de semana. Enjoy!</p>
<hr /><p style="height: 64px;"><img alt='Stephanie Falla Aroche' src='http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G' class='avatar avatar-64 photo' height='64' width='64' style="float:left;padding:0 5px" /> <strong>Stephanie Falla Aroche</strong> para <a href="http://www.maestrosdelweb.com">Maestros del Web</a>.<br /><a href="http://www.maestrosdelweb.com/editorial/educacion-en-linea-curso-gratuitos/#respond">Agrega tu comentario</a> | <a href="http://www.maestrosdelweb.com/editorial/educacion-en-linea-curso-gratuitos/">Enlace permanente</a> al artículo</p><hr style="clear: both;"/>
		<p><strong>Síguenos en:</strong> <img src="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" style="vertical-align:middle;"> <a href="http://twitter.com/maestros">@maestros</a> | <img style="vertical-align:middle;" src="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png"> <a href="http://facebook.com/maestrosdelweb">Fan page</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/educacion-en-linea-curso-gratuitos/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:thumbnail url="http://www.maestrosdelweb.com/images/2012/04/cursos.jpg" />
		<media:content url="http://www.maestrosdelweb.com/images/2012/04/cursos.jpg" medium="image">
			<media:title type="html">Cursos Maestros del Web</media:title>
		</media:content>
		<media:content url="http://1.gravatar.com/avatar/b9bb861f611cdd39ebb0b17d9a9c0636?s=64&amp;d=http%3A%2F%2Fwww.maestrosdelweb.com%2Fwp-content%2Fthemes%2Fmdw2%2Fimages%2Fno-avatar64.png%3Fs%3D64&amp;r=G" medium="image">
			<media:title type="html">Stephanie Falla Aroche</media:title>
		</media:content>
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/twitter.png" medium="image" />
		<media:content url="http://www.maestrosdelweb.com/diseno/imagenes/facebook.png" medium="image" />
	</item>
	</channel>
</rss>

