El libro de Django 1.0

17.3. Crear vistas de administración personalizadas

Hasta ahora, cualquiera que haya buscando agregar comportamientos personalizados a la interfaz de administración probablemente esté un poco frustrado. "Todo lo que han dicho es cómo cambiar la interfaz visualmente", los escuchamos llorar. "¿Pero como puedo cambiar la forma en que la interfaz de administración funciona?"

La primer cosa para entender es que esto no es mágico. Esto es, nada de lo que la interfaz hace es especial de manera alguna — ya que se trata simplemente de un conjunto de vistas (que se encuentran en django.contrib.admin.views) que manipulan datos como cualquier otra vista.

Seguro, hay bastante código allí, y se debe a que tienen que lidear con todas las opciones, diferentes tipos de campos, y configuraciones que influyen en el comportamiento. No obstante, cuando te das cuenta que la interfaz de administración es sólo un juego de vistas, agregar las tuyas propias es más fácil de entender.

A modo de ejemplo, agreguemos una vista "reporte de editores" a nuestra aplicación de libros del Capítulo 6. Construiremos una vista de administración que muestre la lista de libros en función de los editores — un ejemplo bastante típico de vista de "reporte" que puedes necesitar construir.

Primero, actualicemos nuestro archivo URLconf. Necesitamos insertar esta línea:

(r'^admin/books/report/$', 'mysite.books.admin_views.report'),

antes de la línea que incluye las vistas del administrador. Un esqueleto del URLconf puede parecerse a algo así:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^admin/libreria/reporte/$', 'libreria.admin_views.reporte'),
    (r'^admin/', include('django.contrib.admin.urls')),
)

¿Por qué ponemos la vista personalizada antes de incluir las del administrador? Recuerda que Django procesa los patrones de URL en orden. La inclusión de los patrones de URLs del administrador coincide con casi cualquier cosa que llega a su punto de inclusión, por lo que si invertimos el orden de esas lineas, Django encontrará una vista por omisión para ese patrón y no funcionará como queremos. En este caso particular, intentará cargar un un lista de cambios para un modelo "Reporte" en la aplicación "libros", que no existe.

Ahora escribamos nuestra vista. Para hacer honor a la simplicidad, sólo cargaremos todos los libros dentro del contexto, y dejaremos que la plantilla maneje el agrupamiento con la etiqueta {% regroup %}. Crea un archivo books/admin_views.py, con este código:

from mysite.books.models import Book
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.contrib.admin.views.decorators import staff_member_required


def report(request):
    return render_to_response(
        "admin/books/report.html",
        {'book_list' : Book.objects.all()},
        RequestContext(request, {}),
    )
report = staff_member_required(report)

Debido a que dejamos el agrupamiento a la plantilla, esta vista es bastante simple. Sin embargo, hay algunos fragmentos sutiles dignos de explicitar:

  • Usamos el decorador staff_member_required de django.contrib.admin.views.decorators. Esto es similar a login_required discutido en el Capítulo 12, pero este decorador también verifica que el usuario esté marcado como un mientro del "staff", y tenga en consecuencia acceso a la interfaz de administración.

    Este decorador protege todos las vistas predefinidas del administrador, y hace que la lógica de autenticación para tus vistas coincida con la del resto de la interfaz.

  • Renderizamos una plantilla que se encuentra bajo admin/. Aunque esto no es estrictamente requerido, se considera una buena practica para mantener todas tus plantillas de administración agrupadas en un directorio admin/. También pusimos la plantilla en un directorio llamado books luego de nuestra aplicación — lo que es también una buena práctica.
  • Usamos RequestContext como el tercer parámetro (context_instance) para render_to_response. Esto asegura que la información sobre el usuario en curso está disponible para la plantilla.

    Mira el Capítulo 10 para saber más sobre RequestContext.

Finalmente, haremos una plantilla para esta vista. Extenderemos una plantilla de la administración para que lograr que nuestra vista coincida visualmente con el resto de la interfaz:

{% extends "admin/base_site.html" %}

{% block title %}List of books by publisher{% endblock %}

{% block content %}
<div id="content-main">
  <h1>List of books by publisher:</h1>
  {% regroup book_list|dictsort:"publisher.name" by publisher as books_by_publisher %}
  {% for publisher in books_by_publisher %}
    <h3>{{ publisher.grouper }}</h3>
    <ul>
      {% for book in publisher.list|dictsort:"title" %}
        <li>{{ book }}</li>
      {% endfor %}
    </ul>
  {% endfor %}
</div>
{% endblock %}

Al extender admin/base_site.html, conseguimos el look and feel de la interfaz de administración de Django "gratis". La Figura 17-2 muestra como luce el resultado.

Una vista personalizada "libros por editor"

Figura 17.2 Una vista personalizada "libros por editor"

Puedes usar esta técnica para agregar cualquier cosa que sueñes para la interfaz de administración. Recuerda que las llamadas vistas de administración personalizadas en realidad son sólo vistas comunes de Django; por lo que puedes usar todas las técnicas aprendidas en el resto de este libro para proveer una interfaz con tanta complejidad como necesites.

Cerraremos este capítulo con algunas ideas para vistas de administración personalizadas.