El libro de Django 1.0

3.2. Mapeando URLs a Vistas

Repasemos, esta función de vista retorna un página HTML que contiene la fecha y hora actual. ¿Pero cómo le decimos a Django que utilice ese código?. Ahí es donde vienen las URLconfs.

Una URLconf es como una tabla de contenido para tu sitio web hecho con Django. Básicamente, es un mapeo entre los patrones URL y las funciones de vista que deben ser llamadas por esos patrones URL. Es como decirle a Django, "Para esta URL, llama a este código, y para esta URL, llama a este otro código". Recuerda que estas funciones de vista deben estar en tu Python path.

Cuando ejecutaste django-admin.py startproject en el capítulo anterior, el script creó automáticamente una URLconf por tí: el archivo urls.py. Editemos ese archivo. Por omisión, se verá como:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    # Example:
    # (r'^mysite/', include('mysite.apps.foo.urls.foo')),

    # Uncomment this for admin:
#     (r'^admin/', include('django.contrib.admin.urls')),
)

Repasemos el código anterior línea a línea:

  • La primera línea importa todos los objetos desde el módulo django.conf.urls.defaults, incluyendo una función llamada patterns.
  • La segunda línea llama a la función patterns() y guarda el resultado en una variable llamada urlpatterns. La función patterns() sólo recibe un argumento — la cadena de caracteres vacía. El resto de las líneas están comentadas. (La cadena de caracteres puede ser usada para proveer un prefijo común para las funciones de vista, pero dejemos este uso más avanzado para más adelante).

Lo principal que debemos notar aquí es la variable urlpatterns, la cual Django espera encontrar en tu módulo ROOT_URLCONF. Esta variable define el mapeo entre las URLs y el código que manejan esas URLs.

Por defecto, todo lo que está en URLconf está comentado — tu aplicación de Django es una pizarra blanca. (Como nota adicional, esta es la forma en la que Django sabía que debía mostrar la página "It worked!" en el capítulo anterior. Si la URLconf esta vacía, Django asume que acabas de crear el proyecto, por lo tanto, muestra ese mensaje).

Editemos este archivo para exponer nuestra vista current_datetime:

from django.conf.urls.defaults import *
from mysite.views import current_datetime

urlpatterns = patterns('',
    (r'^time/$', current_datetime),
)

Hicimos dos cambios aquí. Primero, importamos la vista current_datetime desde el módulo (mysite/views.py, que en la sintaxis de import de Python se traduce a mysite.views). Luego, agregamos la línea (r'^time/$', current_datetime),. Esta línea hace referencia a un URLpattern — es una tupla de Python en dónde el primer elemento es una expresión regular simple y el segundo elemento es la función de vista que usa para ese patrón.

En pocas palabras, le estamos diciendo a Django que cualquier petición a la URL /time será manejada por la función de vista current_datetime.

Algunas cosas que vale la pena resaltar:

  • Notemos que, en este ejemplo, pasamos la función de vista current_datetime como un objeto sin llamar a la función. Esto es una característica de Python (y otros lenguajes dinámicos): las funciones son objetos de primera clase, lo cual significa que puedes pasarlas como cualquier otra variable. ¡Qué bueno!, ¿no?
  • La r en r'^time/$' significa que '^time/$' es una cadena de caracteres en crudo de Python. Esto permite que las expresiones regulares sean escritas sin demasiadas sentencias de escape.
  • Puedes excluir la barra al comienzo de la expresión '^time/$' para que coincida con /time/. Django automáticamente agrega una barra antes de toda expresión. A primera vista esto parece raro, pero una URLconf puede ser incluida en otra URLconf, y el dejar la barra de lado simplifica mucho las cosas. Esto se retoma en el Capítulo 8.
  • El caracter acento circunflejo (^) y el carácter signo de dólar ($) son importantes. El acento circunflejo significa que "requiere que el patrón concuerde con el inicio de la cadena de caracteres", y el signo de dólar significa que "exige que el patrón concuerde con el fin de la cadena". Este concepto se explica mejor con un ejemplo. Si hubiéramos utilizado el patrón '^time/' (sin el signo de dólar al final), entonces cualquier URL que comience con time/ concordaría, así como /time/foo y /time/bar, no sólo /time/. Del mismo modo, si dejamos de lado el carácter acento circunflejo inicial ('time/$'), Django concordaría con cualquier URL que termine con time/, así como /foo/bar/time/. Por lo tanto, usamos tanto el acento circunflejo como el signo de dólar para asegurarnos que sólo la URL /time/ concuerde. Nada más y nada menos. Quizás te preguntes qué pasa si alguien intenta acceder a /time. Esto es manejado como esperarías (a través de un redireccionamiento) siempre y cuando APPEND_SLASH tenga asignado el valor True. (Veáse el Apéndice E para una buena lectura sobre este tema).

Para probar nuestro cambios en la URLconf, inicia el servidor de desarrollo de Django, como hiciste en el Capítulo 2, ejecutando el comando python manage.py runserver. (Si ya lo tenías corriendo, está bien también. El servidor de desarrollo automáticamente detecta los cambios en tu código de Python y recarga de ser necesario, así no tienes que reiniciar el servidor al hacer cambios). El servidor está corriendo en la dirección http://127.0.0.1:8000/, entonces abre tu navegador web y ve a http://127.0.0.1:8000/time/. Deberías ver la salida de tu vista de Django.

¡Enhorabuena! Has creado tu primera página Web hecha con Django.

3.2.1. Expresiones Regulares

Las Expresiones Regulares (o regexes) son la forma compacta de especificar patrones en un texto. Aunque las URLconfs de Django permiten el uso de regexes arbitrarias para tener un potente sistema de definición de URLs, probablemente en la práctica no utilices más que un par de patrones regex. Esta es una pequeña selección de patrones comunes:

Símbolo Coincide con
. Cualquier carácter
\d Cualquier dígito
[A-Z] Cualquier carácter, A-Z (mayúsculas)
[a-z] Cualquier carácter, a-z (minúsculas)
[A-Za-z] Cualquier carácter, a-z (no distingue entre mayúscula y minúscula)
+ Una o más ocurrencias de la expresión anterior (ejemplo, \d+coincidirá con uno o más dígitos)
[^/]+ Todos los caracteres excepto la barra
* Cero o más ocurrencias de la expresión anterior (ejemplo, \d*coincidirá con cero o más dígitos)
{1,3} Entre una y tres (inclusive) ocurrencias de la expresión anterior

Para más información acerca de las expresiones regulares, mira el módulo re-module.