Curso Python. Volumen XIX: Framework Django. Parte VI

Escrito por Javier Ceballos Fernández
Programación

Bienvenidos un día más al curso de Python, hoy vamos a continuar con la web de administración que nos proporciona el framework Django que os mostramos en el capítulo anterior. Nos centraremos en la personalización de los formularios que tiene para que se adapte mejor a nuestra aplicación. Así que pongámonos manos a la obra.

Personalización del formulario del administrador

Comprobamos en el capítulo anterior que por escribir una simple línea de código, se nos generaba todo el código necesario de un formulario, de modo que no tuviéramos que escribirlo nosotros. Esto es gracias al framework de Django, ya que registrando el modelo “Pregunta” con “admin.site.register(Pregunta)”, el framework supo que tenía que construir los formularios por defecto para poder acceder a la información básica de estos.

Es verdad que en muchas ocasiones no nos valdrá con el formulario por defecto y querremos personalizarlo. Esto lo vamos a conseguir introduciendo algunos parámetros cuando realizamos el registro del modelo. Por ejemplo vamos a realizar una reordenación de campo dentro del formulario de edición. Para esto tendremos que sustituir la línea “admin.site.register(Question)” por el siguiente código:

polls/admin.py
from django.contrib import admin
from .models import Pregunta

class PreguntaAdmin(admin.ModelAdmin):
    fields = ['fecha_publi', 'texto_pregunta']

admin.site.register(Pregunta, PreguntaAdmin)

Como podéis comprobar, lo que hemos hecho es crear una clase “PreguntaAdmin” que entiende de “admin.ModelAdmin” para definir dentro el orden de los campos, después cuando realizamos el registro del modelo también ponemos como parámetro esta nueva clase, de este modo Django sabe qué orden queremos. Siempre se tendrá que realizar de este modo para realizar cambios en los formularios.

Una vez guardado el código anterior comprobaréis que “Fecha Publicación” se muestra antes que el campo “Pregunta”:

Esto es muy importante en formularios con muchos campos, debido a que el orden que se escoja puede influir es su usabilidad de cara al usuario final. Pensando en usabilidad podríamos querer dividir los formularios en distintos “fieldsets”. Para realizar esto tendremos que hacer lo siguiente:

polls/admin.py
from django.contrib import admin
from .models import Pregunta

class PreguntaAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {'fields': ['texto_pregunta']}),
        ('Informacion de Fecha', {'fields': ['fecha_publi']}),
    ]

admin.site.register(Pregunta, PreguntaAdmin)

Cada lista que define los “fieldsets” contiene dos parámetros, el primero define el título y el segundo la lista de campos que se van a mostrar. Después de realizar estos cambios el formulario se verá de este otro modo:

También podemos asignar clases HTML a cada “fieldset” para proporcionarles de una funcionalidad. Por ejemplo “Django” provee una clase “collapse” que muestra el “fieldset” inicialmente plegado. Esto es útil cuando uno tiene un formulario que es muy extenso y tiene campos que no son muy usados:

polls/admin.py
from django.contrib import admin
from .models import Pregunta

class PreguntaAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {'fields': [texto_pregunta']}),
        ('Informacion Fecha', {'fields': ['fecha_publi'], 'classes': ['collapse']}),
    ]

admin.site.register(Pregunta, PreguntaAdmin)

Agregando objetos relacionados

Hasta ahora tenemos nuestro formulario para nuestro modelo “Pregunta”. Pero un objeto “Pregunta” puede tener varias “Opciones”, aunque estas ahora mismo no son mostradas. Para mostrar estas “Opciones” existen dos maneras de hacerlo. La primera es registrar “Opcion” con el administrador como hicimos con “Pregunta”. Esta sería la solución más sencilla y lo implementaríamos del siguiente modo:

polls/admin.py
from django.contrib import admin
from .models import Opcion, Pregunta

# ...

admin.site.register(Opcion)

Ahora “Opciones” está disponible en el administrado de “Django”. El formulario de “Add Option” sería del siguiente modo:

En este formulario, podemos ver que el campo “Pregunta” es un desplegable que contiene todas las preguntas de la base de datos. Django sabe que una clave ajena hay que mostrarla como un “<select>” en el administrador. En nuestro caso, existe solamente una pregunta por el momento.

Si os dais cuenta también ha agregado un enlace “Add Another” al lado de “Pregunta”. Esto es debido a que al existir una relación de clave ajena el propio “Django” lo añade. Cuando hagáis click en “Add Another”, se abrirla una ventana emergente con el formulado de “Add pregunta”. Si lo rellenáis el formulario y hacéis click en “Save”, “Django” guardará la pregunta en la base de datos y además la seleccionará dinámicamente como valor en el formulario de “Add choice” que estábamos rellenando.

Aunque es cierto que esta no es la mejor manera de hacerlo, ya que sería mucho más intuitivo y fácil para el usuario si a la vez que crea la “Pregunta” pudiera ir rellenando sus “Opciones”.

Entonces vamos a modificar el código anterior para que lo tengamos todo en un único formulario. Para ello lo primero que tenemos que hacer es borrar la llamada al método “register()” que hemos añadido para el modelo “Opcion”. A continuación editaremos el código del siguiente modo:

polls/admin.py
from django.contrib import admin
from .models import Opcion, Pregunta

class OpcionEnLinea(admin.StackedInline):
    model = Opcion
    extra = 3

class PreguntaAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {'fields': [texto_pregunta']}),
        ('Date information', {'fields': ['fecha_publi'], 'classes': ['collapse']}),
    ]
    inlines = [OpcionEnLinea]

admin.site.register(Pregunta, PreguntaAdmin)

Este código le indica a “Django” que los objetos “Opcion” se editan en la página de administración de “Pregunta” y además que por defecto, contara con 3 campos “Opcion”.

Si nos dirigimos a la página de “Add pregunta” nos mostrará lo siguiente:

De este modo tan sencillo lo tenemos todo en un formulario. Además, si miramos al final de los 3 “opciones” encontraremos un enlace para agregar una nueva “Opcion” (“Add another Opcion”). Si se hace click en el mismo, veremos cómo se añade una opción más al formulario que estará lista para ser rellenada. Si por el contrario lo que se quiere es eliminar una “Opcion” tan solo tendremos que pulsar en la “X” que se encuentra en la esquina superior derecha de la “Opcion”. Aunque solo podremos eliminar hasta quedarnos en el número de “Opciones” por defecto. A continuación os mostramos una “Opcion” agregada:

Podréis comprobar que el formulario con las opciones de este modo ocupa mucho espacio de pantalla. “Django” nos ofrece una alternativa para poder corregir este problema. Para eso tendremos que hacer que nuestra clase “OpcionEnLinea” derive de “admin.TabularInline” en ver de “StackedInline” como os mostramos en el código que se muestra a continuación:

polls/admin.py

class OpcionEnLinea(admin.TabularInline):

#...

Con “TabularInline”, lo que conseguimos es que los objetos los mostremos en formato de tabla y así aparezcan más compactos:

Si os fijáis, ahora tendremos una columna extra con la opción “Delete?” que nos permite borrar las filas que hayamos agregado usando el botón “Add Another Opcion”.

Hasta aquí el capítulo de hoy, como podéis comprobar Django nos facilita la tarea de personalización evitándonos escribir la mayor parte del código. Os invitamos como siempre a que sigáis explorando este framework y probando. Y para todos los que se acaban de incorporar indicarles que tenemos un índice con todos los capítulos del curso, ya que nunca es tarde para empezar.


Continúa leyendo
  • Alejandro Hurtado

    Te sugiero que pongas en los títulos de tus post, un titulo del tema NO como pate I, II, etc

    • Hola,

      Gracias por la sugerencia pero no podemos poner titulares tan largos, da problemas tanto en las redes sociales como visibilidad del artículo en Google.

Últimos análisis

Valoración RZ
8
Valoración RZ
9
Valoración RZ
9
Valoración RZ
10
Valoración RZ
9
Valoración RZ
10
Valoración RZ
7
Valoración RZ
9
Valoración RZ
10