Comunidad de diseño web y desarrollo en internet

Python en la web con Django (VI): web de administración

Ya hemos visto mucho sobre base de datos y nuestros modelos. Ahora vamos a ver como agregar, editar y eliminar datos de una manera cómoda y sencilla. El uso de esta web está dedicado a muchos fines: crear entradas de un blog, subir productos de una tienda, gestión de usuarios, etc..

Como he dicho, el panel de administración es una Web, limitada a administradores, que permite agregar, editar y eliminar el contenido del sitio. También nos ayuda con la gestión de usuarios si usamos los modelos propios de django (los veremos en el próximo tutorial).

Esta Web funciona leyendo clases que heredan de django.contrib.admin.ModelAdmin y que describe una serie de atributos que se corresponden a metadatos de nuestros modelos.

Activando la interfaz


Hay varios pasos a seguir para mostrar la Web de administración:

  1. Instalar las aplicaciones a nuestro proyecto. Tendremos que agregar a nuestra variable INSTALLED_APPS del fichero settings.py las siguientes aplicaciones:
    -django.contrib.admin
    -django.contrib.sessions
    -django.contrib.auth
    -django.contrib.contenttypes

  2. Descomentar todas las líneas de la variable MIDDLEWARE_CLASSES y borrar o comentar la definicion de la variable TEMPLATE_CONTEXT_PROCESSOR al menos de momento. El fichero settings quedará así:

    Código :

    alberto@a-AMILO-Si-3655:~/django/tutorial$ view settings.py
        [...]
         96 MIDDLEWARE_CLASSES = (
         97     'django.middleware.common.CommonMiddleware',
         98     'django.contrib.sessions.middleware.SessionMiddleware',
         99     'django.middleware.csrf.CsrfViewMiddleware',
        100     'django.contrib.auth.middleware.AuthenticationMiddleware',
        101     'django.contrib.messages.middleware.MessageMiddleware',
        102 )
        [...]
        110 INSTALLED_APPS = (
        111     'django.contrib.auth',
        112     'django.contrib.contenttypes',
        113     'django.contrib.sessions',
        114     #'django.contrib.sites',
        115     #'django.contrib.messages',
        116     #'django.contrib.staticfiles',
        117     'tutorial.foro',
        118     # Uncomment the next line to enable the admin:
        119     'django.contrib.admin',
        120     # Uncomment the next line to enable admin documentation:
        121     # 'django.contrib.admindocs',
        122 )

  3. Agregar a nuestra lista de urls el registro para la web de administración. Para esto tenemos que importar admin del paquete django.contrib(linea 3) e incluir todas las urls de este paquete para el patron de url que queramos(linea 7):

    Código :

    alberto@a-AMILO-Si-3655:~/django/tutorial$ view urls.py
          1 from django.conf.urls.defaults import *
          2 from tutorial.firstView import holaMundo, suma
          3 from django.contrib import admin
          4 
          5 
          6 urlpatterns = patterns('',
          7         (r'^admin/', include(admin.site.urls)),
          8         (r'^hola/$',holaMundo),
          9         (r'^suma/(\d+)/(\d+)/$',suma),
         10 )

    Cosas que aclarar antes de seguir. El concepto de include en vistas no lo hemos estudiado aun así que creedme que esto va así y ya lo comprenderéis mejor en el tuto de vistas avanzadas. Mirad también que no he puesto ningún símbolo de dólar, esto también se debe al include así que copiar y pegar.

  4. Sincronizar la base de datos con el proyecto para que cree las tablas necesarias. Para esto ya sabéis que tenemos que lanzar "python manage.py syncdb".
    En este paso nos dirá si queremos crear un superusuario. Esto es obligatorio porque si no no podremos entrar en la web de administración.
    Si no nos pide crear el superusuario podremos lanzar "python manage.py createsuperuser" para crear uno. Esto usará el script de django/contrib/auth/create_superuser.py dentro de la carpeta de instalación de django.

    Código :

    alberto@a-AMILO-Si-3655:~/django/tutorial$ python manage.py syncdb
    Creating tables ...
    Creating table auth_permission
    Creating table auth_group_permissions
    Creating table auth_group
    Creating table auth_user_user_permissions
    Creating table auth_user_groups
    Creating table auth_user
    Creating table auth_message
    Creating table django_content_type
    Creating table django_session
    Creating table django_admin_log
    
    You just installed Django's auth system, which means you don't have any superusers defined.
    Would you like to create one now? (yes/no): yes
    Username (Leave blank to use 'alberto'): 
    E-mail address: a.chamorro.ruiz@gmail.com
    Password: 
    Password (again): 
    Superuser created successfully.
    Installing custom SQL ...
    Installing indexes ...
    No fixtures found.

  5. Arrancar nuestro servidor y abrir en nuestro navegador la url http://127.0.0.1:8000/admin


Configurar nuestros modelos para la web de administración


Tenemos dos formas de configurar un modelo para que aparezca en la web de administración. Para ambas tendremos que importar admin del paquete django.contrib.

Sin opciones


Si queremos que django use todas las opciones por defecto para un modelo podremos incluir este con la sentencia admin.site.register(<referencia_modelo>)

Con opciones


Si queremos editar las opciones en las que será tratado nuestro modelo, tendremos que crear una clase(fuera del modelo) que herede de la clase admin.ModelAdmin del paquete django.contrib y asociarla a nuestro modelo con la sentencia admin.site.register(<referencia_modelo>,<referencia_clase_administracion>)

Aquí un ejemplo de las dos formas:

Código :

alberto@a-AMILO-Si-3655:~/django/tutorial/foro$ view models.py
from django.db import models
from django.contrib import admin

# Create your models here.
class Temas(models.Model):
   titulo = models.CharField(max_length=40)
   cuerpo = models.CharField(max_length=300)

class TemasAdmin(admin.ModelAdmin):
   pass

class Comentarios(models.Model):
   texto = models.CharField(max_length=150)
   tema = models.ForeignKey(Temas)


admin.site.register(Temas,TemasAdmin)
admin.site.register(Comentarios)

admin.autodiscover()


Aquí hay una línea que no hemos comentado(admin.autodiscover()). Con esta sentencia conseguimos incluir los modelos User y Group propios de django.
Si en algún momento editamos de manera errónea un modelo y tenemos el servidor arrancado este se parará automáticamente indicando el por qué del error.

Usando la interfaz


Lo primero que veremos será la pantalla de autenticación. Aquí introduciremos usuario y password del superusuario.
Un vez dentro veremos varios bloques:

  1. Los modelos de gestión de usuarios -> Users y Groups
  2. Los modelos que hayamos registrado el el objeto admin. A estos modelos se les agrega la letra s al final indicando plural por lo que en nuestro caso Temas lo veremos como Temass. De ahi que se desaconseje indicar con plurales los nombres de los modelos ;-)
  3. A la derecha registro de las acciones que se han hecho en la web

Si pulsamos en el enlace de algún modelo iremos a lo que se llama listas de cambios. Estas listas se corresponden con el listado de todos los datos insertados en la tabla correspondiente. Ahora veremos como personalizarla.

Si en la lista de cambios pulsamos sobre uno de los registros se abrirá lo que se denomina como formulario de edición. Estos formularios sirven para editar registros, crear nuevos o borrarlos. Dependiendo del tipo de campo django usara un tipo de elemento html para su correcta edición. Estos formularios también podemos personalizarlos, lo vemos ahora.

Usuarios y grupos


El superusuario puede crear, editar y eliminar cualquier objeto.
Podemos editar usuarios y permisos a través de los módulos Users y Groups.
Vamos a entrar en Users-><nuestro usuario> para ver todo lo que tenemos:

  • datos básicos: email, nombre de usuario y contraseña son obligatorios. Después nombre completo como opcional.
  • permisos:
    *Active: si el usuario está activo o no.
    *Staff status: indica si el usuario puede entrar a la web de administración o no.
    *Superuser status: indica si el usuario es superusuario. Peligroso!!
    *User permissions: en caso de no ser superusuario pero si de staff podremos personalizar que permisos tendrá sobre que modelos.
  • fechas importantes: fecha de creación y último login.
  • grupos: a los que pertenece el usuario. Un grupo es un conjunto de permisos comunes para poder aplicar a unos determinados usuarios.


Personalizando la interfaz


Como estamos ahora, la lista de cambio no muestra información como para poder seleccionar fácilmente el elemento que queremos editar. Podemos agregar columnas, filtros, funciones de búsqueda, ...
También podremos editar los formularios de edición seleccionando los campos que queremos mostrar para editar, marcar campos como no editables o simplemente creando categorías dependiendo de los campos.

Para editar cualquiera de las dos funcionalidades de la web de administración tendremos que añadir atributos especiales a nuestra clase ModelAdmin del modelo.
Os pongo los más comunes pero podéis ver todos en la url https://docs.djangoproject.com/en/1.3/ref/contrib/admin/

Lista de cambios



  • list_display : controla las columnas que aparecen en la lista. Este atributo debe igualarse a una lista y acepta tanto strings con los nombres de los campos del modelo como referencias de funciones de formateo de los campos. Estas funciones pueden estar dentro de la clase ModelAdmin, dentro del modelo o fuera de todos estos. Pero cuidado! Si la función se encuentra dentro de alguna de las clases la referencia en el atributo list_display irá como string pero si la función está fuera de estas clases debemos pasar al atributo la referencia de la clase. Para que lo veamos mejor os pongo los ejemplos posibles:

    Ejemplo con campos del modelo sin formatear:

    Código :

    class TemasAdmin(admin.ModelAdmin):
       list_display = ('id','titulo','cuerpo',)
    [...]
    admin.site.register(Temas,TemasAdmin)


    Ejemplo de una función fuera de cualquier clase:

    Código :

    def titulo_upper(tema):
       return ("%s" % (tema.titulo)).upper()
    titulo_upper.short_description = "Titulo"
    
    class TemasAdmin(admin.ModelAdmin):
       list_display = (titulo_upper,)


    Ejemplo de una función dentro del modelo:

    Código :

    class Temas(models.Model):
       titulo = models.CharField(max_length=40)
       cuerpo = models.CharField(max_length=300)
    
       def titulo_upper(self):
          return ("%s" % (self.titulo)).upper()
       
       titulo_upper.short_description = "Titulo"
    
    class TemasAdmin(admin.ModelAdmin):
       list_display = ('titulo_upper',)


    Ejemplo de una función dentro de la clase ModelAdmin:

    Código :

    class TemasAdmin(admin.ModelAdmin):
       list_display = ('titulo_upper',)
       [...]
    
       def titulo_upper(self,tema):
          return ("%s" % (tema.titulo)).upper()
       
       titulo_upper.short_description = "Titulo"

    Habréis notado que he modificado un atributo de la función, concretamente el atributo short_description. Si no modificáramos este valor en nuestra web de administración aparecería el nombre de la función y no queremos eso ¿verdad?

    Cosas a tener en cuenta:
    -No acepta campos ManyToManyField.
    -Una función puede devolver HTML pero tendremos que indicar el atributo allow_tags=True a la función(como hemos hecho con short_description).
    -Si el campo es un ForeignField se mostrará como unicode.

  • list_filter : crea una barra de filtrado del lado derecho del listado. Se puede indicar que filtre por cualquier campo pero booleanos, fechas y claves foráneas son las que mejor funcionan. El filtro aparece cuando tiene al menos 2 valores diferentes para el campo.

    Código :

    list_filter = ('created',)

  • ordering : orden en el que se muestra el listado. Podemos ordenar de manera inversa con un signo - delante del nombre del campo.

    Código :

    ordering = ('created',)
    ordering = ('-created',)

  • search_fields : habilita una caja de texto para buscar. Tendremos que indicarle los campos en los que buscará el texto.

    Código :

    search_fields = ('titulo','cuerpo',)



Formularios de edición



  • fields : listado con los campos que queremos que se muestren en el formulario.

    Código :

    fields = ('titulo',)

  • exclude : función inversa a fields. Campos que no queremos que aparezcan.

    Código :

    exclude = ('cuerpo',)

  • readonly_fields : no permitirá editar los campos que le pasemos.

    Código :

    readonly_fields = ('titulo',)

  • fieldsets : podemos crear categorías en el formulario de edición diferenciar campos por su contenido. Este atributo espera una lista que contenga tuplas con dos valores (<nombre_de_la_categoria>,<diccionario_de_opciones>). Parece complejo pero mirad el ejemplo y después ir al formulario de edición y lo comprenderéis:

    Código :

    class TemasAdmin(admin.ModelAdmin):
       list_display = ('titulo_upper',)
       list_filter = ('id',)
       ordering = ('id',)
       search_fields = ('titulo','cuerpo',)
       fieldsets = (
          ('Titulo', {'fields': ('titulo',)} ),
          (None , {'fields': ('cuerpo',)} )
          )



Como ya he dicho esto son sólo opciones de las más comunes e incluso atributos como fieldsets tienen más posibilidades. Para saber más a la documentación oficial de django.

Personalizando la plantilla


Como ya dijimos, la variable TEMPLATE_DIRS es una lista con los directorios que contienen plantillas de nuestro proyecto.
Si queremos modificar la apariencia de la web de administración tendremos que crear una carpeta admin en alguno de los directorios de TEMPLATE_DIRS y copiar ahí el fichero de la plantilla original que queramos editar. Las plantillas originales se encuentran en el directorio de instalación de django en la ruta django/contrib/admin/templates/admin.

Por ejemplo si queremos modificar el titulo de la ventana tendremos que copiar el fichero 'base_site.html'. Vamos a ello. En mi TEMPLATE_DIRS tenía el directorio del proyecto y ahí dentro la carpeta templates(/home/alberto/django/tutorial/templates). Pues mirad como queda:

Código :

alberto@a-AMILO-Si-3655:~/django/tutorial/templates$ tree admin
admin
└── base_site.html


Ahora cambiamos el bloque del título por lo que nosotros queramos:

Código :

#ORIGINAL
{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}

Código :

#PERSONALIZADO
{% block title %}Esto es CRISTALAB{% endblock %}



No tiene mala pinta esta web ¿verdad? Y además es muy sencilla de usar.
He de comunicaros que sólo quedan 3 tutoriales si no los he contado mal que son: cookies y sesiones, vistas avanzadas y django con apache y mod_python.
Mensaje a todos los que estáis interesados en desarrollo con Python y Django: debemos movilizarnos y pedir que nos abran un foro en la categoría de desarrollo ¿no creéis? ¿un "ataque" twitter a @cristalab?

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate