list_display
list_display controla las columnas que aparecen en el listado del modelo:
from django.contrib import admin
from django.utils.html import format_html
from .models import Producto
@admin.register(Producto)
class ProductoAdmin(admin.ModelAdmin):
list_display = [
'nombre',
'precio_formateado', # Método del ModelAdmin
'categoria',
'activo',
'fecha_creacion',
'imagen_preview' # Método con HTML seguro
]
def precio_formateado(self, obj):
return f'{obj.precio} €'
precio_formateado.short_description = 'Precio'
precio_formateado.admin_order_field = 'precio' # Permite ordenar por este campo
def imagen_preview(self, obj):
if obj.imagen:
return format_html('<img src="{}" width="50" height="50">', obj.imagen.url)
return '—'
imagen_preview.short_description = 'Imagen'

list_filter
list_filter añade una barra lateral de filtros para facilitar la navegación:
list_filter = [
'activo',
'categoria',
'fecha_creacion',
('precio', admin.filters.SimpleListFilter), # Filtro personalizado
]
# Filtro personalizado
class RangoPrecioFilter(admin.SimpleListFilter):
title = 'rango de precio'
parameter_name = 'rango_precio'
def lookups(self, request, model_admin):
return [
('barato', 'Menos de 20 €'),
('medio', 'Entre 20 € y 100 €'),
('caro', 'Más de 100 €'),
]
def queryset(self, request, queryset):
if self.value() == 'barato':
return queryset.filter(precio__lt=20)
elif self.value() == 'medio':
return queryset.filter(precio__gte=20, precio__lte=100)
elif self.value() == 'caro':
return queryset.filter(precio__gt=100)
return queryset
search_fields
search_fields habilita el buscador en el listado. Soporta lookups (__icontains por defecto):
search_fields = [
'nombre',
'descripcion',
'categoria__nombre', # Búsqueda en campo de modelo relacionado
'proveedor__email',
]
Resto de opciones clave
@admin.register(Producto)
class ProductoAdmin(admin.ModelAdmin):
list_display = ['nombre', 'precio', 'activo', 'categoria', 'fecha_creacion']
list_filter = [RangoPrecioFilter, 'activo', 'categoria']
search_fields = ['nombre', 'descripcion']
ordering = ['-fecha_creacion', 'nombre'] # Orden por defecto
list_per_page = 25 # Objetos por página
list_max_show_all = 200 # Máximo al usar "Mostrar todos"
list_editable = ['activo', 'precio'] # Editable directamente en el listado
date_hierarchy = 'fecha_creacion' # Navegación jerárquica por fecha
show_full_result_count = False # Desactiva el conteo total (mejora rendimiento)
# Columnas que se pueden ordenar por clic en cabecera
sortable_by = ['nombre', 'precio', 'fecha_creacion']
Personalización del formulario de edición
@admin.register(Producto)
class ProductoAdmin(admin.ModelAdmin):
# Organizar campos en secciones
fieldsets = [
('Información básica', {
'fields': ['nombre', 'descripcion', 'categoria']
}),
('Precio y disponibilidad', {
'fields': ['precio', 'precio_oferta', 'activo', 'stock'],
'classes': ['collapse'], # Sección colapsable
}),
('Multimedia', {
'fields': ['imagen', 'video_url'],
'description': 'Archivos multimedia del producto',
}),
('Metadatos', {
'fields': ['fecha_creacion', 'fecha_modificacion', 'creado_por'],
'classes': ['collapse'],
}),
]
readonly_fields = ['fecha_creacion', 'fecha_modificacion', 'creado_por']
prepopulated_fields = {'slug': ['nombre']} # Genera slug automáticamente
# Autocompletar campos relacionados (require search_fields en el modelo relacionado)
autocomplete_fields = ['categoria', 'etiquetas']
def save_model(self, request, obj, form, change):
if not change: # Solo al crear
obj.creado_por = request.user
super().save_model(request, obj, form, change)
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Django es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Django
Explora más contenido relacionado con Django y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Configurar list_display para controlar las columnas del listado de modelos. Usar list_filter para añadir filtros laterales por campo. Implementar search_fields para búsqueda de texto en el listado. Definir ordering y list_per_page para ordenación y paginación. Usar list_editable para editar campos directamente desde el listado.