Commits

Manuel Kaufmann committed ce0b849

agrego todas las charlas que he dado hasta el momento, aun no tienen historia en
el repositorio ni están ordenadas adecuadamente

Comments (0)

Files changed (44)

+# use glob syntax.
+syntax: glob
+
+*.elc
+*.pyc
+*~
+python/django-trunk
+python/trunk
+python/tutorial
+python/issue.to.solve.txt
+
+# switch to regexp syntax.
+#syntax: regexp
+#^\.pc/
+
Add a comment to this file

django/PyCon_BuenoAires_Sep_2009.ppt

Binary file added.

Add a comment to this file

django/SanLuis-Oct-2008.odp

Binary file added.

Add a comment to this file

django/SanLuis-Oct-2008.pdf

Binary file added.

Add a comment to this file

django/codigo/Django-1.0.tar.gz

Binary file added.

Add a comment to this file

django/codigo/blog/__init__.py

Empty file added.

Add a comment to this file

django/codigo/blog/data.db

Binary file added.

django/codigo/blog/manage.py

+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+    import settings # Assumed to be in the same directory.
+except ImportError:
+    import sys
+    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+    sys.exit(1)
+
+if __name__ == "__main__":
+    execute_manager(settings)
Add a comment to this file

django/codigo/blog/posts/__init__.py

Empty file added.

django/codigo/blog/posts/admin.py

+from blog.posts.models import Post
+from django.contrib import admin
+
+
+admin.site.register(Post)

django/codigo/blog/posts/models.py

+from django.db import models
+
+class Etiqueta(models.Model):
+    nombre = models.CharField(max_length=25)
+
+class Post(models.Model):
+    titulo = models.CharField(max_length=50)
+    contenido = models.TextField()
+    etiquetas = models.ManyToManyField(Etiqueta)
+
+class Comentario(models.Model):
+    autor = models.CharField(max_length=25)
+    contenido = models.TextField()
+    post = models.ForeignKey(Post)
+
+# Formularios
+from django.forms import ModelForm
+
+class PostForm(ModelForm):
+    class Meta:
+        model = Post
+

django/codigo/blog/posts/templates/agregar_post.html

+<html>
+    <head>
+    </head>
+
+    <body>
+        <h2>Agregar post</h2>
+        <form action="." method="post">
+            <table>
+                <p>{{ formulario.as_table }}</p>
+            </table>
+            <input type="submit">
+        </form>
+    </body>
+
+</html>

django/codigo/blog/posts/templates/index.html

+<html>
+    <head>
+    </head>
+
+    <body>
+        <h2>Pagina principal</h2>
+        {% for post in posts %}
+            <h3>{{ post.titulo|upper }}</h3>
+            {% for etiqueta in post.etiquetas.all %}
+                <pre>{{ etiqueta.nombre }}</pre>
+            {% endfor %}
+            <p>{{ post.contenido }}</p>
+            {% for comentario in post.comentario_set.all %}
+                <hr/>
+                <p>Autor: {{ comentario.autor }}</p>
+                <p>Contenido: {{ comentario.contenido }}</p>
+            {% endfor %}
+        {% endfor %}
+    </body>
+
+</html>

django/codigo/blog/posts/views.py

+from django.shortcuts import render_to_response
+from django.http import HttpResponseRedirect
+from django.forms import ModelForm
+from blog.posts.models import PostForm, Post
+
+
+def agregar_post(request):
+        if request.method == 'GET':
+            formulario = PostForm()
+            return render_to_response('agregar_post.html', {'formulario': formulario})
+        else:
+            formulario = PostForm(request.POST)
+            if formulario.is_valid():
+                formulario.save()
+            else:
+                print 'No valido el formulario'
+            return HttpResponseRedirect('/index')
+
+def index(request):
+    if request.method == 'GET':
+        posts = Post.objects.all()
+        return render_to_response('index.html', {'posts': posts})
+
+

django/codigo/blog/settings.py

+# Django settings for blog project.
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+    # ('Your Name', 'your_email@domain.com'),
+)
+
+MANAGERS = ADMINS
+
+DATABASE_ENGINE = 'sqlite3'           # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+DATABASE_NAME = 'data.db'             # Or path to database file if using sqlite3.
+DATABASE_USER = ''             # Not used with sqlite3.
+DATABASE_PASSWORD = ''         # Not used with sqlite3.
+DATABASE_HOST = ''             # Set to empty string for localhost. Not used with sqlite3.
+DATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3.
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'America/Chicago'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# Absolute path to the directory that holds media.
+# Example: "/home/media/media.lawrence.com/"
+MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash if there is a path component (optional in other cases).
+# Examples: "http://media.lawrence.com", "http://example.com/media/"
+MEDIA_URL = ''
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/media/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 'ug(zau3*l=r1%vtqm(ar6wmvmt&4pe!2^%4hb_83jtixkezc83'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+    'django.template.loaders.filesystem.load_template_source',
+    'django.template.loaders.app_directories.load_template_source',
+#     'django.template.loaders.eggs.load_template_source',
+)
+
+MIDDLEWARE_CLASSES = (
+    'django.middleware.common.CommonMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+)
+
+ROOT_URLCONF = 'blog.urls'
+
+TEMPLATE_DIRS = (
+    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+    # Always use forward slashes, even on Windows.
+    # Don't forget to use absolute paths, not relative paths.
+    'posts/templates'
+)
+
+INSTALLED_APPS = (
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.sites',
+    'django.contrib.admin',
+    'blog.posts',
+)

django/codigo/blog/urls.py

+from django.conf.urls.defaults import *
+
+# Uncomment the next two lines to enable the admin:
+from django.contrib import admin
+admin.autodiscover()
+
+urlpatterns = patterns('',
+    # Example:
+    # (r'^blog/', include('blog.foo.urls')),
+
+    # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
+    # to INSTALLED_APPS to enable admin documentation:
+    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
+
+    # Uncomment the next line to enable the admin:
+    (r'^admin/(.*)', admin.site.root),
+    (r'^posts/agregar/$', 'blog.posts.views.agregar_post'),
+    (r'^index/$', 'blog.posts.views.index'),
+
+)

django/contenido.html

+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
+<title>Introducción a Django</title>
+<meta name="author" content="Manuel Kaufmann" />
+<meta name="date" content="jue sep 11 22:17:12 ART 2008" />
+<meta name="copyright" content="GNU Free Document License" />
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 5196 2007-06-03 20:25:28Z wiemann $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin: 0 0 0.5em 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left {
+  clear: left }
+
+img.align-right {
+  clear: right }
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font-family: serif ;
+  font-size: 100% }
+
+pre.literal-block, pre.doctest-block {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+ul.auto-toc {
+  list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="introducci-n-a-django">
+<h1 class="title">Introducción a <a class="reference external" href="http://www.djangoproject.com">Django</a></h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>Manuel Kaufmann</td></tr>
+<tr><th class="docinfo-name">Contact:</th>
+<td><a class="first last reference external" href="mailto:humitos&#64;gmail.com">humitos&#64;gmail.com</a></td></tr>
+<tr><th class="docinfo-name">Revision:</th>
+<td>29</td></tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>jue sep 11 22:17:12 ART 2008</td></tr>
+<tr><th class="docinfo-name">Copyright:</th>
+<td>GNU Free Document License</td></tr>
+</tbody>
+</table>
+<div class="section" id="qu-es-django">
+<h1>¿Qué es Django?</h1>
+<p>Django es un <tt class="docutils literal"><span class="pre">framework</span></tt> de alto nivel hecho en <a class="reference external" href="http://www.python.org">Python</a> para el desarrollo de
+páginas web y a su vez fomenta el desarrollo de aplicaciones rápidas y limpias.
+Este framework nos permite preocuparnos únicamente por las partes específicas
+de nuestro sitio web en vez de las tareas comunes y repetitivas de cualquier
+sitio, como pueden ser, autenticación, permisos, sesiones, formularios,
+listados, etc.</p>
+<div class="section" id="para-qu-se-utiliza">
+<h2>¿Para qué se utiliza?</h2>
+<p>Django permite ser utilizarlo para el desarrollo de un blog, una encuesta, o
+hasta un <tt class="docutils literal"><span class="pre">sistema</span> <span class="pre">completo</span></tt> sin tener ningún tipo de inconveniente y
+facilitando mucho el trabajo. La abstracción que posse en cuanto a las tareas
+comunes permite un rápido diseño como así también su desarrollo.</p>
+</div>
+<div class="section" id="historia">
+<h2>Historia</h2>
+<p>Django nace por una necesidad. En el año 2003, programadores del diario
+<tt class="docutils literal"><span class="pre">Lawrence</span> <span class="pre">Journal-World</span></tt>, Adrian Holovaty y Simon Willison recibían por parte de
+los periodístas muchos pedidos de modificaciones del sitio con muy poco previo
+aviso pero sí con fechas límites.</p>
+<p>En el verano del 2005, luego de haber desarrollado el framework hasta que haga
+funcionar la mayoría de los sitios, el equipo, que ahora incluía a Jacob
+Kaplan-Moss decidió liberar este framework como software de código abierto. El
+nombre Django viene por el guitarrista de jazz Django Reinhardt.</p>
+</div>
+</div>
+<div class="section" id="patr-n-de-dise-o-mvc">
+<h1>Patrón de diseño MVC</h1>
+<p>Es un patrón de arquitectura de software que separa los datos de una
+aplicación, la interfaz de usuario, y la lógica de control en tres componentes
+distintos. El patrón MVC se ve frecuentemente en aplicaciones web, donde la
+vista es la página HTML y el código que provee de datos dinámicos a la página,
+el modelo es el Sistema de Gestión de Base de Datos y la Lógica de negocio y el
+controlador es el responsable de recibir los eventos de entrada desde la vista.</p>
+<blockquote>
+<a class="reference external" href="http://www.wikipedia.com.ar">Wikipedia</a></blockquote>
+<p>Aunque esta definición es bien clara, Django cambia un poco la sigla y utiliza
+MTV para describir su patrón de diseño, significando Models Templates Views. En
+dónde la anología sería Models-Models, Templates-Views y Views-Controler
+comparado con la anterior definición.</p>
+<div class="section" id="modelo-models-py">
+<h2>Modelo (models.py)</h2>
+<p>Este archivo contiene la descripción de las tablas para una aplicación,
+definidas como clases de Python. Usando estas clases de Python se pueden crear,
+buscar, actualizar y borrar entradas de la base de datos usando código Python
+en vez de sentencias SQL.</p>
+</div>
+<div class="section" id="vista-views-py">
+<h2>Vista (views.py)</h2>
+<p>En él se encuentra toda la lógica que se necesita para mostrar los resultados
+en la pantalla. Por ejemplo, procesar un ingreso de datos proveniente del
+usuario. A cada una de estas funciones se las llama <tt class="docutils literal"><span class="pre">vista</span></tt>.</p>
+</div>
+<div class="section" id="plantillas-index-html">
+<h2>Plantillas (index.html)</h2>
+<p>Las plantillas son simplemente código <tt class="docutils literal"><span class="pre">HTML</span></tt> el cual describe el aspecto que
+tendrá nuestra página al ser renderizada por el navegador. Además se puede
+escribir en el lenguaje de plantillas de Django para realizar algunas cosas
+especiales.</p>
+</div>
+</div>
+<div class="section" id="instalaci-n">
+<h1>Instalación</h1>
+<pre class="literal-block">
+[humitos]$ wget -c http://www.djangoproject.com/download/1.0/tarball/
+[humitos]$ tar xzvf Django-1.0.tar.gz
+......
+[humitos]$ cd Django-1.0
+[humitos]$ sudo python setup.py install
+</pre>
+<div class="section" id="prueba">
+<h2>Prueba</h2>
+<pre class="literal-block">
+[humitos]$ python
+Python 2.5.2 (r252:60911, Aug  6 2008, 09:17:29)
+[GCC 4.3.1] on linux2
+Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
+&gt;&gt;&gt; import django
+&gt;&gt;&gt; django.VERSION
+(1, 0, 'final')
+&gt;&gt;&gt;
+</pre>
+</div>
+</div>
+<div class="section" id="comenzar-un-proyecto">
+<h1>Comenzar un proyecto</h1>
+<pre class="literal-block">
+[humitos]$ django-admin.py startproject blog
+[humitos]$ ls blog/
+__init__.py  manage.py  settings.py  urls.py
+[humitos]$ python manage.py runserver
+</pre>
+<p>¡Ya está! Ahora si vamos a un navegador web y en la url ponemos
+<a class="reference external" href="http://localhost:8000">http://localhost:8000</a> veremos que Django nos muestra la página de bienvenida:
+<tt class="docutils literal"><span class="pre">It</span> <span class="pre">worked!</span></tt>.</p>
+<p>Anteriormente vimos que al ejecutar <tt class="docutils literal"><span class="pre">startproject</span></tt> Django nos crea cuatro
+archivos de Python:</p>
+<blockquote>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">___init___.py</span></tt>: es un archivo requerido por Python para indicarle que
+trate a este directorio como un paquete (conjunto de módulos).</li>
+<li><tt class="docutils literal"><span class="pre">manage.py</span></tt>: utilidad de línea de comandos para interactuar con el
+proyecto de Django creado anteriormente.</li>
+<li><tt class="docutils literal"><span class="pre">settings.py</span></tt>: archivo de configuraciones para el proyecto actual,
+entre ellas idioma, base de datos, etc.</li>
+<li><tt class="docutils literal"><span class="pre">urls.py</span></tt>: aquí se encuentran las declaraciones de las urls del sitio
+web que estamos desarrollando.</li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="mapear-url-s">
+<h1>Mapear URL's</h1>
+<p>Django concuerda cada url que se escribe en el navegador con una función vista,
+de tal manera que al acceder a un determinado lugar del sitio se llame a la
+función que nosotros indicamos. Esto se hace mediante expresiones regulares, en
+comparación con otros frameworks que es de acuerdo a la estructura de los
+directorios.</p>
+<div class="section" id="expresiones-regulares">
+<h2>Expresiones Regulares</h2>
+<p>Este mapeo del que hablamos se indica mediante expresiones regulares, lo que
+nos permite tener el control absoluto sobre las url y poder hacer fácilmente lo
+que queramos: restringir una url a que contenga cierta cantidad de números
+en un lugar predeterminado, por ejemplo.</p>
+<p>Django además nos permite utilizar grupos (nombrados o no) en las expresiones
+regulares, que luego serán pasados como argumento a nuestra función vista. Si
+utilizamos grupos nombrados, no importa el orden de los argumentos en la
+definición de la función, pero por el contario, el primer argumento será el
+primer grupo que aparezca en la expresión regular.</p>
+</div>
+<div class="section" id="funcion-para-la-url">
+<h2>Funcion para la url</h2>
+<p>La forma de indicarle a Django cual es la función vista que debe utilizar para
+cada una de las urls que queramos es pasarle una cadena de caracteres con la
+ruta para llegar a esta función (en sintaxis de Python) o bien pasarle
+diréctamente el objeto función que queremos. Cada una de estas vistas debe
+devolver un objeto HttpResponse.</p>
+</div>
+</div>
+<div class="section" id="crear-una-aplicaci-n">
+<h1>Crear una aplicación</h1>
+<div class="section" id="qu-es-una-aplicaci-n">
+<h2>¿Qué es una aplicación?</h2>
+<p>Una aplicación es un conjunto de archivos de código fuente de Python,
+incluyendo sus propios modelos y vista y que se encuentran agrupados en un
+mismo paquete. Por otro lado, un proyecto es un conjunto de aplicaciones, el
+cual establece las configuraciones globales para cada una de ellas, por ejemplo
+la conexión a la base de datos.</p>
+<p>Lo bueno de tener separadas las distintas aplicaciones, es que luego se pueden
+reutilizar sin modificar nada en el código ya que las cosas que están
+relacionadas con el proyecto no se encuentran dentro de estas. Django viene con
+una cantidad de aplicaciones listas para usar, entre ellas, el sistema de
+administración.</p>
+</div>
+<div class="section" id="ejemplo">
+<h2>Ejemplo</h2>
+<pre class="literal-block">
+[humitos]$ python manage.py startapp posts
+</pre>
+<p>Notar que utilizamos <tt class="docutils literal"><span class="pre">manage.py</span></tt> en vez de <tt class="docutils literal"><span class="pre">django-admin.py</span></tt>. Estos
+archivos tiene una funcionabilidad muy similar, pero utilizando el primero nos
+evitamos tener que indicarle la ruta del proyecto que queremos utilizar.</p>
+<p>Luego de ejecutar esta senticia se crea un directorio <tt class="docutils literal"><span class="pre">posts</span></tt> con tres
+archivos: <tt class="docutils literal"><span class="pre">__init__.py</span></tt>, <tt class="docutils literal"><span class="pre">models.py</span></tt> y <tt class="docutils literal"><span class="pre">views.py</span></tt>, que son los mismos que
+explicamos anteriormente pero para esta aplicación específica. Todos se
+encuentran vacíos y es dónde pondremos el código que corresponda en cada caso.</p>
+</div>
+</div>
+<div class="section" id="modelos">
+<h1>Modelos</h1>
+<p>Los modelos hacen referencia a todo lo que esté relacionado con la base de
+datos. En cada una de las aplicaciones definimos las clases (tablas en SQL)
+necesarias para que esta aplicación pueda funcionar correctamente.</p>
+<div class="section" id="configuraci-n-del-motor">
+<h2>Configuración del motor</h2>
+<p>Como la elección del motor de base de datos a utilizar es una configuración a
+nivel de proyecto, necesitamos indicar esto en el archivo <tt class="docutils literal"><span class="pre">settings.py</span></tt> que
+nos creó Django al momento de iniciar el proyecto.</p>
+<p>En este archivo se encuentra una sección con campos similares a estos:</p>
+<pre class="literal-block">
+DATABASE_ENGINE = ''
+DATABASE_NAME = ''
+DATABASE_USER = ''
+DATABASE_PASSWORD = ''
+DATABASE_HOST = ''
+DATABASE_PORT = ''
+</pre>
+<p>En donde se puede indicar el nombre del motor a utilizar, nombre de la base de
+datos, nombre del usuario, contraseña y demás. En caso de utilizar SQLite hay
+que indicar únicamente el campo <tt class="docutils literal"><span class="pre">DATABASE_NAME</span></tt> con un path al archivo en el
+disco. Para empezar y también para proyectos chicos es recomendable utilizar
+este motor, ya que es sencillo de configurar y no requiere módulos extras.</p>
+</div>
+<div class="section" id="definici-n-de-modelos">
+<h2>Definición de modelos</h2>
+<p>Para crear un modelo debemos editar el archivo <tt class="docutils literal"><span class="pre">models.py</span></tt> de la aplicación
+que necesite de estos. En principio vamos a crear la tabla <tt class="docutils literal"><span class="pre">post</span></tt> definiendo
+una clase en el archivo de esta aplicación:</p>
+<pre class="literal-block">
+from django.db import models
+
+class Post(models.Model):
+    titulo = models.CharField(max_length=50)
+    contenido = models.TextField()
+    etiquetas = models.ManyToManyField(Etiqueta)
+</pre>
+<p>Definimos una clase <tt class="docutils literal"><span class="pre">Post</span></tt> que contendrá un <em>título</em> y será un string de
+longitud máxima igual a 50, un campo <em>contenido</em> que será un string largo al
+cual luego el administrador lo representará como un <tt class="docutils literal"><span class="pre">&lt;textarea&gt;</span></tt> (entrada
+multilínea) en el que se guardará el contenido mismo del post y <em>etiquetas</em>
+que establece una relación muchos a muchos con <tt class="docutils literal"><span class="pre">Etiqueta</span></tt>.</p>
+<p>Ahora definamos los modelos <tt class="docutils literal"><span class="pre">Etiqueta</span></tt> y <tt class="docutils literal"><span class="pre">Comentario</span></tt>:</p>
+<pre class="literal-block">
+class Etiqueta(models.Model):
+    nombre = models.CharField(max_length=25)
+
+class Comentario(models.Model):
+    autor = models.CharField(max_length=25)
+    contenido = models.TextField()
+    post = models.ForeignKey(Post)
+</pre>
+<p>Una vez que tenemos esto creado en el modelo, lo que resta es instalar esta
+nueva aplicación en el proyecto y sincronizar la base de datos con el
+modelo. Para la instalación, editamos el archivo <tt class="docutils literal"><span class="pre">settings.py</span></tt> y agregamos
+nuetra aplicación a la variable <tt class="docutils literal"><span class="pre">INSTALLED_APPS</span></tt> que no es más que una tupla
+de strings:</p>
+<pre class="literal-block">
+INSTALLED_APPS = (
+'django.contrib.auth',
+'django.contrib.contenttypes',
+'django.contrib.sessions',
+'django.contrib.sites',
+'blog.posts',
+)
+</pre>
+<p>Lo que resta entonces es sincronizar la base de datos, para esto se debe
+ejecutar la siguiente sentencia de línea de comandos:</p>
+<pre class="literal-block">
+[humitos]$ python manage.py syncdb
+</pre>
+<p>En este momento nos pregunta si queremos crear una cuenta para el
+administrador, luego nos pedirá un email y su password. Una vez que este
+comando finalice tendremos creadas nuestras tablas.</p>
+</div>
+<div class="section" id="id1">
+<h2>Prueba</h2>
+<pre class="literal-block">
+[humitos]$ python manage.py shell
+Python 2.5.2 (r252:60911, Aug  6 2008, 09:17:29)
+[GCC 4.3.1] on linux2
+Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
+&gt;&gt;&gt; from posts.models import Post
+&gt;&gt;&gt; Post.objects.all()
+[]
+&gt;&gt;&gt; p = Post(titulo='Hola Mundo!', contenido='Hola a todos, este es mi primer post')
+&gt;&gt;&gt; p.save()
+&gt;&gt;&gt; Post.objects.all()
+[&lt;Post: Post object&gt;]
+&gt;&gt;&gt;
+</pre>
+<p>Lo que acabamos de hacer es insertar en el modelo un nuevo objeto post, con
+título <em>Hola Mundo!</em> y un contenido. Además no se encuentra relacionado con
+ninguna etiqueta. Una vez guardado el objeto, consultamos nuevamente la base de
+datos y nos dice que se encuetra un Post como resultado.</p>
+</div>
+<div class="section" id="sistema-de-administraci-n">
+<h2>Sistema de Administración</h2>
+<p>Django trae consigo una aplicación muy interesante: el sistema de
+administración. Éste nos permite agregar, quitar y modificar usuarios con un
+enterno web muy agradable y sencillo. Por ejemplo podemos probar lo que hicimos
+en la sección anterior únicamente haciendo clicks.</p>
+<p>Primero se debe <tt class="docutils literal"><span class="pre">instalar</span></tt> la aplicación en Django por lo que las
+aplicaciones instaladas quedarían así:</p>
+<pre class="literal-block">
+INSTALLED_APPS = (
+'django.contrib.auth',
+'django.contrib.contenttypes',
+'django.contrib.sessions',
+'django.contrib.sites',
+'django.contrib.admin',
+'blog.posts',
+)
+</pre>
+<p>Luego hay que sincronizar nuevamente la base de datos, ya que el sistema de
+administración tiene sus propias tablas. Si no estamos seguros qué va a suceder
+antes de ejecutar <tt class="docutils literal"><span class="pre">syncdb</span></tt> lo podemos comprobar utilizando este comando:</p>
+<pre class="literal-block">
+[humitos]$ python manage.py sql admin
+BEGIN;
+CREATE TABLE &quot;django_admin_log&quot; (
+    &quot;id&quot; integer NOT NULL PRIMARY KEY,
+    &quot;action_time&quot; datetime NOT NULL,
+    &quot;user_id&quot; integer NOT NULL REFERENCES &quot;auth_user&quot; (&quot;id&quot;),
+    &quot;content_type_id&quot; integer NULL REFERENCES &quot;django_content_type&quot; (&quot;id&quot;),
+    &quot;object_id&quot; text NULL,
+    &quot;object_repr&quot; varchar(200) NOT NULL,
+    &quot;action_flag&quot; smallint unsigned NOT NULL,
+    &quot;change_message&quot; text NOT NULL
+)
+;
+COMMIT;
+</pre>
+<p>Una vez que estamos seguro que es esto lo que queremos hacer, ejecutamos estas
+sentencias con el comando <tt class="docutils literal"><span class="pre">syncdb</span></tt>:</p>
+<pre class="literal-block">
+[humitos]$ python manage.py syncdb
+Creating table django_admin_log
+Installing index for admin.LogEntry model
+</pre>
+<p>Descomentamos las líneas del archivo <tt class="docutils literal"><span class="pre">urls.py</span></tt>:</p>
+<pre class="literal-block">
+from django.contrib import admin
+admin.autodiscover()
+...
+(r'^admin/(.*)', admin.site.root),
+</pre>
+<p>Ahora accediendo a la dirección <a class="reference external" href="http://localhost:8000/admin">http://localhost:8000/admin</a> nos debe mostrar
+una pantalla de login. Si indicamos el nombre de usuario y la contraseña que
+pusimos al crear el proyecto deberíamos poder ingresar al sitio de
+administración.</p>
+<p>En este momento aún no aparecen nuestra aplicaciones que hemos creados, le
+tenemos que indicar a Django que deseamos que las muestre. Para esto basta con
+crear un archivo <tt class="docutils literal"><span class="pre">admin.py</span></tt> dentro de la aplicación que queremos mostrar, en
+este caso <tt class="docutils literal"><span class="pre">posts</span></tt>:</p>
+<pre class="literal-block">
+from blog.posts.models import Post
+from django.contrib import admin
+
+admin.site.register(Post)
+</pre>
+</div>
+</div>
+<div class="section" id="vistas">
+<h1>Vistas</h1>
+<p>Una función de vista no es más que una función de Python que recibe como
+argumento una petición web y retorna una respuesta web. Esta respuesta puede
+ser código HTML, una imágen, un archivo de texto, o cualquier otra cosa.</p>
+<p>Al estar separadas las aplicaciones cada una de estas pueden tener lsa vistas
+que necesite, al igual que ocurría con los modelos. En este caso vamos a hacer
+la vista para agregar un nuevo post al blog:</p>
+<pre class="literal-block">
+from django.shortcuts import render_to_response
+from django.http import HttpResponseRedirect
+from django.forms import ModelForm
+from blog.posts.models import PostForm, Post
+
+def agregar_post(request):
+    if request.method == 'GET':
+        formulario = PostForm()
+        return render_to_response('agregar_post.html', {'formulario': formulario})
+    else:
+        formulario = PostForm(request.POST)
+        if formulario.is_valid():
+            formulario.save()
+        return HttpResponseRedirect('/')
+</pre>
+<p>Quedaría modificar el archivo <tt class="docutils literal"><span class="pre">urls.py</span></tt> para que cuando se ingrese a
+<a class="reference external" href="http://localhost:8000/posts/agregar">http://localhost:8000/posts/agregar</a> se ejecute la vista que acabamos de
+definir. Una vez hecho esto al ingresar a esta dirección se presenta un
+formulario para completar con los campos del modelo Post. Al presionar el
+botón se guarda este formulario en el modelo y se redirecciona a la página
+principal del blog.</p>
+</div>
+<div class="section" id="sistema-de-plantillas">
+<h1>Sistema de plantillas</h1>
+</div>
+</div>
+</body>
+</html>

django/contenido.rst

+==========================================
+Introducción a Django_
+==========================================
+
+:Author: Manuel Kaufmann
+:Contact: humitos@gmail.com
+:Revision: 29
+:Date: jue sep 11 22:17:12 ART 2008
+:Copyright: GNU Free Document License
+
+
+¿Qué es Django?
+---------------
+
+Django es un ``framework`` de alto nivel hecho en Python_ para el desarrollo de
+páginas web y a su vez fomenta el desarrollo de aplicaciones rápidas y limpias.
+Este framework nos permite preocuparnos únicamente por las partes específicas
+de nuestro sitio web en vez de las tareas comunes y repetitivas de cualquier
+sitio, como pueden ser, autenticación, permisos, sesiones, formularios,
+listados, etc.
+
+¿Para qué se utiliza?
+~~~~~~~~~~~~~~~~~~~~~
+
+Django permite ser utilizarlo para el desarrollo de un blog, una encuesta, o
+hasta un ``sistema completo`` sin tener ningún tipo de inconveniente y
+facilitando mucho el trabajo. La abstracción que posse en cuanto a las tareas
+comunes permite un rápido diseño como así también su desarrollo.
+
+Historia
+~~~~~~~~
+
+Django nace por una necesidad. En el año 2003, programadores del diario
+``Lawrence Journal-World``, Adrian Holovaty y Simon Willison recibían por parte de
+los periodístas muchos pedidos de modificaciones del sitio con muy poco previo
+aviso pero sí con fechas límites.
+
+En el verano del 2005, luego de haber desarrollado el framework hasta que haga
+funcionar la mayoría de los sitios, el equipo, que ahora incluía a Jacob
+Kaplan-Moss decidió liberar este framework como software de código abierto. El
+nombre Django viene por el guitarrista de jazz Django Reinhardt.
+
+Patrón de diseño MVC
+--------------------
+
+Es un patrón de arquitectura de software que separa los datos de una
+aplicación, la interfaz de usuario, y la lógica de control en tres componentes
+distintos. El patrón MVC se ve frecuentemente en aplicaciones web, donde la
+vista es la página HTML y el código que provee de datos dinámicos a la página,
+el modelo es el Sistema de Gestión de Base de Datos y la Lógica de negocio y el
+controlador es el responsable de recibir los eventos de entrada desde la vista.
+
+    Wikipedia_
+
+Aunque esta definición es bien clara, Django cambia un poco la sigla y utiliza
+MTV para describir su patrón de diseño, significando Models Templates Views. En
+dónde la anología sería Models-Models, Templates-Views y Views-Controler
+comparado con la anterior definición.
+
+Modelo (models.py)
+~~~~~~~~~~~~~~~~~~
+
+Este archivo contiene la descripción de las tablas para una aplicación,
+definidas como clases de Python. Usando estas clases de Python se pueden crear,
+buscar, actualizar y borrar entradas de la base de datos usando código Python
+en vez de sentencias SQL.
+
+Vista (views.py)
+~~~~~~~~~~~~~~~~
+
+En él se encuentra toda la lógica que se necesita para mostrar los resultados
+en la pantalla. Por ejemplo, procesar un ingreso de datos proveniente del
+usuario. A cada una de estas funciones se las llama ``vista``.
+
+Plantillas (index.html)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Las plantillas son simplemente código ``HTML`` el cual describe el aspecto que
+tendrá nuestra página al ser renderizada por el navegador. Además se puede
+escribir en el lenguaje de plantillas de Django para realizar algunas cosas
+especiales.
+
+Instalación
+-----------
+
+::
+
+    [humitos]$ wget -c http://www.djangoproject.com/download/1.0/tarball/
+    [humitos]$ tar xzvf Django-1.0.tar.gz
+    ......
+    [humitos]$ cd Django-1.0
+    [humitos]$ sudo python setup.py install
+
+Prueba
+~~~~~~
+
+::
+
+    [humitos]$ python
+    Python 2.5.2 (r252:60911, Aug  6 2008, 09:17:29)
+    [GCC 4.3.1] on linux2
+    Type "help", "copyright", "credits" or "license" for more information.
+    >>> import django
+    >>> django.VERSION
+    (1, 0, 'final')
+    >>>
+
+Comenzar un proyecto
+--------------------
+
+::
+
+    [humitos]$ django-admin.py startproject blog
+    [humitos]$ ls blog/
+    __init__.py  manage.py  settings.py  urls.py
+    [humitos]$ python manage.py runserver
+
+¡Ya está! Ahora si vamos a un navegador web y en la url ponemos
+http://localhost:8000 veremos que Django nos muestra la página de bienvenida:
+``It worked!``.
+
+Anteriormente vimos que al ejecutar ``startproject`` Django nos crea cuatro
+archivos de Python:
+
+    * ``___init___.py``: es un archivo requerido por Python para indicarle que
+      trate a este directorio como un paquete (conjunto de módulos).
+
+    * ``manage.py``: utilidad de línea de comandos para interactuar con el
+      proyecto de Django creado anteriormente.
+
+    * ``settings.py``: archivo de configuraciones para el proyecto actual,
+      entre ellas idioma, base de datos, etc.
+
+    * ``urls.py``: aquí se encuentran las declaraciones de las urls del sitio
+      web que estamos desarrollando.
+
+Mapear URL's
+------------
+
+Django concuerda cada url que se escribe en el navegador con una función vista,
+de tal manera que al acceder a un determinado lugar del sitio se llame a la
+función que nosotros indicamos. Esto se hace mediante expresiones regulares, en
+comparación con otros frameworks que es de acuerdo a la estructura de los
+directorios.
+
+Expresiones Regulares
+~~~~~~~~~~~~~~~~~~~~~
+
+Este mapeo del que hablamos se indica mediante expresiones regulares, lo que
+nos permite tener el control absoluto sobre las url y poder hacer fácilmente lo
+que queramos: restringir una url a que contenga cierta cantidad de números
+en un lugar predeterminado, por ejemplo.
+
+Django además nos permite utilizar grupos (nombrados o no) en las expresiones
+regulares, que luego serán pasados como argumento a nuestra función vista. Si
+utilizamos grupos nombrados, no importa el orden de los argumentos en la
+definición de la función, pero por el contario, el primer argumento será el
+primer grupo que aparezca en la expresión regular.
+
+Funcion para la url
+~~~~~~~~~~~~~~~~~~~
+
+La forma de indicarle a Django cual es la función vista que debe utilizar para
+cada una de las urls que queramos es pasarle una cadena de caracteres con la
+ruta para llegar a esta función (en sintaxis de Python) o bien pasarle
+diréctamente el objeto función que queremos. Cada una de estas vistas debe
+devolver un objeto HttpResponse.
+
+Crear una aplicación
+--------------------
+
+¿Qué es una aplicación?
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Una aplicación es un conjunto de archivos de código fuente de Python,
+incluyendo sus propios modelos y vista y que se encuentran agrupados en un
+mismo paquete. Por otro lado, un proyecto es un conjunto de aplicaciones, el
+cual establece las configuraciones globales para cada una de ellas, por ejemplo
+la conexión a la base de datos.
+
+Lo bueno de tener separadas las distintas aplicaciones, es que luego se pueden
+reutilizar sin modificar nada en el código ya que las cosas que están
+relacionadas con el proyecto no se encuentran dentro de estas. Django viene con
+una cantidad de aplicaciones listas para usar, entre ellas, el sistema de
+administración.
+
+Ejemplo
+~~~~~~~
+
+::
+
+    [humitos]$ python manage.py startapp posts
+
+Notar que utilizamos ``manage.py`` en vez de ``django-admin.py``. Estos
+archivos tiene una funcionabilidad muy similar, pero utilizando el primero nos
+evitamos tener que indicarle la ruta del proyecto que queremos utilizar.
+
+Luego de ejecutar esta senticia se crea un directorio ``posts`` con tres
+archivos: ``__init__.py``, ``models.py`` y ``views.py``, que son los mismos que
+explicamos anteriormente pero para esta aplicación específica. Todos se
+encuentran vacíos y es dónde pondremos el código que corresponda en cada caso.
+
+Modelos
+-------
+
+Los modelos hacen referencia a todo lo que esté relacionado con la base de
+datos. En cada una de las aplicaciones definimos las clases (tablas en SQL)
+necesarias para que esta aplicación pueda funcionar correctamente.
+
+Configuración del motor
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Como la elección del motor de base de datos a utilizar es una configuración a
+nivel de proyecto, necesitamos indicar esto en el archivo ``settings.py`` que
+nos creó Django al momento de iniciar el proyecto.
+
+En este archivo se encuentra una sección con campos similares a estos::
+
+    DATABASE_ENGINE = ''
+    DATABASE_NAME = ''
+    DATABASE_USER = ''
+    DATABASE_PASSWORD = ''
+    DATABASE_HOST = ''
+    DATABASE_PORT = ''
+
+En donde se puede indicar el nombre del motor a utilizar, nombre de la base de
+datos, nombre del usuario, contraseña y demás. En caso de utilizar SQLite hay
+que indicar únicamente el campo ``DATABASE_NAME`` con un path al archivo en el
+disco. Para empezar y también para proyectos chicos es recomendable utilizar
+este motor, ya que es sencillo de configurar y no requiere módulos extras.
+
+Definición de modelos
+~~~~~~~~~~~~~~~~~~~~~
+
+Para crear un modelo debemos editar el archivo ``models.py`` de la aplicación
+que necesite de estos. En principio vamos a crear la tabla ``post`` definiendo
+una clase en el archivo de esta aplicación::
+
+    from django.db import models
+
+    class Post(models.Model):
+        titulo = models.CharField(max_length=50)
+        contenido = models.TextField()
+        etiquetas = models.ManyToManyField(Etiqueta)
+
+Definimos una clase ``Post`` que contendrá un *título* y será un string de
+longitud máxima igual a 50, un campo *contenido* que será un string largo al
+cual luego el administrador lo representará como un ``<textarea>`` (entrada
+multilínea) en el que se guardará el contenido mismo del post y *etiquetas*
+que establece una relación muchos a muchos con ``Etiqueta``.
+
+Ahora definamos los modelos ``Etiqueta`` y ``Comentario``::
+
+    class Etiqueta(models.Model):
+        nombre = models.CharField(max_length=25)
+
+    class Comentario(models.Model):
+        autor = models.CharField(max_length=25)
+        contenido = models.TextField()
+        post = models.ForeignKey(Post)
+
+Una vez que tenemos esto creado en el modelo, lo que resta es instalar esta
+nueva aplicación en el proyecto y sincronizar la base de datos con el
+modelo. Para la instalación, editamos el archivo ``settings.py`` y agregamos
+nuetra aplicación a la variable ``INSTALLED_APPS`` que no es más que una tupla
+de strings::
+
+    INSTALLED_APPS = (
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.sites',
+    'blog.posts',
+    )
+
+Lo que resta entonces es sincronizar la base de datos, para esto se debe
+ejecutar la siguiente sentencia de línea de comandos::
+
+    [humitos]$ python manage.py syncdb
+
+En este momento nos pregunta si queremos crear una cuenta para el
+administrador, luego nos pedirá un email y su password. Una vez que este
+comando finalice tendremos creadas nuestras tablas.
+
+Prueba
+~~~~~~
+
+::
+
+    [humitos]$ python manage.py shell
+    Python 2.5.2 (r252:60911, Aug  6 2008, 09:17:29)
+    [GCC 4.3.1] on linux2
+    Type "help", "copyright", "credits" or "license" for more information.
+    >>> from posts.models import Post
+    >>> Post.objects.all()
+    []
+    >>> p = Post(titulo='Hola Mundo!', contenido='Hola a todos, este es mi primer post')
+    >>> p.save()
+    >>> Post.objects.all()
+    [<Post: Post object>]
+    >>>
+
+Lo que acabamos de hacer es insertar en el modelo un nuevo objeto post, con
+título *Hola Mundo!* y un contenido. Además no se encuentra relacionado con
+ninguna etiqueta. Una vez guardado el objeto, consultamos nuevamente la base de
+datos y nos dice que se encuetra un Post como resultado.
+
+
+Sistema de Administración
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Django trae consigo una aplicación muy interesante: el sistema de
+administración. Éste nos permite agregar, quitar y modificar usuarios con un
+enterno web muy agradable y sencillo. Por ejemplo podemos probar lo que hicimos
+en la sección anterior únicamente haciendo clicks.
+
+Primero se debe ``instalar`` la aplicación en Django por lo que las
+aplicaciones instaladas quedarían así::
+
+    INSTALLED_APPS = (
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.sites',
+    'django.contrib.admin',
+    'blog.posts',
+    )
+
+Luego hay que sincronizar nuevamente la base de datos, ya que el sistema de
+administración tiene sus propias tablas. Si no estamos seguros qué va a suceder
+antes de ejecutar ``syncdb`` lo podemos comprobar utilizando este comando::
+
+    [humitos]$ python manage.py sql admin
+    BEGIN;
+    CREATE TABLE "django_admin_log" (
+        "id" integer NOT NULL PRIMARY KEY,
+        "action_time" datetime NOT NULL,
+        "user_id" integer NOT NULL REFERENCES "auth_user" ("id"),
+        "content_type_id" integer NULL REFERENCES "django_content_type" ("id"),
+        "object_id" text NULL,
+        "object_repr" varchar(200) NOT NULL,
+        "action_flag" smallint unsigned NOT NULL,
+        "change_message" text NOT NULL
+    )
+    ;
+    COMMIT;
+
+Una vez que estamos seguro que es esto lo que queremos hacer, ejecutamos estas
+sentencias con el comando ``syncdb``::
+
+    [humitos]$ python manage.py syncdb
+    Creating table django_admin_log
+    Installing index for admin.LogEntry model
+
+Descomentamos las líneas del archivo ``urls.py``::
+
+    from django.contrib import admin
+    admin.autodiscover()
+    ...
+    (r'^admin/(.*)', admin.site.root),
+
+Ahora accediendo a la dirección http://localhost:8000/admin nos debe mostrar
+una pantalla de login. Si indicamos el nombre de usuario y la contraseña que
+pusimos al crear el proyecto deberíamos poder ingresar al sitio de
+administración.
+
+En este momento aún no aparecen nuestra aplicaciones que hemos creados, le
+tenemos que indicar a Django que deseamos que las muestre. Para esto basta con
+crear un archivo ``admin.py`` dentro de la aplicación que queremos mostrar, en
+este caso ``posts``::
+
+    from blog.posts.models import Post
+    from django.contrib import admin
+
+    admin.site.register(Post)
+
+Vistas
+------
+
+Una función de vista no es más que una función de Python que recibe como
+argumento una petición web y retorna una respuesta web. Esta respuesta puede
+ser código HTML, una imágen, un archivo de texto, o cualquier otra cosa.
+
+Al estar separadas las aplicaciones cada una de estas pueden tener lsa vistas
+que necesite, al igual que ocurría con los modelos. En este caso vamos a hacer
+la vista para agregar un nuevo post al blog::
+
+    from django.shortcuts import render_to_response
+    from django.http import HttpResponseRedirect
+    from django.forms import ModelForm
+    from blog.posts.models import PostForm, Post
+
+    def agregar_post(request):
+        if request.method == 'GET':
+            formulario = PostForm()
+            return render_to_response('agregar_post.html', {'formulario': formulario})
+        else:
+            formulario = PostForm(request.POST)
+            if formulario.is_valid():
+                formulario.save()
+            return HttpResponseRedirect('/')
+
+Quedaría modificar el archivo ``urls.py`` para que cuando se ingrese a
+http://localhost:8000/posts/agregar se ejecute la vista que acabamos de
+definir. Una vez hecho esto al ingresar a esta dirección se presenta un
+formulario para completar con los campos del modelo Post. Al presionar el
+botón se guarda este formulario en el modelo y se redirecciona a la página
+principal del blog.
+
+Sistema de plantillas
+---------------------
+
+
+
+.. _Django: http://www.djangoproject.com
+.. _Python: http://www.python.org
+.. _Wikipedia: http://www.wikipedia.com.ar
Add a comment to this file

django/imagenes/django_admin.png

Added
New image
Add a comment to this file

django/imagenes/django_admin_app.png

Added
New image
Add a comment to this file

django/imagenes/it_worked.png

Added
New image

django/indice.rst

+---------------------
+Introducción a Django
+---------------------
+
+Resumen: ``En esta charla se verán los conceptos básicos de Django, desde
+         la instalación hasta la confección de un blog muy muy simple. Se
+         explicará el patrón MVC y como se utiliza este en Django, el
+         matcheo de urls, la definición de una vista y su interacción con
+         los templates``
+
+Nivel: ``Bajo-Medio``
+
+Conocimientos previos: ``Mínimos conocimientos en Python``
+
+Disertante: ``Manuel Kaufmann``
+
+Email: ``humitos@gmail.com``
+
+Teléfono: ``0343 - 154053434
+            0342 - 4598908``
+
+Localidad: ``Santa Fe - Capital``
+
+Organizaciones: ``Python Argentina``
+
+Blog: ``http://humitos.wordpress.com``
+
+Índice de contenidos
+====================
+
+ * Qué es Django?
+   * Para que se utiliza?
+   * Historia
+
+ * Patron de diseño MVC
+   * Modelo
+   * Vista
+   * Controlador
+
+   MTV -> Model Template Views
+
+ * Instalación
+   * Muy por arriba
+
+ * Comenzar un proyecto
+   * Ejemplo
+   * Mostrar que inicia algo
+   * Explicaciones de los archivos
+     * __init__.py
+     * settings.py
+     * urls.py
+
+ * Mapear URL's
+   * Expresiones regulares
+   * Argumentos en las URL's
+   * Funcion de Python o cadena de caracteres
+     * La funcion debe devolver un HttpResponse
+
+ * Crear una aplicacion
+   * ¿Qué es una aplicacion? Usos
+   * Ejemplo
+     * python manage.py startapp pools
+     * __init__.py
+     * models.py
+     * views.py
+
+ * Modelos
+   * Definición de los modelos.
+   * Campos y relaciones.
+   * ABM en el sistema de administración (admin.py).
+
+ * Vistas
+   * Definir una vista
+   * Escribir la url
+   * Pasar argumentos (FALTA)
+
+ * Sistema de plantillas
+   * Contexto (argumentos)
+   * Herencia (plantilla base) - extends/block/endblock
+   * render_to_response (shortcuts)
+   * Etiquetas (if, for, etc..) forloop, ifequal
+   * Filtros (lower, truncatewords, con argumentos)
+   * Extención... definir un filtro y una etiqueta
+     * Mencionarlo
+
+   * TEMPLATE_DIRS (en settings)
+
+ * Sistema de Administracion
+   * ABM autogenerado
+   * Modificaciones
+   * admin.py
+
+

manuscritos/sl-en-la-universidad.rst

+================================
+Software Libre en la Universidad
+================================
+
+
+Comienzos en el Software Libre
+------------------------------
+
+Desde el comienzo de mis estudios en la Universidad, cuando no conocía el
+Sofware Libre, he utilizado todo el software que me brindaban los profesores
+sin ningún tipo de objeción al respecto.
+
+A medida que el tiempo fue pasando, apareció GNU/Linux en mi vida y las cosas
+comenzaron a cambiar lentamente. Hace aproximadamente cuatro años mis amigos me
+mostraron que existía otro sistema llamado GNU/Linux y que era mejor que
+Windows. Yo estaba totalmente desconcertado y lo negaba totalmente.
+
+Me convencieron de instalar GNU/Linux en mi computadora como para que vaya
+migrando lentamente y dejando de lado el otro sistema. Admito que no fue una
+tarea fácil de llevar a cabo, ya que estaba muy acostumbrado a como se hacían
+las cosas en mi viejo sistema. Aunque el mayor provecho que le saqué a
+GNU/Linux fue cuando quité totalmente Windows de mi PC, buscando la
+forma de realizar todo lo que necesitaba en este y sorprendiéndome
+de que las cosas que eran tediosas en Windows en GNU/Linux las desarrollaba
+casi de manera trivial con un programa de linea de comandos.
+
+
+Acercamiento a la filosofía del proyecto
+----------------------------------------
+
+Aunque hace algunos años que conozco GNU/Linux nunca indagué en su filosofía,
+quizás por desconocer que había todo un mundo detrás de esto o debido a un
+desinterés personal quizás, no lo sé. Si bien me hacía preguntas como `¿Qué es
+el software libre?`, `¿Libre es gratis?`, `¿Qué beneficios tiene que la gente
+publique sus programas de esta forma?`, etc. Creo que son las preguntas que se
+hace cualquiera persona que conoce recientemente GNU/Linux y quizás muchas
+veces no pueden ser respondidas de forma adecuada, como fue mi caso.
+
+Varios años después de estar utilizando GNU/Linux y participando de diferentes
+jornadas de software libre en distintos puntos de mi país, generalmente
+asistiendo a charlas técnicas (lenguajes de programación, servidores web,
+control de versiones, etc) y esporadicamente a charlas sociales --recuerdo
+muy pocas. Hace algunos meses atrás asistí a una en particular llamada `Patentes de Software: tu código
+es mío` de Federico Heinz, que me hizo cambiar la forma de ver las cosas con
+respecto al software libre y entender porqué es bueno que se utilize. Además de
+investigar y leer mucho con resepcto a esta filosofía y consultar distintas
+opiniones a mis amigos.
+
+Luego de comprender en profundidad estos conceptos, escuchar ditintas opiniones
+y formar una personal sobre determinadas ideas, comencé a respetarlas
+firmemente en cuanto me fue posible. Muchas veces teniendo que limitarme a no utilizar
+distintos programas que son privativos o que tienen licencias con las que no
+estoy de acuerdo. Esto me ha traído algunos problemas de distintos grados en
+los cuales estoy trabajando para tratar de cambiar. Comenzando desde los archivos
+adjuntos en un mail con formato `rar`, lo cual muchas veces se soluciona
+pidiéndole a la persona que me reenvíe su mail en algún formato de compresión
+libre como por ejemplo `tar` hasta algún software privativo que no tiene
+equivalente.
+
+
+Obligado a utilizar software privativo
+--------------------------------------
+
+Desde que empecé a respetar mi conciencia en cuanto a la utilización de
+software libre, me he puesto a observar en mi círculo social cuanta gente
+utiliza software libre y porqué lo hacen. Si están de acuerdo con su filosofía
+o simplemente porque consideran que es un mejor sistema.
+
+Me puse a pensar que en la Universidad nunca había escuchado hablar de software
+libre por parte de los profesores, ni siquiera dando una alternativa libre a
+algún programa que utilizábamos para desarrollar alguna actividad. La mayoría
+corrían sobre Windows y eran privativos. Asique me propuse intentar cambiar en
+algún punto esto cuando se me presente la oportunidad de hacerlo.
+
+Un tiempo después me encuentro cursando la materia `Gestión de datos` en la que
+se da ANSI SQL y los profesores de la cátedra lo explican sobre *Oracle*. Pasa
+un tiempo del cursado y nos informan que había que desarrollar una base de
+datos como trabajo práctico y su implementación debía ser en *Microsoft Access*, lo
+cual me sorprendió ya que cualquier base de datos soporta el estándar ANSI SQL.
+En esa primera instancia y frente a toda la clase pregunté si había alguna
+posibilidad de realizar el trabajo sobre una base de datos que fuese libre
+
+
+
Add a comment to this file

python/como-colaborar-con-python.odp

Binary file added.

python/como-colaborar-con-python/Makefile

+# Makefile
+# genera la version Adobe PDF
+
+.PHONY: all tex pdf clean veryclean
+.SUFFIXES: .rst
+
+tex :
+	rst2latex										\
+		--time										\
+		--generator									\
+		--halt=none									\
+		--font-encoding=T1							\
+		--output-encoding=utf-8						\
+		--language=es								\
+		--documentclass=article						\
+		--stylesheet-path=./latex2e.sty				\
+		--footnote-references=brackets				\
+		--graphicx-option=pdftex					\
+		--use-latex-toc								\
+		--verbose									\
+		como-colaborar-con-python.rst > como-colaborar-con-python.tex
+
+pdf : tex
+	pdflatex como-colaborar-con-python.tex
+
+clean:
+	rm -f como-colaborar-con-python.tex
+	rm -f como-colaborar-con-python.aux 
+	rm -f como-colaborar-con-python.log
+	rm -f como-colaborar-con-python.out
+
+veryclean : clean
+	rm -f como-colaborar-con-python.pdf	
+
Add a comment to this file

python/como-colaborar-con-python/bugfix-images/bugfix1.jpeg

Added
New image
Add a comment to this file

python/como-colaborar-con-python/bugfix-images/bugfix2.jpeg

Added
New image
Add a comment to this file

python/como-colaborar-con-python/bugfix-images/bugfix3.jpeg

Added
New image
Add a comment to this file

python/como-colaborar-con-python/bugfix-images/bugfix4.jpeg

Added
New image
Add a comment to this file

python/como-colaborar-con-python/bugfix-images/bugfix5.jpeg

Added
New image
Add a comment to this file

python/como-colaborar-con-python/bugfix-images/bugfix6.jpeg

Added
New image
Add a comment to this file

python/como-colaborar-con-python/bugfix-images/bugfix7.jpeg

Added
New image
Add a comment to this file

python/como-colaborar-con-python/bugfix-images/bugfix8.jpeg

Added
New image
Add a comment to this file

python/como-colaborar-con-python/charla/0.1.odp

Binary file added.

Add a comment to this file

python/como-colaborar-con-python/charla/0.1.pdf

Binary file added.

Add a comment to this file

python/como-colaborar-con-python/charla/Cubes_1x.sti

Binary file added.

python/como-colaborar-con-python/charla/encuesta.txt

+ - ¿Quienes conocen Python?
+ - ¿Cuantos usan Python?
+ - ¿Cuantos han reportado un Bug?
+ - ¿Cuantos han corregido un Bug?
+ - ¿Quienes conocen subversion?
+
+
Add a comment to this file

python/como-colaborar-con-python/como-colaborar-con-python.pdf

Binary file added.

python/como-colaborar-con-python/como-colaborar-con-python.rst

+=====================================================
+¿Cómo colaborar con Python?
+=====================================================
+
+:Author: Manuel Kaufmann
+:Contact: humitos@gmail.com
+:Revision: 16
+:Date: Mon May 12 00:48:37 ART 2008
+:Copyright: GNU Free Document License
+
+
+Objetivos
+=========
+
+ * Reportar un bug: de código, documentación, etc.
+ * Corregir el bug. ¿Por qué no?
+ * Agregar funcionabilidad
+ * Aprender cómo está hecho Python.
+
+
+Tareas generales
+================
+
+ * Descargar el código fuente de Python.
+ * Compilar los fuentes.
+ * Probar que funcione.
+ * Buscar y corregir el error.
+ * Escribir el test correspondiente.
+ * Ejecutar los test de prueba.
+ * Recompilar el código nuevamente.
+ * Probar que funcione correctamente.
+ * Crear el parche.
+ * Reportar el bug incorporando el parche.
+ * ¡Listo!
+
+
+Procedimiento paso a paso
+=========================
+
+
+Descargar el código
+-------------------
+
+Python dispone de un repositorio ``svn`` en el cual está alojado su código
+fuente. Para descargar el código en su última versión se debe hacer un
+``checkout`` del mismo mediante este comando::
+
+    svn checkout http://svn.python.org/projects/python/trunk python-trunk
+
+Esto nos crea la carpeta *python-trunk* en dónde se encuentra todo lo que está
+en el respositorio de forma actualizada al día en que se hace en ``checkout``.
+
+Las carpetas se distribuyen a grandes rasgos de la siguiente manera:
+
+ * Demo: ejemplos de código de Python.
+ * Doc: documentación de los módulos y demás.
+ * Grammar: contiene un archivo que indica la gramática de Python.
+ * Include: archivos de cabeceras del código de C.
+ * Lib: módulos y paquetes de Python escritos en Python.
+ * Mac: fuentes para sistemas Os/X.
+ * Misc: ?
+ * Modules: módulos escritos en C.
+ * Objects: objetos de C.
+ * Parser: archivos en C del parser de Python.
+ * PC: fuentes para sistemas PC Compatible.
+ * PCbuild: ?
+ * Python: cabeceras y código en C del Core de Python.
+ * RISCOS: ?
+ * Tools: utilidades varias.
+
+Compilar las fuentes
+--------------------
+
+Para compilar el código de Python es necesario tener instalado en el sistema
+como mínimo estos programas :
+
+ * ``compilador de C`` (gcc)
+
+Opcionalmente se pueden instalar otras bibliotecas así el Python que compilemos nosotros
+soporte todo lo que viene con la biblioteca estándar de Python. Por ejemplo, si no instalamos
+la librería de ``sqlite 3`` no podremos hacer::
+
+  import sqlite3
+
+Por lo tanto no podremos solucionar bugs relacionados con este módulo. La bibliotecas
+opcionales a instalar son (lo que figura entre paréntesis es el correspondiente paquete
+en Debian):
+
+ * ``readline`` (libreadline5-dev)
+ * ``sqlite 3`` (libsqlite3-dev)
+ * ``ssl`` (libssl-dev)
+ * ``ncurses`` (libncurses5-dev)
+ * ``gzip`` (zlib1g-dev)
+ * ``tk`` (tk8.4-dev)
+ * ``berkeley`` (libdb-dev)
+ * ``bzip2`` (libbz2-dev)
+ * ``gnu dbm`` (libgdbm-dev)
+ * ``make`` (make)
+
+Luego de tener todo instalado se debe compilar el código fuente::
+
+    $ cd python-trunk
+    $ ./configure
+    $ make
+
+Si termina y no da ningún error, ya tenemos la versión de desarrollo lista para
+usar en nuestro sistema. Debe mostrar algo así si todo funciona correctamente::
+
+    $ ./python
+    Python 2.6a2+ (trunk:62702, May  4 2008, 10:52:17)
+    [GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
+    Type "help", "copyright", "credits" or "license" for more information.
+    >>>
+
+
+Buscar y corregir un error
+--------------------------
+
+Si nosotros mismos encontramos un error, ya sea en la documentación, en algún
+módulo de Python o en el core mismo, debemos reportarlo en el `Issue Tracker`_
+marcando de qué tipo es el error y explicando brevemente que está sucediendo.
+
+Si de lo contrario no hemos encontrado un error nosotros mismos, podemos
+visitar el `Issue Tracker`_ de Python, en donde están todos los bug reportados y
+buscar alguno que nos interese, o que estemos en condiciones de solucionarlo.
+
+También se pueden buscar en `Python Open Tickets`_, pudiendo filtrar por
+distintos campos, entre ellos: prioridad, versión, llave, etc.
+
+Una vez que sepamos que bug queremos solucionar, no basta más que
+editar el archivo que tiene el error, corregirlo y listo.
+
+
+Escribir el test correspondiente
+--------------------------------
+
+Si agregamos funcionabilidad a algún módulo ya existente, debemos buscar el
+test correspondiente a este módulo en el directorio ``Lib/test/`` y crear el
+test para esta nueva funcionabilidad.
+
+Sino, si corregimos algún error, debemos ejecutar los test nuevamente y
+comprobar que todo funcione::
+
+    $ ./python Lib/test/regrtest.py
+
+De esta forma se ejecutan todas las pruebas (demora mucho) sobre la versión que compilamos
+nosotros mismos. Si únicamente queremos probar el módulo que modificamos
+nosotros (módulo random, por ejemplo), podemos ejecutar::
+
+    $ ./python Lib/test/test_random.py
+
+Y comprobar que todo haya salido como lo esperábamos.
+
+
+Recompilar el código nuevamente
+-------------------------------
+
+Para esto, volvemos al paso de ``Compilar el código fuente`` y luego ejecutamos
+nuevamente los test para asegurarnos que todo funciona correctamente.
+
+
+Crear el parche
+---------------
+
+Una vez que estamos seguros que todo funciona como queremos, nos dirigimos a la
+página de `Issue Tracker`, reportamos el bug que encontramos informando que lo
+solucionamos. Además subimos el parche que se genera luego de ejecuar este
+comando::
+
+    $ svn diff > random.patch
+
+El archivo contendrá algo similar a esto::
+
+    Index: Lib/random.py
+    ===================================================================
+    --- Lib/random.py       (revisión: 62721)
+    +++ Lib/random.py       (copia de trabajo)
+    @@ -105,6 +105,7 @@
+             If a is not None or an int or long, hash(a) is used instead.
+             """
+
+    +        # agrego un comentario acá
+             if a is None:
+                 try:
+                     a = long(_hexlify(_urandom(16)), 16)
+
+El cual indica que se agregan las líneas que empiezan con **+** y se eliminan
+las que comienzan con **-**.
+
+¡Listo!
+-------
+
+Terminado de realizar todos estos pasos, falta esperar que algún usuario con
+permisos de escritura en el servidor ``svn`` aplique el parche que acabamos de
+hacer. Este procedimiento generalmente es bastante rápido. ¡El último que hice
+demoró 6 minutos!
+
+
+.. _Issue Tracker: http://bugs.python.org/
+.. _Python Open Tickets: http://www.taniquetil.com.ar/cgi-bin/pytickets.py

python/como-colaborar-con-python/como-colaborar-con-python.tex

+% generated by Docutils <http://docutils.sourceforge.net/>
+\documentclass[a4paper,spanish]{article}
+\usepackage{fixltx2e} % LaTeX patches, \textsubscript
+\usepackage{cmap} % fix search and cut-and-paste in PDF
+\usepackage{babel}
+\addto\shorthandsspanish{\spanishdeactivate{."~<>}}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{ifthen}
+\usepackage{tabularx}
+\newcommand{\DUfooter}{
+Generated on: 2010-03-07 19:03 UTC.
+Generated by \href{http://docutils.sourceforge.net/}{Docutils} from \href{http://docutils.sourceforge.net/rst.html}{reStructuredText} source.
+
+}
+
+%%% User specified packages and stylesheets
+\usepackage{latex2e}
+
+%%% Fallback definitions for Docutils-specific commands
+
+% providelength (provide a length variable and set default, if it is new)
+\providecommand*{\DUprovidelength}[2]{
+  \ifthenelse{\isundefined{#1}}{\newlength{#1}\setlength{#1}{#2}}{}
+}
+
+% docinfo (width of docinfo table)
+\DUprovidelength{\DUdocinfowidth}{0.9\textwidth}
+
+% titlereference role
+\providecommand*{\DUroletitlereference}[1]{\textsl{#1}}
+
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+  \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+}{}
+\hypersetup{
+  pdftitle={¿Cómo colaborar con Python?},
+}
+
+%%% Body
+\begin{document}
+
+% Document title
+\title{¿Cómo colaborar con Python?%
+  \phantomsection%
+  \label{como-colaborar-con-python}}
+\author{}
+\date{}
+\maketitle
+
+% Docinfo
+\begin{center}
+\begin{tabularx}{\DUdocinfowidth}{lX}
+\textbf{Author}: &
+Manuel Kaufmann
+\\
+\textbf{Contact}: &
+\href{mailto:humitos@gmail.com}{humitos@gmail.com}
+\\
+\textbf{Revision}: &
+16
+\\
+\textbf{Date}: &
+Mon May 12 00:48:37 ART 2008
+\\
+\textbf{Copyright}: &
+	GNU Free Document License \\
+\end{tabularx}
+\end{center}
+
+
+%___________________________________________________________________________
+
+\section*{Objetivos%
+  \phantomsection%
+  \addcontentsline{toc}{section}{Objetivos}%
+  \label{objetivos}%
+}
+%
+\begin{quote}
+%
+\begin{itemize}
+
+\item Reportar un bug: de código, documentación, etc.
+
+\item Corregir el bug. ¿Por qué no?
+
+\item Agregar funcionabilidad
+
+\item Aprender cómo está hecho Python.
+
+\end{itemize}
+
+\end{quote}
+
+
+%___________________________________________________________________________
+
+\section*{Tareas generales%
+  \phantomsection%
+  \addcontentsline{toc}{section}{Tareas generales}%
+  \label{tareas-generales}%
+}
+%
+\begin{quote}
+%
+\begin{itemize}
+
+\item Descargar el código fuente de Python.
+
+\item Compilar los fuentes.
+
+\item Probar que funcione.
+
+\item Buscar y corregir el error.
+
+\item Escribir el test correspondiente.
+
+\item Ejecutar los test de prueba.
+
+\item Recompilar el código nuevamente.
+
+\item Probar que funcione correctamente.
+
+\item Crear el parche.
+
+\item Reportar el bug incorporando el parche.
+
+\item ¡Listo!
+
+\end{itemize}
+
+\end{quote}
+
+
+%___________________________________________________________________________
+
+\section*{Procedimiento paso a paso%
+  \phantomsection%
+  \addcontentsline{toc}{section}{Procedimiento paso a paso}%
+  \label{procedimiento-paso-a-paso}%
+}
+
+
+%___________________________________________________________________________
+
+\subsection*{Descargar el código%
+  \phantomsection%
+  \addcontentsline{toc}{subsection}{Descargar el código}%
+  \label{descargar-el-codigo}%
+}
+
+Python dispone de un repositorio \texttt{svn} en el cual está alojado su código
+fuente. Para descargar el código en su última versión se debe hacer un
+\texttt{checkout} del mismo mediante este comando:
+%
+\begin{quote}{\ttfamily \raggedright \noindent
+svn~checkout~http://svn.python.org/projects/python/trunk~python-trunk
+}
+\end{quote}
+
+Esto nos crea la carpeta \emph{python-trunk} en dónde se encuentra todo lo que está
+en el respositorio de forma actualizada al día en que se hace en \texttt{checkout}.
+
+Las carpetas se distribuyen a grandes rasgos de la siguiente manera:
+%
+\begin{quote}
+%
+\begin{itemize}
+
+\item Demo: ejemplos de código de Python.
+
+\item Doc: documentación de los módulos y demás.
+
+\item Grammar: contiene un archivo que indica la gramática de Python.
+
+\item Include: archivos de cabeceras del código de C.
+
+\item Lib: módulos y paquetes de Python escritos en Python.
+
+\item Mac: fuentes para sistemas Os/X.
+
+\item Misc: ?
+
+\item Modules: módulos escritos en C.