Capítulo 6: El sitio de administración de Django

Hay un aspecto del desarrollo Web que siempre hemos odiado: escribir interfaces de administración. Desarrollar las partes del sitio que ve el público general es siempre diferente e interesante, pero lo que usan los adminitradores para modificar el sitio es siempre lo mismo. Hay que tratar con autentificación de usuarios, mostrar y gestionar formularios, lidiar con problemas de validación poco evidentes... Es aburrido y repetitivo.

¿La solución de Django para esta tarea aburrida y repetitiva? Hacerlo por usted (en sólo un par de líneas de código, ni más ni menos).

Una de las partes más antiguas y potentes de Django es la interfaz automática de administración. Se nutre de los metadatos de su modelo para proporcionar una interfaz potente y lista para producción que los productores de contenido puede usar de inmediato para empezar a añadir contenido al sitio.

Activación de la interfaz de administración

Pensamos que la interfaz de administración es lo característica más atractiva de Django (y la mayoría de Djangonautas están de acuerdo), pero como no todo el mundo lo necesita, es una pieza opcional. Esto significa que hay que dar tres pasos para activar la interfaz de administración:

  1. Añada metadatos de administración a sus modelos.

    No todos los modelos pueden (o deben) ser editables por los usuarios administradores, así que necesitamos "marcar" los modelos deberían tener interfaz de administración. Esto lo hacemos añadiendo al modelo una clase interna Admin (junto con la clase Meta, si hay una). Así que para añadir una interfaz de administración a nuestro modelo Libro del capítulo anterior:

    class Libro(models.Model):
        titulo = models.CharField(maxlength=100)
        autores = models.ManyToManyField(Autor)
        editorial = models.ForeignKey(Editorial)
        fecha_publicacion = models.DateField()
    
        class Admin:
            pass
    

    La declaración de Admin marca la clase como poseedora de una interfaz de administración. Hay una serie de opciones que podemos bajo Admin, pero por ahora vamos a limitarnos al comportamiento por omisión, así que escribimos pass para decirle a Python que la clase Admin está vacía.

    Si está siguiendo este ejemplo escribiendo su propio código, probablemente sea buena idea añadir ahora declaraciones Admin a las clases Editorial y Autor.

  2. Instale los modelos de administración. Basta con añadir "django.contrib.admin" a la opción INSTALLED_APPS y ejecute python manage.py syncdb para instalar las tablas extra que usa la aplicación de administración.

    Nota

    Es probable que la primera vez que ejecutó syncdb, le preguntase algo al respecto de crear un superusuario. Si no lo hizo en ese momento, tendrá que ejecutar django/contrib/auth/bin/create_superuser.py para crear un usuario administrador. En caso contrario no será capaz de identificarse para entrar a la interfaz de administración.

  3. Añada el patrón de URL en su urls.py. Si aún está usando el creado po startproject, el patrón de la URL de administración debería estar ya ahí, pero comentado. De cualquier forma, los patrones de URL deberían acabar siendo algo así:

    from django.conf.urls.defaults import *
    
    urlpatterns = patterns('',
        (r'^admin/', include('django.contrib.admin.urls')),
    )
    

Eso es todo. Ahora ejecute python manage.py runserver para arrancar el servidor de desarrollo y verá algo como esto:

Validating models...
0 errors found.

Django version 0.96-pre, using settings 'ch6.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Ahora podemos visitar la URL que Django nos ha indicado (http://127.0.0.1:8000/admin/ en el ejemplo anterior), identifíquese y juegue un poco.

Uso de la interfaz de administración

La interfaz de administración está diseñada para que la utilicen usuarios no técnicos, y por tanto debería ser bastante autoexplicativa. Aún así, se imponen unas pocas notas sobre las características de la interfaz de administración.

Lo primero que verá es una página de identificación:

http://media.djangobook.com/content/chapter06/login.png

Usaremos el nombre de usuario y la clave que configuramos al ejecutar syncdb por primera vez. Una vez identificados, veremos que podemos gestionar usuarios, grupos y permisos; lo verá más adelante.

Cada objeto al que se le ha dado una declaración Admin aparece en la página principal de la interfaz de administración. Los enlaces para añadir y modificar objetos llevan a dos páginas a las que nos referiremos como "listas de cambio" y "formularios de edición" de objetos:

http://media.djangobook.com/content/chapter06/admin_index.png

Las listas de cambio son en esencia páginas de índice de objetos del sistema:

http://media.djangobook.com/content/chapter06/changelist.png

Hay varias opciones que pueden controlar los campos que aparecen en esas listas y la aparición de características extra como campos de búsqueda e interfaces de filtro. Más adelante hablaremos sobre esto.

Los formularios de edición se usan para modificar objetos existentes y crear otros nuevos. Aquí aparece cada campo definido en el modelo, y notará que los campos de tipos diferentes se muestran usando controles distintos (o sea, los campos de fecha/hora tienen controles de calendario, las claves foráneas tienen una caja de selección, etc.):

http://media.djangobook.com/content/chapter06/editform.png

Observará que la interfaz también valida la entrada por usted; intente dejar en blanco un campo obligatorio, o poner una hora inexistente en un campo de hora y verá estos errores cuando intente guardar:

http://media.djangobook.com/content/chapter06/editform_errors.png

Esta validación la realiza realmente un potente framework de validación que comentaremos en el Capítulo 7.

Al editar un objeto que ya existe verá un enlace "history" (histórico) en la esquina superior derecha. Cada cambio que se realiza usando la interfaz de administración queda registrado, y puede examinar el registro pulsando en el botón de histórico:

http://media.djangobook.com/content/chapter06/history.png

Los borrados en la interfaz de administración son en cascada. Es decir, al borrar un objeto existente la interfaz le pedirá que confirme dicha acción para evitar errores costosos. Lo que podría no ser inmediatamente obvio es que esta página le mostrará también el resto de objetos relacionados que van a ser borrados simultáneamente:

Deletions in the admin cascade. That is, when deleting an existing object, you’ll see that the admin asks you to confirm the delete action to avoid costly mistakes. What might not be instantly obvious is that this page will show you all the related objects that will be deleted as well:

http://media.djangobook.com/content/chapter06/delete_confirm.png

Usuarios, grupos y permisos

Dado que hemos ingresado en el sistema como superusuarios, tenemos derecho a crear, editar y borrar cualquier objeto. Sin embargo, la interfaz dispone de un sistema de permisos que podemos usar para dar acceso a otros usuarios sólo a las partes que necesitan.

Editamos estos usuarios y permisos mediante la interfaz de la misma manera que con cualquier otro objeto; el enlace a los modelos User y Group se encuentra en el índice junto con el resto de objetos que hemos definido nosotros mismos.

Los objetos User tienen los campos que podrían esperarse como nombre de usuario, clave, email y nombre real, junto con varios campos que definen lo que está autorizado a hacer el usuario en la interfaz de administración. Antes de nada, hay tres señalizadores:

  • "is active" controla si el usuario está activo. Si no está marcado, el usuario no tendrá acceso a ninguna URL que precise identificación.
  • "is staff" controla si el usuario tiene permiso para ingresar en la interfaz de administración (es decir, se considera "personal" -staff- de la organización). Dado que se puede usar este mismo sistema de usuarios para controlar el acceso a sitios abiertos al público (es decir, fuera de la administración - véase el Capítulo 12), este señalizador diferencia a los usuarios entre público y administradores.
  • "is superuser" le da al usuario acceso ilimitado y completo a todos los elementos de la interfaz, ignorando los permisos normales.

Para los usuarios "normales" de la interfaz ("staff", activos, no superusuarios), el acceso de que disfruten depende de un conjunto de permisos asignables. Cada objeto editable en la interfaz de administración posee tres permisos: uno de creación, otro de edición y el de borrado. Asignar permisos a los usuarios les da derecho a hacer lo que describen dichos permisos.

Nota

Tenga en cuenta que el acceso a edición de usuarios y permisos también lo controla el propio sistema de permisos. Si le da a los usuarios permiso para editar usuarios, serán capaces de cambiar sus propios permisos, ¡y probablemente no querrá eso!

También puede asignar usuarios a grupos. Un grupo no es más que un conjunto de permisos que se aplica a todos los miembros del grupo. Pueden ser muy útiles para poder conceder permisos idénticos a gran cantidad de usuarios.

Personalización de la interfaz de administración

Hay varias maneras de personalizar el aspecto de la interfaz de administración. Veremos sólo unas pocas relacionadas con nuestro modelo Libro, pero el Capítulo 12 trata este tema en detalle.

Tal como está ahora, la lista de cambios para nuestros libros sólo muestra la representación textual del modelo que añadimos a su __str__. Esto está bien para unos pocos libros, pero si tenemos cientos o miles de ellos sería difícil buscar una aguja en el pajar. Sin embargo, podemos añadir de forma sencilla algunas funciones de muestra, búsqueda y filtrado a esta interfaz. Cambiemos la declaración Admin así:

class Libro(models.Model):
    titulo = models.CharField(maxlength=100)
    autores = models.ManyToManyField(Autor)
    editorial = models.ForeignKey(Editorial)
    fecha_publicacion = models.DateField()

    class Admin:
        list_display   = ('titulo', 'editorial', 'fecha_publicacion')
        list_filter    = ('editorial', 'fecha_publicacion')
        ordering       = ('-fecha_publicacion',)
        search_fields  = ('titulo',)

Estas cuatro líneas producen cambios profundos en nuestra interfaz de listado:

http://media.djangobook.com/content/chapter06/changelist2.png

Cada una de esas líneas le dice al subsistema de administración que construya una parte diferente de la nueva interfaz:

Usando estas opciones (y las otras descritas en el Capítulo 12) puede crear una interfaz de edición de datos muy potente y preparada para entrar en producción, con sólo añadir unas pocas líneas de código.

Personalización del aspecto del administrador

Está claro que tener "Django administration" en la cabecera de cada página del administrador es ridículo. Es sólo un texto de plantilla.

Es fácil de cambiar usando el sistema de plantillas. El sistema de administración de Django funciona usando el propio Django, así que sus interfaces utilizan el sistema de plantillas. (¡Qué meta!)

Abra el fichero de configuración (recuerde, misitio/settings.py) y busque la opción TEMPLATE_DIRS. TEMPLATE_DIRS es una tupla de directorios del sistema de ficheros que hay que comprobar al cargar plantillas de Django. Es una ruta de búsqueda.

Por omisión, TEMPLATE_DIRS está vacía. Así que añadamos unas líneas, para decirle a Django dónde residen nuestras plantillas:

TEMPLATE_DIRS = (
    "/home/misplantillas", # Cambie esto por su propio directorio.
)

Nota

Asegúrese de incluir aquí la coma del final (Python la usa para distinguir entre tuplas de un único elemento de las expresiones entre paréntesis).

Ahora, copie la plantilla admin/base_site.html que hay dentro del directorio de plantillas de administración de Django (django/contrib/admin/templates) dentro de un subdirectorio admin bajo el directorio que haya indicado en TEMPLATE_DIRS. Por ejemplo, si TEMPLATE_DIRS incluye "/home/misplantillas", copie django/contrib/admin/templates/admin/base_site.html a /home/mytemplates/admin/base_site.html. No olvide ese subdirectorio admin.

Ahora no tiene más que editar el nuevo fichero admin/base_site.html para sustituir el texto genérico de Django con el del nombre de su propio sitio como usted vea mejor.

Observe que puede reemplazar cualquier plantilla de administración de Django. Para reemplazar una plantilla, haga lo mismo que ha hecho con base_site.html (cópiela del directorio por omisión a su directorio de personalizadas y realice cambios sobre la copia).

Los lectores astutos pueden estar preguntándose cómo estaba encontrando Django las plantillas por omisión si TEMPLATE_DIRS estaba inicialmente vacía. La respuesta es que Django busca las plantillas automáticamente bajo un directorio templates/ dentro de cada paquete de aplicación como último recuerso. Vea "Cargadores de plantillas" en el Capítulo 10 si desea más información sobre cómo funciona esto.

Personalización de la página de índice del administrador

De forma similar, podríamos querer personalizar el aspecto de la página de índice del administrador de Django.

Por omisión, muestra todas las aplicaciones disponibles de acuerdo a la opción INSTALLED_APPS, ordenadas por el nombre de la aplicación. Sin embargo podríamos querer cambiar este orden para facilitar la búsqueda de las aplicaciones que estamos buscando. Después de todo, el índice es quizá la página más importante del administrador, así que debería ser sencillo de usar.

La plantilla a personalizar es admin/index.html. (Recuerde copiar admin/base_site.html a su directorio de plantillas como en el ejemplo anterior.) Edite el fichero y verá que usa una etiqueta llamada {% get_admin_app_list as app_list %}. Éste es el código que obtiene cada aplicación instalada. En lugar de usar eso, podemos escribir enlaces prefijados a páginas de administración de objetos concretas de la manera que crea mejor. Si no le agrada prefijar los enlaces, también puede leer en el Capítulo 10 los detalles de implementación de sus propias etiquetas.

Django le ofrece otros atajos en este departamento. Ejecute la orden python manage.py adminindex <aplic> y obtendrá un trozo de código de plantilla para incluir en el índice del administrador. Es un buen punto de partida.

Si quiere más detalles sobre la personalización del aspecto general del sitio de administración, lea el Capítulo 12.

Cuándo usar la interfaz de administración, y por qué

Pensamos que el administrador de Django es bastante espectacular. De hecho, la hemos calificado como una de las características decisivas (killer) de Django. Sin embargo, a menudo nos hacen preguntas sobre los "casos de uso" del administrador (¿cuándo usarlos y por qué?). Con los años, hemos descubierto varios patrones de uso de la interfaz de administración que pensamos podrían ser útiles.

Obviamente, es muy útil para modificar datos (se veía venir). Si tenemos cualquier tipo de tarea de introducción de datos, el administrador es lo mejor que hay. Sospechamos que la gran mayoría de lectores de este libro tiene una horda de tareas de este tipo.

El administrador destaca especialmente cuando se necesita que introduzcan datos usuarios de perfil técnico bajo, ya que fueron el origen de esta característica. En el periódico donde desarrollamos Django por primera vez, la creación de un elemento en línea típico (digamos que un reportaje especial sobre la calidad del agua en el suministro municipal) sería así:

En otras palabras, la raison d'être del administrador de Django es facilitar el trabajo simultáneo de varios productores de contenido y programadores.

Sin embargo, más allá de las tareas obvias de introducción de datos, encontramos que el administrador es útil en otros casos:

¿Qué sigue?

Hasta ahora hemos creado unos pocos modelos y configurado una interfaz increíble para editar esos datos. En el siguiente capítulo pasaremos al meollo del desarrollo Web: creación y proceso de formularios.

Así que tómese otra taza de su brebaje favorito y empecemos.