Escribiendo tu primera aplicación de Django, parte 7

Este tutorial comienza donde Tutorial 6 dejó. Continuamos con la aplicación de encuestas en línea y nos enfocaremos en personalizar el sitio administrativo generado automáticamente por Django que exploramos por primera vez en Tutorial 2.

¿Dónde obtener ayuda:

Si tienes problemas al seguir este tutorial, por favor dirígete a la sección Ayuda del FAQ.

Personaliza la forma del administrador

Al registrar el modelo Question con admin.site.register(Question), Django pudo construir una representación de formulario predeterminada. A menudo, querrás personalizar cómo se ve y funciona la forma del administrador. Lo harás contando a Django las opciones que deseas cuando registres el objeto.

Vamos a ver cómo funciona reordenando los campos en la forma de edición. Reemplaza la línea admin.site.register(Question) con:

polls/admin.py
from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fields = ["pub_date", "question_text"]


admin.site.register(Question, QuestionAdmin)

Sigue este patrón – crea una clase de administración del modelo, luego pasa como segundo argumento a admin.site.register(): cualquier vez que necesites cambiar las opciones de administración para un modelo.

Esta particular modificación anterior hace que la fecha de publicación aparezca antes del campo «Pregunta»:

Los campos han sido reordenados

Aunque esto no es impresionante con solo dos campos, elegir un orden intuitivo es un detalle importante para la usabilidad en formularios administrativos con decenas de campos.

Y hablando de formularios con decenas de campos, podrías querer dividir el formulario en grupos de campos:

polls/admin.py
from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {"fields": ["question_text"]}),
        ("Date information", {"fields": ["pub_date"]}),
    ]


admin.site.register(Question, QuestionAdmin)

El primer elemento de cada tupla en fieldsets es el título del grupo de campos. Aquí está cómo se ve nuestro formulario ahora:

El formulario tiene grupos de campos ahora

Personaliza la lista de cambio del administrador

Ahora que la página de administración de preguntas está bien, vamos a hacer algunas ajustes a la «lista de cambio» – la página que muestra todas las preguntas en el sistema.

Esto es lo que se ve en este punto:

La página de lista de encuestas cambia

Por defecto, Django muestra la str() de cada objeto. Pero a veces sería más útil si pudiéramos mostrar campos individuales. Para hacer eso, utiliza la opción administrativa list_display del administrador, que es una lista de nombres de campo para mostrar, como columnas, en la página de cambio de lista para el objeto:

polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ["question_text", "pub_date"]

Para mayor medida, incluye también el método was_published_recently() de Tutorial 2:

polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ["question_text", "pub_date", "was_published_recently"]

La página de cambios de preguntas ahora se ve así:

Página de cambio de encuestas actualizada

Puedes hacer clic en los encabezados de columna para ordenar por esos valores – excepto en el caso del encabezado was_published_recently, porque ordenar por la salida de un método arbitrario no está soportado. También ten en cuenta que el encabezado de columna para was_published_recently es, por defecto, el nombre del método (con subrayados reemplazados por espacios), y que cada línea contiene la representación de cadena de la salida.

Puedes mejorar eso utilizando el decorador display() en ese método (extendiendo el archivo polls/models.py creado en Tutorial 2), como sigue:

polls/models.py
from django.contrib import admin


class Question(models.Model):
    # ...
    @admin.display(
        boolean=True,
        ordering="pub_date",
        description="Published recently?",
    )
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now

Para más información sobre las propiedades configurables a través del decorador, consulta la propiedad list_display.

Edita de nuevo tu archivo polls/admin.py y agrega una mejora a la página de cambio de preguntas: filtros utilizando la opción administrativa list_filter. Agrega la siguiente línea a QuestionAdmin:

list_filter = ["pub_date"]

Eso agrega un «Filtro» lateral que permite a las personas filtrar la lista de cambios por el campo pub_date:

Página de cambio de encuestas actualizada

El tipo de filtro mostrado depende del tipo de campo en el que estás filtrando. Porque pub_date es un DateTimeField, Django sabe dar opciones de filtro apropiadas: «Cualquier fecha», «Hoy», «7 días pasados», «Este mes», «Este año».

Esto está resultando bien. Vamos a agregar la capacidad de búsqueda:

search_fields = ["question_text"]

Eso agrega una caja de búsqueda en la parte superior de la lista de cambios. Cuando alguien ingresa términos de búsqueda, Django buscará el campo question_text. Puedes utilizar tantos campos como desees – aunque porque utiliza una consulta LIKE detrás de escena, limitar el número de campos de búsqueda a un número razonable hará que sea más fácil para tu base de datos realizar la búsqueda.

Es también un buen momento para señalar que las listas de cambios te dan paginación gratuita. El valor por defecto es mostrar 100 elementos por página. Paginación de lista de cambios, cajas de búsqueda, filtros, jerarquías de fecha y ordenación del encabezado de columna funcionan juntos como crees que deberían.

Personaliza la apariencia del administrador

Claramente, tener «Django administration» en la parte superior de cada página de administración es ridículo. Es solo texto de relleno.

Puedes cambiarlo, aunque, utilizando el sistema de plantillas de Django. El administrador de Django está impulsado por Django mismo y sus interfaces utilizan el propio sistema de plantillas de Django.

Personalizar las plantillas de tu proyecto

Crea un directorio templates en tu directorio djangotutorial. Las plantillas pueden vivir en cualquier lugar del filesystem que pueda acceder Django. (Django corre como el usuario con el que se ejecuta tu servidor.) Sin embargo, mantener tus plantillas dentro del proyecto es una buena convención para seguir.

Abre tu archivo de configuración (mysite/settings.py, recuerda) y agrega un DIRS opción en la TEMPLATES configuración:

mysite/settings.py`
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

DIRS es una lista de directorios del filesystem a buscar cuando se cargan las plantillas de Django; es un camino de búsqueda.

Organizando plantillas

Al igual que los archivos estáticos, podríamos tener todas nuestras plantillas juntas, en un directorio de plantillas grande y único, y funcionaría perfectamente bien. Sin embargo, las plantillas que pertenecen a una aplicación particular deben colocarse en el directorio de plantillas de esa aplicación (por ejemplo, polls/templates) en lugar del proyecto (templates). Discutiremos con más detalle en la tutorial de aplicaciones reutilizables por qué lo hacemos.

Ahora crea un directorio llamado admin dentro de templates, y copia el template admin/base_site.html desde el directorio de plantillas predeterminadas del administrador de Django en el código fuente de Django mismo (django/contrib/admin/templates) a ese directorio.

¿Dónde están los archivos de código fuente de Django?

Si tienes dificultades para encontrar dónde se encuentran los archivos de código fuente de Django en tu sistema, ejecuta el siguiente comando:

$ python -c "import django; print(django.__path__)"

Luego, edita el archivo y reemplaza {{ site_header|default:_('Administración de Django') }} (incluyendo las llaves) con el nombre de tu sitio como prefieras. Deberías terminar con una sección de código como:

{% block branding %}
<div id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></div>
{% if user.is_anonymous %}
  {% include "admin/color_theme_toggle.html" %}
{% endif %}
{% endblock %}

Usamos este enfoque para enseñarte a sobreescribir plantillas. En un proyecto real, probablemente usarías la django.contrib.admin.AdminSite.site_header atributo para hacer esta personalización particular de manera más fácil.

Este archivo de plantilla contiene mucho texto como {% block branding %} y {{ title }}. Las etiquetas {% y {{ son parte del lenguaje de plantillas de Django. Cuando Django renderice admin/base_site.html, este lenguaje de plantillas se evaluará para producir la página HTML final, al igual que vimos en Tutorial 3.

Tenga en cuenta que cualquier plantilla de administrador predeterminada de Django puede ser sobrescrita. Para sobreescribir una plantilla, haz lo mismo que hiciste con base_site.html – copia desde el directorio predeterminado a tu directorio personalizado y haz cambios.

Personalizando las plantillas de tus aplicaciones

Los textos traducidos manteniendo todas sus etiquetas intactas son:

Nuestra aplicación de encuesta no es muy compleja y no necesita templates administrativos personalizados. Pero si creciera más sofisticada y requiriera la modificación de los templates administrativos estándar de Django para alguna de sus funcionalidades, sería más sensato modificar los templates de la aplicación, en lugar de aquellos del proyecto. De esta manera, podrías incluir la aplicación de encuestas en cualquier nuevo proyecto y estar seguro de que encontraría los templates personalizados que necesitaba.

Consulte la documentación sobre [carga de plantillas](template-loading) para obtener más información sobre cómo Django encuentra sus plantillas.

Personaliza la página de inicio del administrador

De manera similar, podrías querer personalizar el aspecto y la sensación de la página de inicio del administrador de Django.

Por defecto, muestra todas las aplicaciones en INSTALLED_APPS que han sido registradas con la aplicación administrativa, en orden alfabético. Es posible que desees hacer cambios significativos en el diseño. Después de todo, la página de inicio es probablemente la página más importante del administrador y debe ser fácil de usar.

La plantilla para personalizar es admin/index.html. (Haz lo mismo que con admin/base_site.html en la sección anterior – copia el archivo desde el directorio predeterminado a tu directorio de plantillas personalizadas). Edita el archivo y verás que utiliza una variable de plantilla llamada app_list. Esa variable contiene todas las aplicaciones Django instaladas. En lugar de utilizar esa, puedes codificar enlaces a páginas administrativas específicas de objetos de la manera que mejor te parezca.

Cuando estés cómodo con el administrador, lee [parte 8 de este tutorial](tutorial08) para aprender a usar paquetes de terceros.