Una de las partes más potentes de Django es la interfaz de administración automática. Lee metadatos de tus modelos para proporcionar una interfaz rápida y centrada en el modelo donde los usuarios autorizados pueden gestionar contenido en tu sitio. El uso recomendado del admin está limitado a herramientas de gestión interna de una organización. No se trata de construir toda la parte frontal alrededor.
El admin tiene muchas oportunidades para personalizarlo, pero ten cuidado de no utilizar únicamente esas oportunidades. Si necesitas proporcionar una interfaz centrada en el proceso que abstracta los detalles de implementación de las tablas y campos de la base de datos, entonces es probable que sea hora de escribir tus propias vistas.
En este documento se discute cómo activar, utilizar y personalizar la interfaz de administración de Django.
El admin está habilitado en el plantilla de proyecto por defecto utilizada por startproject.
Si no estás utilizando el plantilla de proyecto por defecto, aquí están los requisitos:
Añade 'django.contrib.admin' y sus dependencias - django.contrib.auth, django.contrib.contenttypes, django.contrib.messages, y django.contrib.sessions - a tu configuración de INSTALLED_APPS.
Configura un backend de plantillas DjangoTemplates en tu configuración de TEMPLATES con django.template.context_processors.request, django.contrib.auth.context_processors.auth, y django.contrib.messages.context_processors.messages en la opción 'context_processors' de <OPTIONS <TEMPLATES-OPTIONS>>.
Si has personalizado la configuración de MIDDLEWARE, django.contrib.sessions.middleware.SessionMiddleware, django.contrib.auth.middleware.AuthenticationMiddleware, y django.contrib.messages.middleware.MessageMiddleware deben estar incluidos.
Conecta las URL del administrador en tu archivo de configuración de URLs.
Una vez que hayas completado estos pasos, podrás utilizar el sitio administrativo visitando la URL a la que lo hayas conectado (/admin/, por defecto).
Si necesitas crear un usuario para iniciar sesión con él, utiliza el comando createsuperuser. Por defecto, iniciar sesión en el administrador requiere que el usuario tenga la atributo is_staff establecido a True.
Finalmente, determina qué modelos de tu aplicación deben ser editables en la interfaz del administrador. Para cada uno de esos modelos, regístralos con el administrador tal como se describe en ModelAdmin.
Ver también
Para obtener información sobre cómo servir los archivos estáticos (imágenes, JavaScript y CSS) asociados al administrador en producción, consulta Servir archivos.
Tienes problemas? Prueba FAQ: El administrador.
ModelAdmin.¶La clase ModelAdmin es la representación de un modelo en la interfaz administrativa. Normalmente, estos se almacenan en un archivo llamado admin.py en tu aplicación. Vamos a echar un vistazo a un ejemplo de la clase ModelAdmin:
from django.contrib import admin
from myapp.models import Author
class AuthorAdmin(admin.ModelAdmin):
pass
admin.site.register(Author, AuthorAdmin)
¿Necesitas un objeto ModelAdmin en absoluto?
En el ejemplo precedente, la clase ModelAdmin no define ningún valor personalizado (todavía). Como resultado, se proporcionará la interfaz administrativa por defecto. Si estás satisfecho con la interfaz administrativa por defecto, no necesitas definir un objeto ModelAdmin en absoluto – puedes registrar la clase de modelo sin proporcionar una descripción del administrador de modelos. El ejemplo precedente podría simplificarse a:
from django.contrib import admin
from myapp.models import Author
admin.site.register(Author)
register¶También hay un decorador para registrar tus clases ModelAdmin:
from django.contrib import admin
from .models import Author
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
pass
Se le da uno o más clases de modelo para registrar con el administrador de modelos. Si estás utilizando un sitio administrativo personalizado, pasa su valor usando la palabra clave site:
from django.contrib import admin
from .models import Author, Editor, Reader
from myproject.admin_site import custom_admin_site
@admin.register(Author, Reader, Editor, site=custom_admin_site)
class PersonAdmin(admin.ModelAdmin):
pass
No puedes utilizar este decorador si necesitas referenciar tu clase de administrador de modelos en su método __init__(), por ejemplo super(PersonAdmin, self).__init__(*args, **kwargs). Puedes usar super().__init__(*args, **kwargs).
When pones 'django.contrib.admin' en tu configuración de INSTALLED_APPS, Django busca automáticamente un módulo admin en cada aplicación y lo importa.
Esta es la clase por defecto AppConfig para el administrador. Llama a autodiscover() cuando Django arranca.
Esta clase funciona como AdminConfig, excepto que no llama a autodiscover().
Una ruta de importación puntuada al clase por defecto del sitio administrativo o a una función callable que devuelve una instancia de sitio. Por defecto, es 'django.contrib.admin.sites.AdminSite'. Consulta Sobrescribiendo el sitio administrativo predeterminado para su uso.
Esta función intenta importar un módulo admin en cada aplicación instalada. Dichos módulos se esperan que registren modelos con el administrador.
Normalmente no necesitarás llamar a esta función directamente, ya que AdminConfig la llama cuando Django arranca.
Si estás utilizando un sitio administrativo personalizado, es común importar todas las subclases de ModelAdmin en tu código y registrarlas en el sitio administrativo personalizado. En ese caso, para deshabilitar la auto-detección, debes poner 'django.contrib.admin.apps.SimpleAdminConfig' en lugar de 'django.contrib.admin' en tu configuración de INSTALLED_APPS.
ModelAdmin¶El ModelAdmin es muy flexible. Tiene varias opciones para personalizar la interfaz. Todas las opciones están definidas en la subclase de ModelAdmin:
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
date_hierarchy = "pub_date"
Una lista de acciones que se deben hacer disponibles en la página de lista de cambios. Consulta Acciones del administrador para detalles.
Controla dónde en la página aparece la barra de acciones. Por defecto, la lista de cambios del administrador muestra las acciones en la parte superior de la página (actions_on_top = True; actions_on_bottom = False).
Controla si se muestra un contador de selección junto a el menú de acciones. Por defecto, la lista de cambios del administrador lo mostrará (actions_selection_counter = True).
Establece date_hierarchy en el nombre de un campo DateField o DateTimeField de tu modelo, y la página de lista de cambios incluirá una navegación de perforación por fechas basada en ese campo.
Ejemplo:
date_hierarchy = "pub_date"
También puedes especificar un campo en un modelo relacionado utilizando el lookup __, por ejemplo:
date_hierarchy = "author__pub_date"
Esto se llenará inteligentemente con los datos disponibles, por ejemplo, si todas las fechas están en un mismo mes, solo mostrará la perforación a nivel de día.
Nota
date_hierarchy utiliza internamente QuerySet.datetimes(). Por favor, consulta su documentación para algunos consejos cuando se habilita el soporte de zona horaria (:setting:`USE_TZ = True <USE_TZ>).
Esta atributo sobreescribe el valor de visualización por defecto para los campos de los registros que están vacíos (None, cadena vacía, etc.). El valor por defecto es - (un guión). Por ejemplo:
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
empty_value_display = "-empty-"
También puedes sobreescribir empty_value_display para todas las páginas del administrador con AdminSite.empty_value_display, o para campos específicos de esta manera:
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
list_display = ["name", "title", "view_birth_date"]
@admin.display(empty_value="???")
def view_birth_date(self, obj):
return obj.birth_date
Esta atributo, si se proporciona, debe ser una lista de nombres de campos a excluir del formulario.
Por ejemplo, consideremos el siguiente modelo:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
title = models.CharField(max_length=3)
birth_date = models.DateField(blank=True, null=True)
Si deseas un formulario para el modelo Author que incluya solo los campos name y title, especificarías fields o exclude de la siguiente manera:
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
fields = ["name", "title"]
class AuthorAdmin(admin.ModelAdmin):
exclude = ["birth_date"]
Dado que el modelo de Autor solo tiene tres campos, name, title y birth_date, los formularios resultantes de las declaraciones anteriores contendrán exactamente los mismos campos.
Usa la opción fields para realizar cambios en el diseño simple de las formas en las páginas «add» y «change», como mostrar solo un subconjunto de los campos disponibles, modificar su orden o agruparlos en filas. Por ejemplo, podrías definir una versión más sencilla de la forma administrativa del modelo django.contrib.flatpages.models.FlatPage de la siguiente manera:
class FlatPageAdmin(admin.ModelAdmin):
fields = ["url", "title", "content"]
En el ejemplo anterior, solo se mostrarán los campos url, title y content, de forma secuencial, en el formulario. Los campos fields pueden contener valores definidos en ModelAdmin.readonly_fields para ser mostrados como inmodificables.
Para necesidades de diseño más complejas, consulta la opción fieldsets.
La opción fields acepta los mismos tipos de valores que list_display, excepto que no se aceptan llamables y consultas __ para campos relacionados. Los nombres de métodos del modelo y del administrador de modelos solo se utilizarán si están listados en readonly_fields.
Para mostrar varios campos en la misma línea, envuelve esos campos en su propia tupla. En este ejemplo, los campos url y title se mostrarán en la misma línea y el campo content se mostrará debajo de ellos en su propia línea:
class FlatPageAdmin(admin.ModelAdmin):
fields = [("url", "title"), "content"]
Posible confusión con la opción ModelAdmin.fieldsets
Esta opción fields no debe confundirse con la clave del diccionario fields que se encuentra dentro de la opción fieldsets, tal como se describe en la siguiente sección.
Si ninguna de las opciones fields ni fieldsets están presentes, Django utilizará como valor por defecto mostrar cada campo que no sea un AutoField y tenga editable=True, en un único conjunto de campos, en el mismo orden en que los campos se definen en el modelo, seguido de cualquier campo definido en readonly_fields.
Setea fieldsets para controlar la disposición de páginas administrativas «añadir» y «modificar».
fieldsets es una lista de 2-tuplas, en las que cada 2-tupla representa un <fieldset> en la página de formulario administrativa. (Un <fieldset> es una «sección» del formulario.)
Las 2-tuplas están en el formato (nombre, opciones_de_campo), donde nombre es una cadena que representa el título del conjunto de campos y opciones_de_campo es un diccionario de información sobre el conjunto de campos, incluyendo una lista de campos para mostrar en él.
Un ejemplo completo, tomado del modelo django.contrib.flatpages.models.FlatPage:
from django.contrib import admin
class FlatPageAdmin(admin.ModelAdmin):
fieldsets = [
(
None,
{
"fields": ["url", "title", "content", "sites"],
},
),
(
"Advanced options",
{
"classes": ["collapse"],
"fields": ["registration_required", "template_name"],
},
),
]
Esto da como resultado una página administrativa que se ve así:
Si no están presentes ni fieldsets ni las opciones de fields, Django utilizará por defecto mostrar cada campo que no es un AutoField y tiene editable=True, en un único conjunto de campos, en el mismo orden en que los campos se definen en el modelo.
El diccionario field_options puede tener las siguientes claves:
fieldsUna lista o tupla de nombres de campo para mostrar en este conjunto de campos. Esta clave es obligatoria.
Ejemplo:
{
"fields": ["first_name", "last_name", "address", "city", "state"],
}
Al igual que la opción fields, para mostrar varios campos en la misma línea, envuelve esos campos en su propia tupla. En este ejemplo, los campos first_name y last_name se mostrarán en la misma línea:
{
"fields": [("first_name", "last_name"), "address", "city", "state"],
}
Los campos pueden contener valores definidos en readonly_fields para ser mostrados como solo lectura.
Si se agrega el nombre de un callable a los campos, la misma regla aplica que con la opción fields: el callable debe estar listado en readonly_fields.
classesUna lista o tupla conteniendo clases CSS adicionales para aplicar al conjunto de campos. Esto puede incluir cualquier clase CSS personalizada definida en el proyecto, así como cualquier clase CSS proporcionada por Django. Dentro del archivo CSS predeterminado del sitio administrativo, se definen dos clases especialmente útiles: collapse y wide.
Ejemplo:
{
"classes": ["wide", "collapse"],
}
Los conjuntos de campos con estilo wide recibirán espacio horizontal adicional en la interfaz administrativa. Los conjuntos de campos con nombre y estilo collapse se mostrarán inicialmente colapsados, utilizando un widget expandible con una opción para cambiar su visibilidad.
Los conjuntos de campos que utilizan la clase collapse ahora usan elementos <details> y <summary>, siempre y cuando definan un nombre.
descriptionUna cadena de texto opcional adicional para mostrar en la parte superior de cada conjunto de campos, debajo del título del conjunto de campos.
Nota que este valor no se escape a HTML cuando se muestra en la interfaz administrativa. Esto permite incluir HTML si lo deseas. Alternativamente puedes usar texto plano y django.utils.html.escape() para escapar cualquier carácter especial de HTML.
TabularInline tiene limitada soporte para fieldsets
Usando fieldsets con TabularInline tiene limitaciones. Puedes especificar qué campos se mostrarán y su orden dentro del diseño de la interfaz TabularInline definiendo los campos en el diccionario field_options.
Todas las otras características no están soportadas. Esto incluye el uso de name para definir un título para un grupo de campos.
Por defecto, una ManyToManyField se muestra en la página administrativa con un <select multiple>. Sin embargo, las cajas de selección múltiple pueden ser difíciles de usar cuando se seleccionan muchos elementos. Al agregar una ManyToManyField a esta lista, en su lugar se utilizará una interfaz JavaScript «filtro» no intrusiva que permite buscar dentro de las opciones. Las opciones no seleccionadas y seleccionadas aparecen en dos cajas al lado uno del otro. Consulta la filter_vertical para usar una interfaz vertical.
Igual que filter_horizontal, pero utiliza un display vertical de la interfaz de filtro con la caja de opciones no seleccionadas que aparece encima de la caja de opciones seleccionadas.
Por defecto, se crea una ModelForm dinámicamente para tu modelo. Se utiliza para crear el formulario presentado en las páginas de agregar y modificar. Puedes proporcionar fácilmente tu propia ModelForm para superponer cualquier comportamiento del formulario por defecto en las páginas de agregar y modificar. Alternativamente, puedes personalizar el formulario por defecto en lugar de especificar uno completamente nuevo utilizando el método ModelAdmin.get_form().
Para un ejemplo, consulta la sección Agregar validación personalizada al admin.
ModelAdmin.exclude tiene prioridad
Si tu ModelForm y ModelAdmin definen ambos una opción exclude, entonces ModelAdmin tiene prioridad:
from django import forms
from django.contrib import admin
from myapp.models import Person
class PersonForm(forms.ModelForm):
class Meta:
model = Person
exclude = ["name"]
class PersonAdmin(admin.ModelAdmin):
exclude = ["age"]
form = PersonForm
En el ejemplo anterior, el campo «edad» se excluirá pero el campo «nombre» se incluirá en la forma generada.
Esto proporciona una forma rápida y sucia de sobreescribir algunas opciones de los campos Field para su uso en la administración. formfield_overrides es un diccionario que mapea una clase de campo a un diccionario de argumentos para pasar al campo en el momento de su construcción.
Dado que eso es un poco abstracto, vamos a ver un ejemplo concreto. El uso más común de formfield_overrides es agregar un widget personalizado para cierto tipo de campo. Así que imaginemos que hemos escrito una clase RichTextEditorWidget que queremos usar en lugar del widget por defecto <textarea> para campos de texto grandes. Aquí está cómo lo haríamos:
from django.contrib import admin
from django.db import models
# Import our custom widget and our model from where they're defined
from myapp.models import MyModel
from myapp.widgets import RichTextEditorWidget
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.TextField: {"widget": RichTextEditorWidget},
}
Ten en cuenta que la clave en el diccionario es la clase de campo real, no una cadena. El valor es otro diccionario; estos argumentos se pasarán al método __init__() del campo de formulario. Consulta La API de Formularios para obtener más detalles.
Advertencia
Si deseas usar un widget personalizado con un campo relacionado (es decir, ForeignKey o ManyToManyField), asegúrate de que no hayas incluido el nombre del campo en raw_id_fields, radio_fields o autocomplete_fields.
formfield_overrides no te permitirá cambiar el widget en campos relacionados que tengan raw_id_fields, radio_fields o autocomplete_fields configurados. Eso es porque raw_id_fields, radio_fields y autocomplete_fields implican widgets personalizados propios.
Consulta los objetos InlineModelAdmin a continuación, así como la método ModelAdmin.get_formsets_with_inlines().
Establece list_display para controlar qué campos se muestran en la página de lista de cambios de la administración.
Ejemplo:
list_display = ["first_name", "last_name"]
Si no estableces list_display, el sitio de administración mostrará una columna única que muestra la representación __str__() de cada objeto.
Hay cinco tipos de valores que se pueden utilizar en list_display. Todos menos el más simple pueden usar el decorador display(), que se utiliza para personalizar cómo se presenta el campo:
El nombre de un campo del modelo. Por ejemplo:
class PersonAdmin(admin.ModelAdmin):
list_display = ["first_name", "last_name"]
El nombre de un campo relacionado, utilizando la notación __. Por ejemplo:
class PersonAdmin(admin.ModelAdmin):
list_display = ["city__name"]
Una función callable que acepta un argumento, la instancia del modelo. Por ejemplo:
@admin.display(description="Name")
def upper_case_name(obj):
return f"{obj.first_name} {obj.last_name}".upper()
class PersonAdmin(admin.ModelAdmin):
list_display = [upper_case_name]
Una cadena que representa un método ModelAdmin que acepta un argumento, la instancia del modelo. Por ejemplo:
class PersonAdmin(admin.ModelAdmin):
list_display = ["upper_case_name"]
@admin.display(description="Name")
def upper_case_name(self, obj):
return f"{obj.first_name} {obj.last_name}".upper()
Una cadena que representa una atributo o método de modelo (sin ningún argumento requerido). Por ejemplo:
from django.contrib import admin
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=50)
birthday = models.DateField()
@admin.display(description="Birth decade")
def decade_born_in(self):
decade = self.birthday.year // 10 * 10
return f"{decade}’s"
class PersonAdmin(admin.ModelAdmin):
list_display = ["name", "decade_born_in"]
Se agregó soporte para utilizar consultas con __ cuando se dirigen a campos relacionados.
Unos pocos casos especiales sobre los cuales tener en cuenta sobre list_display:
Si el campo es un ForeignKey, Django mostrará la __str__() del objeto relacionado.
Los campos ManyToManyField no están soportados, porque eso implicaría ejecutar una sentencia SQL separada para cada fila en la tabla. Si quieres hacer esto de todos modos, da a tu modelo un método personalizado y agrega el nombre de ese método a list_display. (Ver más abajo sobre métodos personalizados en list_display).
Si el campo es un BooleanField, Django mostrará una icono bonito «sí», «no» o «desconocido» en lugar de True, False o None.
Si la cadena dada es un método del modelo, ModelAdmin o una función callable, Django escapará el HTML por defecto. Para escapar la entrada del usuario y permitir tus propios etiquetas no escapadas, utiliza format_html().
Aquí tienes un ejemplo de modelo completo:
from django.contrib import admin
from django.db import models
from django.utils.html import format_html
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
@admin.display
def colored_name(self):
return format_html(
'<span style="color: #{};">{} {}</span>',
self.color_code,
self.first_name,
self.last_name,
)
class PersonAdmin(admin.ModelAdmin):
list_display = ["first_name", "last_name", "colored_name"]
Como algunos ejemplos ya han demostrado, al utilizar una función callable, un método del modelo o un método ModelAdmin, puedes personalizar el título de la columna envolviendo la función con el decorador display() y pasando el argumento description.
Si el valor de un campo es None, una cadena vacía o un iterable sin elementos, Django mostrará - (un guión). Puedes sobreescribir esto con AdminSite.empty_value_display:
from django.contrib import admin
admin.site.empty_value_display = "(None)"
También puedes utilizar ModelAdmin.empty_value_display:
class PersonAdmin(admin.ModelAdmin):
empty_value_display = "unknown"
O en nivel de campo:
class PersonAdmin(admin.ModelAdmin):
list_display = ["name", "birth_date_view"]
@admin.display(empty_value="unknown")
def birth_date_view(self, obj):
return obj.birth_date
Si la cadena dada es un método del modelo, ModelAdmin o una función callable que devuelve True, False o None, Django mostrará un icono bonito «sí», «no» o «desconocido» si envuelves el método con el decorador display() y pasas el argumento boolean con el valor establecido en True:
from django.contrib import admin
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
birthday = models.DateField()
@admin.display(boolean=True)
def born_in_fifties(self):
return 1950 <= self.birthday.year < 1960
class PersonAdmin(admin.ModelAdmin):
list_display = ["name", "born_in_fifties"]
El método __str__() es tan válido en list_display como cualquier otro método del modelo, por lo que está perfectamente bien hacer esto:
list_display = ["__str__", "some_other_field"]
Normalmente, los elementos de list_display que no son campos de base de datos reales no pueden usarse para ordenar (porque Django hace todo el ordenamiento a nivel de base de datos).
Sin embargo, si un elemento de list_display representa un cierto campo de la base de datos, puedes indicar este hecho utilizando el decorador display() en el método, pasando el argumento ordering:
from django.contrib import admin
from django.db import models
from django.utils.html import format_html
class Person(models.Model):
first_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
@admin.display(ordering="first_name")
def colored_first_name(self):
return format_html(
'<span style="color: #{};">{}</span>',
self.color_code,
self.first_name,
)
class PersonAdmin(admin.ModelAdmin):
list_display = ["first_name", "colored_first_name"]
Lo anterior le dirá a Django que ordene por el campo first_name cuando esté intentando ordenar por colored_first_name en la administración.
Para indicar un orden descendente con el argumento ordering puedes usar una prefijo de guión en el nombre del campo. Utilizando el ejemplo anterior, esto se vería así:
@admin.display(ordering="-first_name")
def colored_first_name(self): ...
El argumento ordering admite consultas de búsqueda para ordenar por valores en modelos relacionados. Este ejemplo incluye una columna «nombre del autor» en la lista de visualización y permite ordenarlo por nombre:
class Blog(models.Model):
title = models.CharField(max_length=255)
author = models.ForeignKey(Person, on_delete=models.CASCADE)
class BlogAdmin(admin.ModelAdmin):
list_display = ["title", "author", "author_first_name"]
@admin.display(ordering="author__first_name")
def author_first_name(self, obj):
return obj.author.first_name
Puedes utilizar expresiones de consulta :doc:` </ref/models/expressions>` con el argumento ordering:
from django.db.models import Value
from django.db.models.functions import Concat
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
@admin.display(ordering=Concat("first_name", Value(" "), "last_name"))
def full_name(self):
return self.first_name + " " + self.last_name
Los elementos de list_display también pueden ser propiedades
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
@property
@admin.display(
ordering="last_name",
description="Full name of the person",
boolean=False,
)
def full_name(self):
return self.first_name + " " + self.last_name
class PersonAdmin(admin.ModelAdmin):
list_display = ["full_name"]
Ten en cuenta que @property debe estar por encima de @display. Si estás utilizando la forma antigua – configurando los atributos relacionados con la visualización directamente en lugar de utilizar el decorador display() – ten en cuenta que se debe usar la función property() y no el decorador @property:
def my_property(self):
return self.first_name + " " + self.last_name
my_property.short_description = "Full name of the person"
my_property.admin_order_field = "last_name"
my_property.boolean = False
full_name = property(my_property)
Los nombres de campo en list_display también aparecerán como clases CSS en el código HTML, en forma de column-<field_name> en cada elemento <th>. Esto se puede utilizar para establecer anchos de columna en un archivo CSS por ejemplo.
Django intentará interpretar cada elemento de list_display en este orden:
Un campo del modelo o desde un campo relacionado.
Un callable.
Una cadena que representa una atributo de ModelAdmin.
Una cadena que representa un atributo del modelo.
Por ejemplo, si tienes first_name como campo del modelo y como atributo de ModelAdmin, se utilizará el campo del modelo.
Utiliza list_display_links para controlar si y qué campos en list_display deben estar vinculados a la página «cambiar» para un objeto.
Por defecto, la página de lista de cambios vinculará la primera columna – el primer campo especificado en list_display – a la página de cambio para cada item. Pero list_display_links te permite cambiar esto:
Establezca a None para obtener ningún enlace.
Establezca a una lista o tupla de campos (en el mismo formato que list_display) cuyas columnas deseas convertir en enlaces.
Puedes especificar uno o muchos campos. A medida que los campos aparezcan en list_display, Django no se preocupa por cuántos (o pocos) campos estén vinculados. La única exigencia es que si deseas utilizar list_display_links de esta manera, debes definir list_display.
En este ejemplo, los campos first_name y last_name se vincularán en la página de lista de cambios:
class PersonAdmin(admin.ModelAdmin):
list_display = ["first_name", "last_name", "birthday"]
list_display_links = ["first_name", "last_name"]
En este ejemplo, la página de lista de cambios tendrá un cuadro con enlaces vacíos:
class AuditEntryAdmin(admin.ModelAdmin):
list_display = ["timestamp", "message"]
list_display_links = None
Establece list_editable a una lista de nombres de campos del modelo que permitirán la edición en la página de lista de cambios. Es decir, los campos listados en list_editable se mostrarán como widgets de formulario en la página de lista de cambios, permitiendo a los usuarios editar y guardar varias filas al mismo tiempo.
Nota
list_editable interactúa con un par de opciones en particular de maneras; debes tener en cuenta las siguientes reglas:
Cualquier campo en list_editable debe estar también en list_display. No puedes editar un campo que no se muestra!
El mismo campo no puede estar listado tanto en list_editable como en list_display_links – un campo no puede ser a la vez un formulario y un enlace.
Obtendrás un error de validación si se rompen alguna de estas reglas.
Establece list_filter para activar los filtros en el lateral derecho de la página de lista de cambios del admin.
De manera simple, list_filter toma una lista o tupla de nombres de campos para activar la filtración, pero se ofrecen varias opciones más avanzadas. Consulta Filtros de lista para ModelAdmin para obtener los detalles.
Establece list_max_show_all para controlar cuántos elementos pueden aparecer en una página de lista de cambios «Mostrar todo» del admin. El admin mostrará un enlace «Mostrar todo» solo si el recuento total de resultados es menor o igual a esta configuración. Por defecto, esto está establecido en 200.
Establece list_per_page para controlar cuántos elementos aparecen en cada página paginada de lista de cambios del admin. Por defecto, esto está establecido en 100.
Set list_select_related para indicarle a Django que utilice la función select_related() al recuperar la lista de objetos en la página de cambio del panel administrativo. Esto puede ahorrar una serie de consultas a la base de datos.
El valor debe ser o un booleano, o una lista o tupla. El valor por defecto es False.
Cuando el valor es True, select_related() se llamará siempre. Cuando el valor está establecido en False, Django mirará a list_display y llamará a select_related() si hay algún ForeignKey presente.
Si necesitas un control más fino, utiliza una tupla (o lista) como valor para list_select_related. Una tupla vacía impedirá que Django llame a select_related en absoluto. Cualquier otra tupla se pasará directamente a select_related como parámetros. Por ejemplo:
class ArticleAdmin(admin.ModelAdmin):
list_select_related = ["author", "category"]
llamará a select_related('author', 'category').
Si necesitas especificar un valor dinámico basado en la solicitud, puedes implementar el método get_list_select_related().
Nota
El panel administrativo ModelAdmin ignora esta atributo cuando select_related() ya se llamó sobre el conjunto de objetos de la página de cambio.
Establece ordering para especificar cómo deben estar ordenadas las listas de objetos en las vistas del panel administrativo Django. Debe ser una lista o tupla en el mismo formato que el parámetro ordering de un modelo.
Si no se proporciona, el panel administrativo Django utilizará la ordenación por defecto del modelo.
Si necesitas especificar un ordenamiento dinámico (por ejemplo dependiendo del usuario o el idioma) puedes implementar el método get_ordering().
Performance considerations with ordering and sorting
Para asegurar un ordenamiento determinista de los resultados, la lista de cambios agrega pk a la ordenación si no puede encontrar un conjunto único o conjunto de campos que proporcionen una ordenación total.
Por ejemplo, si el ordenamiento por defecto es por un campo name no único, entonces la lista de cambios se ordena por name y pk. Esto podría realizar mal si tienes muchas filas y no tienes un índice en name y pk.
La clase del paginador a utilizar para la paginación. Por defecto, se utiliza django.core.paginator.Paginator. Si la clase de paginador personalizada no tiene el mismo interfaz de constructor que django.core.paginator.Paginator, también necesitarás proporcionar una implementación para ModelAdmin.get_paginator().
Establece prepopulated_fields a un diccionario que mapee nombres de campos a los campos que deben prepoblarse desde:
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ["title"]}
Cuando se establezca, los campos dados utilizarán un poco de JavaScript para poblar desde los campos asignados. El uso principal de esta funcionalidad es generar automáticamente el valor para los campos SlugField a partir de uno o más otros campos. El valor generado se produce concatenando los valores de los campos fuentes y luego transformándolo en una cadena válida (por ejemplo, sustituyendo guiones por espacios y minúsculas las letras ASCII).
Los campos prepoblados no se modifican con JavaScript después de que un valor ha sido guardado. Es usualmente indeseable que los slugs cambien (lo que causaría que la URL del objeto cambiara si el slug se utiliza en ella).
prepopulated_fields no acepta campos DateTimeField, ForeignKey, OneToOneField y ManyToManyField.
Por defecto, los filtros aplicados se preservan en la vista de lista después de crear, editar o eliminar un objeto. Puedes tener los filtros eliminados estableciendo esta atributo a False.
Controla si se muestran las cuentas de facetas para los filtros en la lista de cambios del administrador. Por defecto es ShowFacets.ALLOW.
When displayed, facet counts update in line with currently applied filters.
Enum de valores permitidos para ModelAdmin.show_facets.
Siempre mostrar conteos de facetas.
Mostrar conteos de facetas cuando se proporciona el parámetro de consulta _facets.
Nunca mostrar conteos de facetas.
Establecer show_facets en el valor deseado de ShowFacets. Por ejemplo, para siempre mostrar conteos de facetas sin necesidad de proporcionar el parámetro de consulta:
from django.contrib import admin
class MyModelAdmin(admin.ModelAdmin):
...
# Have facets always shown for this model admin.
show_facets = admin.ShowFacets.ALWAYS
Consideraciones sobre rendimiento con facetas
Habilitar filtros de faceta aumentará el número de consultas en la página de cambio de administración en línea con el número de filtros. Estas consultas pueden causar problemas de rendimiento, especialmente para grandes conjuntos de datos. En estos casos puede ser apropiado establecer show_facets en ShowFacets.NEVER para deshabilitar la faceteización por completo.
Por defecto, Django utiliza una interfaz de cuadro desplegable (<select>) para los campos que son ForeignKey o tienen choices establecidos. Si un campo está presente en radio_fields, Django utilizará una interfaz de botones de radio en su lugar. Asumiendo que group es un ForeignKey en el modelo Person:
class PersonAdmin(admin.ModelAdmin):
radio_fields = {"group": admin.VERTICAL}
Tienes la opción de usar HORIZONTAL o VERTICAL desde el módulo django.contrib.admin.
No incluyas un campo en radio_fields a menos que sea un ForeignKey o tenga choices establecido.
La lista autocomplete_fields es una lista de campos ForeignKey y/o ManyToManyField sobre los cuales deseas cambiar a entradas de input de autocompletado Select2 <https://select2.org/>_.
Por defecto, el administrador utiliza una interfaz de caja de selección (<select>) para esos campos. A veces no quieres incurrir en la sobrecarga de seleccionar todas las instancias relacionadas para mostrarlas en el desplegable.
El input Select2 tiene un aspecto similar al input por defecto pero viene con una función de búsqueda que carga las opciones de manera asíncrona. Esto es más rápido y más amigable para los usuarios si el modelo relacionado tiene muchas instancias.
Debes definir search_fields en el objeto ModelAdmin relacionado porque la búsqueda autocompletada utiliza esa información.
Para evitar la divulgación no autorizada de datos, los usuarios deben tener la permiso view o change al objeto relacionado para poder utilizar la función de autocompletado.
La ordenación y paginación de los resultados están controladas por los métodos get_ordering() y get_paginator() del objeto ModelAdmin relacionado.
En el siguiente ejemplo, ChoiceAdmin tiene un campo autocompletado para el ForeignKey a la Question. Los resultados están filtrados por el campo question_text y ordenados por el campo date_created:
class QuestionAdmin(admin.ModelAdmin):
ordering = ["date_created"]
search_fields = ["question_text"]
class ChoiceAdmin(admin.ModelAdmin):
autocomplete_fields = ["question"]
Consideraciones de rendimiento para grandes conjuntos de datos
La ordenación utilizando ModelAdmin.ordering puede causar problemas de rendimiento ya que ordenar en un queryset grande será lento.
También, si tus campos de búsqueda incluyen campos que no están indexados por la base de datos, podrías encontrar rendimiento pobre en tablas extremadamente grandes.
En esos casos, es una buena idea escribir tu propia implementación de ModelAdmin.get_search_results() utilizando una búsqueda con índice de texto completo.
También podrías cambiar el Paginator en tablas muy grandes ya que el paginador por defecto siempre realiza una consulta count(). Por ejemplo, podrías sobrescribir la implementación predeterminada de la propiedad count del Paginator.
Por defecto, Django utiliza un interfaz de select-box (<select>) para campos que son ForeignKey. A veces no quieres incurrir en el overhead de tener que seleccionar todas las instancias relacionadas para mostrar en el menú desplegable.
raw_id_fields es una lista de campos que deseas cambiar a un widget Input para campos ForeignKey o ManyToManyField:
class ArticleAdmin(admin.ModelAdmin):
raw_id_fields = ["newspaper"]
El widget Input de raw_id_fields debe contener una clave primaria si el campo es ForeignKey o una lista separada por comas de valores si el campo es ManyToManyField. El widget raw_id_fields muestra un botón con lupa junto al campo que permite a los usuarios buscar y seleccionar un valor:
Por defecto, la interfaz administrativa muestra todos los campos como editables. Cualquier campo en esta opción (que debe ser una lista o tupla) mostrará sus datos tal cual y no editables; también están excluidos del ModelForm utilizado para crear y editar. Ten en cuenta que cuando se especifica ModelAdmin.fields o ModelAdmin.fieldsets, los campos de solo lectura deben estar presentes para ser mostrados (de lo contrario, son ignorados).
Si readonly_fields se utiliza sin definir un ordenamiento explícito a través de ModelAdmin.fields o ModelAdmin.fieldsets, se agregarán al final después de todos los campos editables.
Un campo de solo lectura no solo puede mostrar datos de un campo del modelo, sino que también puede mostrar el resultado de un método del modelo o un método de la clase ModelAdmin en sí misma. Esto es muy similar a la forma en que ModelAdmin.list_display funciona. Esto proporciona una manera de utilizar la interfaz administrativa para proporcionar retroalimentación sobre el estado de los objetos que se están editando, por ejemplo:
from django.contrib import admin
from django.utils.html import format_html_join
from django.utils.safestring import mark_safe
class PersonAdmin(admin.ModelAdmin):
readonly_fields = ["address_report"]
# description functions like a model field's verbose_name
@admin.display(description="Address")
def address_report(self, instance):
# assuming get_full_address() returns a list of strings
# for each line of the address and you want to separate each
# line by a linebreak
return format_html_join(
mark_safe("<br>"),
"{}",
((line,) for line in instance.get_full_address()),
) or mark_safe("<span class='errors'>I can't determine this address.</span>")
Establece save_as para habilitar una característica «guardar como nuevo» en las formas de cambio del administrador.
Normalmente, los objetos tienen tres opciones de guardado: «Guardar», «Guardar y seguir editando», y «Guardar y agregar otro». Si save_as es True, «Guardar y agregar otro» se reemplazará por un botón «Guardar como nuevo» que crea un nuevo objeto (con una nueva ID) en lugar de actualizar el objeto existente.
Por defecto, save_as está establecido en False.
Cuando se establece :attr:`save_as=True <save_as>, la redirección predeterminada después de guardar el nuevo objeto es a la vista de cambio para ese objeto. Si configuras save_as_continue=False, la redirección será a la vista de listado de cambios.
Por defecto, save_as_continue está establecido en True.
Establece save_on_top para agregar botones de guardar en la parte superior de tus formularios de cambio administrativos.
Normalmente, los botones de guardar aparecen solo en la parte inferior de las formas. Si estableces save_on_top, los botones aparecerán tanto en la parte superior como en la inferior.
Por defecto, save_on_top se establece en False.
Establece search_fields para habilitar una caja de búsqueda en la página de lista de cambios del administrador. Debe establecerse en una lista de nombres de campos que se buscarán cada vez que alguien envíe una consulta de búsqueda en esa caja de texto.
Estos campos deben ser algún tipo de campo de texto, como CharField o TextField. También puedes realizar una búsqueda relacionada en un ForeignKey o ManyToManyField con la notación de consulta «siguiente» del API de búsqueda relacionada:
search_fields = ["foreign_key__related_fieldname"]
Ejemplo: si tienes una entrada de blog con un autor, la siguiente definición permitiría buscar entradas de blog por la dirección de correo electrónico del autor:
search_fields = ["user__email"]
When alguien hace una búsqueda en la caja de búsqueda del administrador, Django divide la consulta de búsqueda en palabras y devuelve todos los objetos que contengan cada una de las palabras, de manera insensible a mayúsculas y minúsculas (utilizando el icontains lookup), donde cada palabra debe estar en al menos uno de search_fields. Por ejemplo, si search_fields está configurado para ['first_name', 'last_name'] y un usuario busca por john lennon, Django hará lo equivalente a esta cláusula SQL WHERE:
WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
La consulta de búsqueda puede contener frases con espacios entre comillas. Por ejemplo, si un usuario busca por "john winston" o 'john winston', Django hará lo equivalente a esta cláusula SQL WHERE:
WHERE (first_name ILIKE '%john winston%' OR last_name ILIKE '%john winston%')
Si no deseas utilizar icontains como lookup, puedes utilizar cualquier otro lookup agregando el campo. Por ejemplo, podrías utilizar exact configurando search_fields para ['first_name__exact'].
Algunos (antiguos) atajos para especificar una búsqueda de campo también están disponibles. Puedes prefijar un campo en search_fields con los siguientes caracteres y es equivalente a agregar __<lookup> al campo:
Prefijo |
Búsqueda |
|---|---|
^ |
|
= |
|
Lo siento, pero no hay texto proporcionado para traducir. Si deseas que traduzca un fragmento de la documentación oficial de inglés a Español de España (Castellano), por favor proporciona el texto en cuestión. Me aseguraré de mantener todas las etiquetas y marcas de código intactas según las reglas establecidas. |
|
None |
Si necesitas personalizar la búsqueda, puedes utilizar ModelAdmin.get_search_results() para proporcionar comportamiento de búsqueda adicional o alternativo.
Establece search_help_text para especificar un texto descriptivo para la caja de búsqueda que se mostrará debajo de ella.
Establece show_full_result_count para controlar si se debe mostrar el recuento completo de objetos en una página administrativa filtrada (por ejemplo, 99 resultados (103 totales)). Si esta opción está configurada como False, se muestra un texto como 99 resultados (Mostrar todos) en su lugar.
La configuración por defecto de show_full_result_count=True genera una consulta para realizar un recuento completo en la tabla, lo que puede ser costoso si la tabla contiene un gran número de filas.
Por defecto, la página de lista de cambios permite ordenar por todos los campos del modelo (y las llamables que utilizan el argumento ordering en el decorador display() o tienen la propiedad admin_order_field) especificados en list_display.
Si deseas deshabilitar el ordenamiento para algunas columnas, establece sortable_by en una colección (por ejemplo, list, tuple o set) de la subconjunto de list_display que quieres que sean ordenables. Una colección vacía deshabilita el ordenamiento para todas las columnas.
Si necesitas especificar esta lista de manera dinámica, implementa el método get_sortable_by() en lugar de eso.
Establece view_on_site para controlar si se muestra o no el enlace «Ver en sitio». Este enlace debería llevar a una URL donde puedas mostrar el objeto guardado.
Este valor puede ser una bandera booleana o un llamable. Si es True (el valor por defecto), se utilizará el método get_absolute_url() del objeto para generar la url.
Si tu modelo tiene un método get_absolute_url() pero no quieres que aparezca el botón «Ver en sitio», solo necesitas establecer view_on_site en False:
from django.contrib import admin
class PersonAdmin(admin.ModelAdmin):
view_on_site = False
En caso de ser un llamable, acepta al objeto del modelo como parámetro. Por ejemplo:
from django.contrib import admin
from django.urls import reverse
class PersonAdmin(admin.ModelAdmin):
def view_on_site(self, obj):
url = reverse("person-detail", kwargs={"slug": obj.slug})
return "https://example.com" + url
La sección Sobreescribir plantillas administrativas describe cómo sobrescribir o extender las plantillas administrativas por defecto. Utiliza las siguientes opciones para sobrescribir las plantillas por defecto utilizadas por las vistas de la clase ModelAdmin:
Ruta a una plantilla personalizada, utilizada por la vista add_view().
Ruta a una plantilla personalizada, utilizada por la vista change_view().
Ruta a una plantilla personalizada, utilizada por la vista changelist_view().
Path a una plantilla personalizada, utilizado por la función delete_view() para mostrar una página de confirmación al eliminar uno o varios objetos.
Ruta a una plantilla personalizada, utilizada por el método delete_selected de acción para mostrar una página de confirmación al eliminar uno o varios objetos. Consulte la documentación sobre acciones.
Path a una plantilla personalizada, utilizado por history_view().
Path a una plantilla personalizada, utilizada por las funciones response_add(), response_change() y response_delete().
ModelAdmin¶Advertencia
Al sobreescribir las funciones ModelAdmin.save_model() y ModelAdmin.delete_model(), su código debe guardar/eliminar el objeto. No están destinados a fines de veto, sino que permiten realizar operaciones adicionales.
La función save_model se le pasa un objeto HttpRequest, una instancia del modelo, una instancia de ModelForm y un valor booleano basado en si se está agregando o cambiando el objeto. Sobrescribiendo esta función permite realizar operaciones pre- o post-guardado. Llame a super().save_model() para guardar el objeto utilizando Model.save().
Por ejemplo, para adjuntar request.user al objeto antes de guardar:
from django.contrib import admin
class ArticleAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.user = request.user
super().save_model(request, obj, form, change)
La función delete_model se le pasa un objeto HttpRequest y una instancia del modelo. Sobrescribiendo esta función permite realizar operaciones pre- o post-borrado. Llame a super().delete_model() para borrar el objeto utilizando Model.delete().
La función delete_queryset() se le pasa un objeto HttpRequest y una colección de objetos QuerySet a eliminar. Sobrescriba esta función para personalizar el proceso de eliminación para la acción «eliminar objetos seleccionados» acción.
El save_formset método se le da el HttpRequest, la instancia de formulario padre ModelForm y un valor booleano basado en si está agregando o cambiando el objeto padre.
Por ejemplo, para adjuntar request.user a cada modelo de instancia del conjunto de formularios modificado:
class ArticleAdmin(admin.ModelAdmin):
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for obj in formset.deleted_objects:
obj.delete()
for instance in instances:
instance.user = request.user
instance.save()
formset.save_m2m()
Vea también Guardar objetos en el conjunto de formularios.
Advertencia
Todas las trampas que devuelven una propiedad ModelAdmin devuelven la propiedad misma en lugar de una copia de su valor. Modificar dinámicamente el valor puede dar como resultado resultados sorprendentes.
Vamos a tomar ModelAdmin.get_readonly_fields() como ejemplo:
class PersonAdmin(admin.ModelAdmin):
readonly_fields = ["name"]
def get_readonly_fields(self, request, obj=None):
readonly = super().get_readonly_fields(request, obj)
if not request.user.is_superuser:
readonly.append("age") # Edits the class attribute.
return readonly
Esto resulta en readonly_fields se convierte en ["name", "age", "age", ...], incluso para un superusuario, ya que "age" se agrega cada vez que un no superusuario visita la página.
El método get_ordering toma como parámetro una solicitud y se espera que devuelva una lista o tupla para ordenar similar a la ordering atributo. Por ejemplo:
class PersonAdmin(admin.ModelAdmin):
def get_ordering(self, request):
if request.user.is_superuser:
return ["name", "rank"]
else:
return ["name"]
El método get_search_results modifica la lista de objetos mostrados en aquellos que coinciden con el término de búsqueda proporcionado. Acepta la solicitud, un conjunto de consultas que aplica los filtros actuales y el término de búsqueda proporcionado por el usuario. Devuelve una tupla conteniendo un conjunto de consultas modificado para implementar la búsqueda, y un booleano indicando si los resultados pueden contener duplicados.
La implementación predeterminada busca en los campos nombrados en ModelAdmin.search_fields.
Esta método puede ser sobrescrito con su propio método de búsqueda personalizado. Por ejemplo, podría desear buscar por un campo entero o utilizar una herramienta externa como Solr o Haystack. Debe establecer si el conjunto de consultas modificado implementado por su método de búsqueda puede introducir duplicados en los resultados y devolver True en la segunda parte del valor de retorno.
Los textos traducidos son:
class PersonAdmin(admin.ModelAdmin):
list_display = ["name", "age"]
search_fields = ["name"]
def get_search_results(self, request, queryset, search_term):
queryset, may_have_duplicates = super().get_search_results(
request,
queryset,
search_term,
)
try:
search_term_as_int = int(search_term)
except ValueError:
pass
else:
queryset |= self.model.objects.filter(age=search_term_as_int)
return queryset, may_have_duplicates
Esta implementación es más eficiente que search_fields = ('name', '=age') lo que resulta en una comparación de cadena para el campo numérico, por ejemplo ... OR UPPER("polls_choice"."votes"::text) = UPPER('4') en PostgreSQL.
El método save_related se le da el HttpRequest, la instancia del formulario padre ModelForm, la lista de formularios inline y un valor booleano basado en si el padre está siendo agregado o modificado. Aquí puedes hacer cualquier operación pre- o post-guardar para objetos relacionados con el padre. Ten en cuenta que en este punto el objeto padre y su formulario ya han sido guardados.
El método get_autocomplete_fields() se le da el HttpRequest y se espera que devuelva una lista o tupla de nombres de campos que se mostrarán con un widget de autocompletar tal como se describe en la sección ModelAdmin.autocomplete_fields.
El método get_readonly_fields se le da el HttpRequest y el objeto obj que está siendo editado (o None en un formulario de agregación) y se espera que devuelva una lista o tupla de nombres de campos que se mostrarán como solo lectura, tal como se describe en la sección ModelAdmin.readonly_fields.
El método get_prepopulated_fields se le da el HttpRequest y el objeto obj que está siendo editado (o None en un formulario de agregación) y se espera que devuelva un diccionario, tal como se describe en la sección ModelAdmin.prepopulated_fields.
El método get_list_display se le da el HttpRequest y se espera que devuelva una lista o tupla de nombres de campos que se mostrarán en la vista de listado tal como se describe en la sección ModelAdmin.list_display.
El método get_list_display_links se le da el HttpRequest y la lista o tupla devuelta por ModelAdmin.get_list_display(). Se espera que devuelva None o una lista o tupla de nombres de campos en la vista de listado que se vincularán a la vista de cambio, tal como se describe en la sección ModelAdmin.list_display_links.
El método get_exclude se le da el HttpRequest y el objeto obj que está siendo editado (o None en un formulario de agregación) y se espera que devuelva una lista de campos, tal como se describe en ModelAdmin.exclude.
El método get_fields se le da el HttpRequest y el objeto obj que está siendo editado (o None en un formulario de agregación) y se espera que devuelva una lista de campos, tal como se describe en la sección ModelAdmin.fields.
El get_fieldsets método se le da el HttpRequest y el obj que está siendo editado (o None en un formulario de agregar) y se espera que devuelva una lista de 2-tuplas, en la cual cada 2-tupla representa un <fieldset> en la página del formulario administrativo, tal como se describe arriba en la sección ModelAdmin.fieldsets.
El método get_list_filter se le da el HttpRequest y se espera que devuelva el mismo tipo de secuencia que para el atributo list_filter.
El método get_list_select_related se le da el HttpRequest y debe devolver un booleano o lista como hace ModelAdmin.list_select_related.
El método get_search_fields se le da el HttpRequest y se espera que devuelva el mismo tipo de secuencia que para el atributo search_fields.
El método get_sortable_by() se pasa el HttpRequest y se espera que devuelva una colección (por ejemplo, list, tuple o set) de nombres de campos que serán ordenables en la página de lista de cambios.
Su implementación por defecto devuelve sortable_by si está configurado, de lo contrario se reenvía a get_list_display().
Por ejemplo, para evitar que uno o más columnas sean ordenables:
class PersonAdmin(admin.ModelAdmin):
def get_sortable_by(self, request):
return {*self.get_list_display(request)} - {"rank"}
El método get_inline_instances se le da el HttpRequest y el obj que está siendo editado (o None en un formulario de agregar) y se espera que devuelva una lista o tupla de objetos InlineModelAdmin, tal como se describe abajo en la sección InlineModelAdmin. Por ejemplo, el siguiente devolvería inlines sin la filtración por defecto basada en permisos de agregar, cambiar, eliminar y ver:
class MyModelAdmin(admin.ModelAdmin):
inlines = [MyInline]
def get_inline_instances(self, request, obj=None):
return [inline(self.model, self.admin_site) for inline in self.inlines]
Si sobreescribes este método, asegúrate de que los inlines devueltos sean instancias de las clases definidas en inlines o podrías encontrar un error «Bad Request» cuando se agregan objetos relacionados.
El método get_inlines se le da el HttpRequest y el obj que está siendo editado (o None en un formulario de agregar) y se espera que devuelva una iteración de inlines. Puedes sobreescribir este método para agregar inlines dinámicamente basados en la solicitud o instancia del modelo en lugar de especificarlos en ModelAdmin.inlines.
La traducción de los textos es la siguiente:
from django.contrib import admin
from django.template.response import TemplateResponse
from django.urls import path
class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super().get_urls()
my_urls = [path("my_view/", self.admin_site.admin_view(self.my_view))]
return my_urls + urls
def my_view(self, request):
# ...
context = dict(
# Include common variables for rendering the admin template.
self.admin_site.each_context(request),
# Anything else you want in the context...
key=value,
)
return TemplateResponse(request, "sometemplate.html", context)
Si deseas usar la plantilla del administrador, extiende de admin/base_site.html:
{% extends "admin/base_site.html" %}
{% block content %}
...
{% endblock %}
Nota
Fíjate cómo la función self.my_view está envuelta en self.admin_site.admin_view. Esto es importante, ya que asegura dos cosas:
Se ejecutan las comprobaciones de permiso, asegurando que solo los usuarios del personal activo puedan acceder a la vista.
Se aplica el decorador django.views.decorators.cache.never_cache() para evitar la caché, asegurando que la información devuelta esté actualizada.
Nota
Fíjate en que los patrones personalizados se incluyen antes de las URLs del administrador regulares: los patrones de URL del administrador son muy permissivos y coincidirán con casi cualquier cosa, por lo que suele ser mejor anexar tus URLs personalizadas a las de ellos.
En este ejemplo, my_view se accederá en /admin/myapp/mymodel/my_view/ (asumiendo que las URL del administrador están incluidas en /admin/.)
Si la página es cachable, pero todavía deseas que se realice la comprobación de permiso, puedes pasar el argumento cacheable=True a AdminSite.admin_view():
path("my_view/", self.admin_site.admin_view(self.my_view, cacheable=True))
Las vistas del administrador ModelAdmin tienen atributos model_admin. Las otras vistas del sitio administrador tienen atributos admin_site.
Devuelve una clase ModelForm para su uso en las vistas de agregar y cambiar en el administrador, véase add_view() y change_view().
La implementación base utiliza modelform_factory() para heredar de form, modificado por atributos como fields y exclude. Por lo tanto, por ejemplo, si deseaba ofrecer campos adicionales a los superusuarios, podría sustituir una forma base diferente de la siguiente manera:
class MyModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser:
kwargs["form"] = MySuperuserForm
return super().get_form(request, obj, **kwargs)
También puedes devolver directamente una clase personalizada ModelForm.
Yields (FormSet, InlineModelAdmin) pares para su uso en vistas de administración de agregar y cambiar.
Por ejemplo, si deseaba mostrar un inline particular solo en la vista de cambio, podría sobrescribir get_formsets_with_inlines de la siguiente manera:
class MyModelAdmin(admin.ModelAdmin):
inlines = [MyInline, SomeOtherInline]
def get_formsets_with_inlines(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# hide MyInline in the add view
if not isinstance(inline, MyInline) or obj is not None:
yield inline.get_formset(request, obj), inline
El método formfield_for_foreignkey en una ModelAdmin permite sobrescribir el campo formulario por defecto para un campo clave foráneo. Por ejemplo, para devolver un subconjunto de objetos para este campo clave foráneo basado en el usuario:
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "car":
kwargs["queryset"] = Car.objects.filter(owner=request.user)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
Esto utiliza la instancia HttpRequest para filtrar el campo clave foráneo Car para mostrar solo los coches propiedad del instante User.
Para filtros más complejos, puedes utilizar el método ModelForm.__init__() para filtrar basado en un instance de tu modelo (ver Campos que manejan relaciones). Por ejemplo:
class CountryAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["capital"].queryset = self.instance.cities.all()
class CountryAdmin(admin.ModelAdmin):
form = CountryAdminForm
Como el método formfield_for_foreignkey, el método formfield_for_manytomany se puede sobrescribir para cambiar el campo formulario por defecto para un campo muchos a muchos. Por ejemplo, si un propietario puede poseer múltiples coches y los coches pueden pertenecer a múltiples propietarios – una relación muchos a muchos – podrías filtrar el campo clave foráneo Car para mostrar solo los coches propiedad del instante User:
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "cars":
kwargs["queryset"] = Car.objects.filter(owner=request.user)
return super().formfield_for_manytomany(db_field, request, **kwargs)
Como los métodos formfield_for_foreignkey y formfield_for_manytomany, el método formfield_for_choice_field se puede sobrescribir para cambiar el campo formulario por defecto para un campo que tenga declaradas opciones. Por ejemplo, si las opciones disponibles a un superusuario deben ser diferentes de las disponibles a los empleados regulares, podrías proceder de la siguiente manera:
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_choice_field(self, db_field, request, **kwargs):
if db_field.name == "status":
kwargs["choices"] = [
("accepted", "Accepted"),
("denied", "Denied"),
]
if request.user.is_superuser:
kwargs["choices"].append(("ready", "Ready for deployment"))
return super().formfield_for_choice_field(db_field, request, **kwargs)
Limitaciones de choices
Cualquier atributo choices establecido en el campo del formulario se limitará solo al campo del formulario. Si el campo correspondiente en el modelo tiene opciones establecidas, las opciones proporcionadas al formulario deben ser un subconjunto válido de esas opciones, de lo contrario la solicitud del formulario fallará con una ValidationError cuando el modelo mismo se valide antes de guardar.
Regresa la clase Changelist para utilizar en listados. Por defecto se utiliza django.contrib.admin.views.main.ChangeList. Al heredar esta clase puedes cambiar el comportamiento del listado.
Devuelve una clase de tipo ModelForm para su uso en el Formset de la página de listado. Para utilizar un formulario personalizado, por ejemplo:
from django import forms
class MyForm(forms.ModelForm):
pass
class MyModelAdmin(admin.ModelAdmin):
def get_changelist_form(self, request, **kwargs):
return MyForm
Devuelve una clase de conjunto de formularios ModelFormSet para su uso en la página de cambio si se utiliza list_editable. Para usar un formulario personalizado, por ejemplo:
from django.forms import BaseModelFormSet
class MyAdminFormSet(BaseModelFormSet):
pass
class MyModelAdmin(admin.ModelAdmin):
def get_changelist_formset(self, request, **kwargs):
kwargs["formset"] = MyAdminFormSet
return super().get_changelist_formset(request, **kwargs)
Los objetos en la página de cambios pueden ser filtrados con consultas desde la cadena de consulta del URL. Esto es cómo funciona list_filter, por ejemplo. Las consultas son similares a las utilizadas en QuerySet.filter() (por ejemplo, user__email=user@example.com). Dado que las consultas en la cadena de consulta pueden ser manipuladas por el usuario, deben ser sanitizadas para prevenir la exposición no autorizada de datos.
La traducción es:
Por defecto, lookup_allowed() permite el acceso a los campos locales de un modelo, a las rutas de campo utilizadas en list_filter (pero no las rutas desde get_list_filter()), y consultas necesarias para que limit_choices_to funcione correctamente en raw_id_fields.
Sobreescribe este método para personalizar las consultas permitidas para tu subclase de ModelAdmin.
Debería devolver True si se permite la visualización de obj, False en caso contrario. Si obj es None, debería devolver True o False para indicar si se permite la visualización de objetos de este tipo en general (por ejemplo, False se interpretará como que el usuario actual no está permitido para ver ningún objeto de este tipo).
La traducción de los textos es la siguiente:
Debería devolver True si se permite agregar un objeto, False en caso contrario.
Debería devolver True si se permite editar obj, False en caso contrario. Si obj es None, debería devolver True o False para indicar si se permite el edición de objetos de este tipo en general (por ejemplo, False se interpretará como que el usuario actual no está permitido editar ningún objeto de este tipo).
Debería devolver True si se permite eliminar obj, False en caso contrario. Si obj es None, debería devolver True o False para indicar si se permite eliminar objetos de este tipo en general (por ejemplo, False se interpretará como que el usuario actual no está permitido eliminar ningún objeto de este tipo).
Debería devolver True si se permite mostrar el módulo en la página de índice del administrador y acceder a la página de índice del módulo, False en caso contrario. Utiliza por defecto User.has_module_perms(). Sustituirlo no restringe el acceso a las vistas de visualización, agregar, cambiar o eliminar: has_view_permission(), has_add_permission(), has_change_permission() y has_delete_permission() deberían usarse para eso.
El método get_queryset en un ModelAdmin devuelve una QuerySet de todos los instancias del modelo que se pueden editar en el sitio administrativo. Un uso común para sobreescribir este método es mostrar objetos propiedad del usuario conectado:
class MyModelAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(author=request.user)
Envía un mensaje al usuario utilizando la django.contrib.messages backend. Consulte el ejemplo de ModelAdmin personalizado.
Los argumentos de palabra clave permiten cambiar el nivel de mensaje, agregar etiquetas CSS adicionales o fallar silenciosamente si no se ha instalado la contrib.messages framework. Estos argumentos de palabra clave coinciden con los de django.contrib.messages.add_message(), consulte la documentación de esa función para obtener más detalles. Una diferencia es que el nivel puede pasar como una etiqueta de cadena en lugar de un entero/constante.
Devuelve una instancia del paginador a utilizar para esta vista. Por defecto, instancia una instancia de paginator.
Determina la HttpResponse para la etapa de la vista add_view.
Se han traducido los textos de la siguiente manera:
Determina la HttpResponse para la etapa change_view().
response_change se llama después de que el formulario administrativo se ha enviado y justo después de que el objeto y todas las instancias relacionadas se han guardado. Puedes sobrescribirlo para cambiar el comportamiento por defecto después de que el objeto se haya cambiado.
Determina la HttpResponse para la etapa delete_view().
response_delete se llama después de que el objeto se ha eliminado. Puedes sobrescribirlo para cambiar el comportamiento por defecto después de que el objeto se haya eliminado.
obj_display es una cadena con el nombre del objeto eliminado.
obj_id es la identificador serializado utilizado para recuperar el objeto a eliminar.
Un hook para personalizar los argumentos de palabra clave pasados al constructor de un conjunto de formularios. Por ejemplo, para pasar request a las formas del conjunto de formularios:
class MyModelAdmin(admin.ModelAdmin):
def get_formset_kwargs(self, request, obj, inline, prefix):
return {
**super().get_formset_kwargs(request, obj, inline, prefix),
"form_kwargs": {"request": request},
}
También puedes utilizarlo para establecer initial para las formas del conjunto de formularios.
Un hook para los datos iniciales en los formularios administrativos de cambio. Por defecto, los campos se dan valores iniciales desde los parámetros GET. Por ejemplo, ?name=valor_inicial establecerá el valor inicial del campo name a ser valor_inicial.
Este método debería devolver un diccionario en la forma {'fieldname': 'fieldval'}.
def get_changeform_initial_data(self, request):
return {"name": "custom_initial_value"}
Un hook para personalizar el proceso de eliminación del delete_view() y la acción «eliminar seleccionado» (acción).
El argumento objs es un iterable homogéneo de objetos (un QuerySet o una lista de instancias del modelo) que se van a eliminar, y request es el HttpRequest.
Este método debe devolver una tupla de 4 elementos de (deleted_objects, model_count, perms_needed, protected).
deleted_objects es una lista de cadenas que representan todos los objetos que se eliminarán. Si existen objetos relacionados que deben eliminarse, la lista está anidada e incluye esos objetos relacionados. La lista se formatea en el template utilizando el filtro unordered_list.
model_count es un diccionario que mapea cada modelo a la cantidad de objetos que se eliminarán, donde la clave es el nombre plural del modelo (verbose_name_plural).
perms_needed es un conjunto de verbose_names de los modelos que el usuario no tiene permiso para eliminar.
protected es una lista de cadenas que representan todos los objetos relacionados protegidos que no pueden ser eliminados. La lista se muestra en el template.
Vista Django para la página de adición de instancia del modelo. Consulta la nota a continuación.
Django vista para la página de edición del modelo instancia. Consulta el nota debajo.
Vista Django para la lista de cambios y acciones de las instancias del modelo. Consulta el nota debajo.
Vista Django para la confirmación de eliminación de la(s) instancia(s) del modelo. Consulta el nota debajo.
Vista Django para la página que muestra la historia de modificaciones para una instancia del modelo determinada.
A diferencia de los métodos ModelAdmin tipo ganchos detallados en la sección anterior, estos cinco métodos están diseñados realmente para ser invocados como vistas Django desde el administrador de aplicaciones URL desencadenante para renderizar las páginas que tratan con operaciones CRUD de instancias del modelo. Como resultado, sobreescribir completamente estos métodos cambiará significativamente el comportamiento de la aplicación administrativa.
Una razón común para sobreescribir estos métodos es aumentar los datos de contexto proporcionados al template que renderiza la vista. En el ejemplo siguiente, se sobreescribe la vista de cambio para que el template renderizado reciba algunos datos de mapeo adicionales que no estarían disponibles de otra manera:
class MyModelAdmin(admin.ModelAdmin):
# A template for a very customized change view:
change_form_template = "admin/myapp/extras/openstreetmap_change_form.html"
def get_osm_info(self):
# ...
pass
def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context["osm_data"] = self.get_osm_info()
return super().change_view(
request,
object_id,
form_url,
extra_context=extra_context,
)
Estas vistas devuelven instancias de TemplateResponse que permiten personalizar fácilmente los datos de respuesta antes de la renderización. Para más detalles, consulta la documentación de TemplateResponse.
ModelAdmin¶Hay veces en las que querrías agregar un poco de CSS y/o JavaScript a las vistas de agregado/cambio. Esto se puede lograr utilizando una clase interna Media en tu ModelAdmin:
class ArticleAdmin(admin.ModelAdmin):
class Media:
css = {
"all": ["my_styles.css"],
}
js = ["my_code.js"]
La aplicación staticfiles agrega el valor de STATIC_URL (o MEDIA_URL si STATIC_URL es None) a cualquier ruta de activos. Las mismas reglas se aplican como las definiciones de activos regulares en formularios <form-asset-paths>.
Django admin JavaScript utiliza la biblioteca jQuery.
Para evitar conflictos con scripts o bibliotecas proporcionados por el usuario, Django’s jQuery (versión 3.7.1) se nombra como django.jQuery. Si deseas utilizar jQuery en tu propio JavaScript de admin sin incluir una copia adicional, puedes usar el objeto django.jQuery en las vistas de cambio y edición. Además, tus propios formularios o widgets que dependen de django.jQuery deben especificar js=['admin/js/jquery.init.js', …] cuando declares los activos de medios como una definición estática.
La clase ModelAdmin requiere jQuery por defecto, por lo que no es necesario agregar jQuery a la lista de recursos de medios de tu ModelAdmin a menos que tengas una necesidad específica. Por ejemplo, si requieres la biblioteca jQuery en el espacio de nombres global (por ejemplo, cuando se utilizan plugins jQuery de terceros) o si necesitas una versión más reciente de jQuery, debes incluir tu propia copia.
Django proporciona tanto versiones no comprimidas como “minificadas” de jQuery, como jquery.js y jquery.min.js respectivamente.
ModelAdmin y InlineModelAdmin tienen una propiedad media que devuelve una lista de objetos Media que almacenan rutas a los archivos JavaScript para los formularios y/o conjuntos de formularios. Si DEBUG es True devolverá las versiones no comprimidas de los varios archivos JavaScript, incluyendo jquery.js; si no, devolverá las “minificadas”.
También puedes agregar una validación personalizada de datos en el admin. La interfaz administrativa automática reutiliza django.forms, y la clase ModelAdmin te da la capacidad de definir tu propio formulario:
class ArticleAdmin(admin.ModelAdmin):
form = MyArticleAdminForm
MyArticleAdminForm se puede definir en cualquier lugar siempre que lo importes donde sea necesario. Ahora dentro de tu formulario puedes agregar una validación personalizada para cualquier campo:
class MyArticleAdminForm(forms.ModelForm):
def clean_name(self):
# do something that validates your data
return self.cleaned_data["name"]
Es importante que utilices un ModelForm aquí, de lo contrario las cosas pueden romperse. Consulta la documentación sobre formularios y, más específicamente, la documentación sobre validación de formularios para obtener más información.
La interfaz administrativa tiene la capacidad de editar modelos en la misma página que un modelo padre. Estos se llaman inlines. Supongamos que tienes estos dos modelos:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
Puedes editar los libros escritos por un autor en la página del autor. Agregas inlines a un modelo especificando ellos en una ModelAdmin.inlines:
from django.contrib import admin
from myapp.models import Author, Book
class BookInline(admin.TabularInline):
model = Book
class AuthorAdmin(admin.ModelAdmin):
inlines = [
BookInline,
]
admin.site.register(Author, AuthorAdmin)
Django proporciona dos subclases de InlineModelAdmin y son:
La diferencia entre estos dos es meramente el template utilizado para renderizarlos.
InlineModelAdmin comparte muchas de las mismas características que ModelAdmin, y agrega algunas propias (las características compartidas se definen en realidad en la superclase BaseModelAdmin). Las características compartidas son:
La clase InlineModelAdmin agrega o personaliza:
El modelo que se está utilizando en la inline. Esto es obligatorio.
El nombre de la clave foránea del modelo. En la mayoría de los casos, esto se tratará automáticamente, pero fk_name debe especificarse explícitamente si hay más de una clave foránea al mismo modelo padre.
Esto se ajusta por defecto a BaseInlineFormSet. Utilizar tu propio conjunto de formularios puede darte muchas posibilidades de personalización. Los inlinos están construidos alrededor de conjuntos de formularios de modelo.
El valor por defecto para form es ModelForm. Esto es lo que se pasa a través de a inlineformset_factory() cuando se crea el conjunto de formularios para este inline.
Advertencia
Cuando se escribe validación personalizada para formularios InlineModelAdmin, ten cuidado al escribir validaciones que dependan de características del modelo padre. Si el modelo padre falla en la validación, puede quedar en un estado inconsistente tal como se describe en la advertencia en Validación de un ModelForm.
Una lista o tupla que contiene clases CSS adicionales para aplicar al fieldset que se renderiza para los inline. Por defecto, es None. Al igual que las clases configuradas en fieldsets, los inlines con una clase collapse se expandirán inicialmente utilizando un widget expansible.
Los conjuntos de campos que utilizan la clase collapse ahora usan elementos <details> y <summary>, siempre y cuando definan un nombre.
Controla el número de formularios adicionales que se mostrarán en el conjunto de formularios, además de los formularios iniciales. Por defecto es 3. Consulte la documentación del conjunto de formularios para obtener más información.
Para los usuarios con navegadores que tienen JavaScript habilitado, se proporciona un enlace «Agregar otro» para poder agregar cualquier número de inlines adicionales además de aquellos proporcionados como resultado del extra argumento.
El enlace dinámico no aparecerá si el número de formularios actualmente mostrados supera max_num, o si el usuario no tiene JavaScript habilitado.
InlineModelAdmin.get_extra() también permite personalizar el número de formularios adicionales.
Esto controla el número máximo de formularios que se muestran en la línea. Esto no se correlaciona directamente con el número de objetos, pero puede hacerlo si el valor es pequeño suficiente. Consulte Limitar el número de objetos editables para obtener más información.
InlineModelAdmin.get_max_num() también permite personalizar el número máximo de formularios adicionales.
Este es el texto traducido:
InlineModelAdmin.get_min_num() también permite personalizar el número mínimo de formularios mostrados.
Por defecto, Django utiliza un interfaz de select-box (<select>) para campos que son ForeignKey. A veces no quieres incurrir en el overhead de tener que seleccionar todas las instancias relacionadas para mostrar en el menú desplegable.
raw_id_fields es una lista de campos que deseas cambiar a un widget Input para campos ForeignKey o ManyToManyField:
class BookInline(admin.TabularInline):
model = Book
raw_id_fields = ["pages"]
El template utilizado para renderizar la línea en la página.
Una sobrescritura del verbose_name desde la clase Meta interna del modelo.
Una sobrescritura del verbose_name_plural desde la clase Meta interna del modelo. Si no se proporciona y el atributo InlineModelAdmin.verbose_name está definido, Django utilizará InlineModelAdmin.verbose_name + 's'.
Indica si los objetos en línea pueden ser eliminados en la línea. Por defecto es True.
Indica si los objetos en línea que se pueden cambiar en el administrador tienen un enlace a la forma de cambio. Por defecto es False.
Devuelve una clase BaseInlineFormSet para su uso en vistas de agregar/cambiar del administrador. obj es el objeto padre que se está editando o None cuando se agrega un nuevo padre. Consulte el ejemplo de ModelAdmin.get_formsets_with_inlines.
Devuelve el número de formularios en línea adicionales a utilizar. Por defecto, devuelve el atributo InlineModelAdmin.extra.
Sobrescriba este método para determinar programáticamente el número de formularios en línea adicionales. Por ejemplo, esto puede estar basado en la instancia del modelo (pasada como argumento de palabra clave obj):
class BinaryTreeAdmin(admin.TabularInline):
model = BinaryTree
def get_extra(self, request, obj=None, **kwargs):
extra = 2
if obj:
return extra - obj.binarytree_set.count()
return extra
Returns the maximum number of extra inline forms to use. By defecto, devuelve el atributo InlineModelAdmin.max_num.
Sobreescribe este método para determinar de forma programática el número máximo de formas en línea. Por ejemplo, esto puede estar basado en la instancia del modelo (pasada como argumento de palabra clave obj):
class BinaryTreeAdmin(admin.TabularInline):
model = BinaryTree
def get_max_num(self, request, obj=None, **kwargs):
max_num = 10
if obj and obj.parent:
return max_num - 5
return max_num
Returns the minimum number of inline forms to use. By defecto, devuelve el atributo InlineModelAdmin.min_num.
Sobreescribe este método para determinar de forma programática el número mínimo de formas en línea. Por ejemplo, esto puede estar basado en la instancia del modelo (pasada como argumento de palabra clave obj).
Debería devolver True si se permite agregar un objeto en línea, False en caso contrario. obj es el objeto padre que se está editando o None cuando se agrega un nuevo padre.
Debería devolver True si se permite editar un objeto en línea, False en caso contrario. obj es el objeto padre que se está editando.
Debería devolver True si se permite eliminar un objeto en línea, False en caso contrario. obj es el objeto padre que se está editando.
Nota
El argumento obj pasado a los métodos de InlineModelAdmin es el objeto padre que se está editando o None cuando se agrega un nuevo padre.
A veces es posible tener más de una clave foránea al mismo modelo. Por ejemplo, este modelo:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Friendship(models.Model):
to_person = models.ForeignKey(
Person, on_delete=models.CASCADE, related_name="friends"
)
from_person = models.ForeignKey(
Person, on_delete=models.CASCADE, related_name="from_friends"
)
Si deseas mostrar un inline en las páginas de administración de agregado/cambio para el modelo Person debes definir explícitamente la clave foránea ya que no es capaz de hacerlo automáticamente:
from django.contrib import admin
from myapp.models import Friendship, Person
class FriendshipInline(admin.TabularInline):
model = Friendship
fk_name = "to_person"
class PersonAdmin(admin.ModelAdmin):
inlines = [
FriendshipInline,
]
admin.site.register(Person, PersonAdmin)
Por defecto, los widgets de administración para relaciones muchos-a-muchos se mostrarán en el modelo que contiene la referencia real a la ManyToManyField. Dependiendo de tu definición ModelAdmin, cada campo muchos-a-muchos en tu modelo se representará mediante un estándar HTML <select multiple>, un filtro horizontal o vertical, o un widget raw_id_fields. Sin embargo, también es posible reemplazar estos widgets con inlines.
Supongamos que tenemos los siguientes modelos:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, related_name="groups")
Si deseas mostrar relaciones muchos-a-muchos utilizando un inline, puedes hacerlo definiendo un objeto InlineModelAdmin para la relación:
from django.contrib import admin
from myapp.models import Group
class MembershipInline(admin.TabularInline):
model = Group.members.through
class GroupAdmin(admin.ModelAdmin):
inlines = [
MembershipInline,
]
exclude = ["members"]
admin.site.register(Group, GroupAdmin)
Hay dos características dignas de nota en este ejemplo.
Primero - la clase MembershipInline referencia Group.members.through. La propiedad through es una referencia al modelo que gestiona la relación muchos-a-muchos. Este modelo se crea automáticamente por Django cuando defines un campo muchos-a-muchos.
En segundo lugar, el administrador de Group debe excluir manualmente el campo members. Django muestra un widget de administración para un campo muchos-a-muchos en el modelo que define la relación (en este caso, Group). Si deseas utilizar un modelo inline para representar la relación muchos-a-muchos, debes decirle a Django que no muestre este widget - de lo contrario, terminarás con dos widgets en tu página de administración para gestionar la relación.
Ten en cuenta que cuando se utiliza esta técnica, los señales m2m_changed no se disparan. Esto es porque desde el punto de vista del administrador, through es solo un modelo con dos campos foráneos en lugar de una relación muchos-a-muchos.
En todos los demás aspectos, el InlineModelAdmin es exactamente lo mismo que cualquier otro. Puedes personalizar la apariencia utilizando cualquiera de las propiedades normales ``ModelAdmin””.
Cuando especificas un modelo intermedio utilizando el argumento through de una ManyToManyField, el administrador no mostrará por defecto un widget. Esto es porque cada instancia del modelo intermedio requiere más información de la que podría ser mostrada en un solo widget, y el diseño requerido para múltiples widgets variará dependiendo del modelo intermedio.
Sin embargo, todavía queremos poder editar esa información inline. Afortunadamente, podemos hacer esto con modelos admin inline. Supongamos que tenemos los siguientes modelos:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through="Membership")
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["person", "group"], name="unique_person_group"
)
]
El primer paso en mostrar este modelo intermedio en el administrador es definir una clase inline para el modelo Membership:
class MembershipInline(admin.TabularInline):
model = Membership
extra = 1
Este ejemplo utiliza los valores por defecto de InlineModelAdmin para el modelo Membership, y limita las formas adicionales a uno. Esto podría ser personalizado utilizando cualquier de las opciones disponibles para las clases InlineModelAdmin.
Ahora crea vistas admin para los modelos Person y Group:
class PersonAdmin(admin.ModelAdmin):
inlines = [MembershipInline]
class GroupAdmin(admin.ModelAdmin):
inlines = [MembershipInline]
Finalmente, registra tus modelos Person y Group con el sitio administrador:
admin.site.register(Person, PersonAdmin)
admin.site.register(Group, GroupAdmin)
Ahora tu sitio administrador está configurado para editar objetos Membership inline desde las páginas de detalles de Person o Group.
Es posible utilizar una inline con objetos relacionados de manera genérica. Digamos que tienes los siguientes modelos:
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
class Image(models.Model):
image = models.ImageField(upload_to="images")
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
class Product(models.Model):
name = models.CharField(max_length=100)
Si deseas permitir la edición y la creación de una instancia de Image en el Product, agrega o modifica vistas que puedes utilizar GenericTabularInline o GenericStackedInline (ambos subclases de GenericInlineModelAdmin) proporcionados por admin. Implementan diseños visuales tabulares y estacados para las formas que representan los objetos inline, respectivamente, exactamente como sus contrapartes no genéricas. Comportan exactamente igual que cualquier otro inline. En tu admin.py para este ejemplo de aplicación:
from django.contrib import admin
from django.contrib.contenttypes.admin import GenericTabularInline
from myapp.models import Image, Product
class ImageInline(GenericTabularInline):
model = Image
class ProductAdmin(admin.ModelAdmin):
inlines = [
ImageInline,
]
admin.site.register(Product, ProductAdmin)
Consulte la documentación de contenttypes para obtener información más específica.
Puedes sobrescribir muchas de las plantillas que el módulo admin utiliza para generar las diversas páginas de un sitio admin. Incluso puedes sobrescribir algunas de estas plantillas para una aplicación específica o un modelo específico.
Los archivos de plantilla administrativa se encuentran en el django/contrib/admin/templates/admin directorio.
Para sobrescribir una o más de ellas, crea primero un directorio admin en el directorio templates de tu proyecto. Puede ser cualquiera de los directorios que especificaste en la opción DIRS del backend DjangoTemplates en la configuración TEMPLATES. Si has personalizado la opción 'loaders', asegúrate de que 'django.template.loaders.filesystem.Loader' aparezca antes de 'django.template.loaders.app_directories.Loader' para que tus plantillas personalizadas sean encontradas por el sistema de carga de plantillas antes de las incluidas con django.contrib.admin.
Dentro de este directorio admin, crea subdirectorios con nombres que correspondan a tu aplicación. Dentro de estos subdirectorios de la aplicación, crea subdirectorios con nombres que correspondan a tus modelos. Ten en cuenta que el módulo admin convertirá el nombre del modelo a minúsculas al buscar el directorio, así que asegúrate de nombrar el directorio en minúsculas si vas a ejecutar tu aplicación en un sistema de archivos sensible a mayúsculas y minúsculas.
Para sobrescribir una plantilla administrativa para una aplicación específica, copia y edita la plantilla del django/contrib/admin/templates/admin directorio, y guárdala en uno de los directorios que acabas de crear.
Por ejemplo, si queremos agregar una herramienta a la vista de lista de cambios para todos los modelos de una aplicación llamada my_app, copiaríamos contrib/admin/templates/admin/change_list.html al directorio templates/admin/my_app/ de nuestro proyecto y realizaríamos cualquier cambio necesario.
Si queremos agregar una herramienta a la vista de lista de cambios para un modelo específico llamado “Página”, copiaríamos el mismo archivo a la carpeta templates/admin/my_app/page de nuestro proyecto.
Debido al diseño modular de las plantillas administrativas, es usualmente ni necesario ni recomendable reemplazar una plantilla completa. Es casi siempre mejor sobrescribir solo la sección de la plantilla que necesitas cambiar.
Para continuar con el ejemplo anterior, queremos agregar un nuevo enlace junto al Historial herramienta para el modelo Página''. Después de revisar ``change_form.html determinamos que solo necesitamos sobrescribir el bloque object-tools-items. Por lo tanto, aquí está nuestra nueva change_form.html :
{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}
{% block object-tools-items %}
<li>
<a href="{% url opts|admin_urlname:'history' original.pk|admin_urlquote %}" class="historylink">{% translate "History" %}</a>
</li>
<li>
<a href="mylink/" class="historylink">My Link</a>
</li>
{% if has_absolute_url %}
<li>
<a href="{% url 'admin:view_on_site' content_type_id original.pk %}" class="viewsitelink">{% translate "View on site" %}</a>
</li>
{% endif %}
{% endblock %}
¡Eso es todo! Si colocáramos este archivo en la carpeta templates/admin/my_app, nuestro enlace aparecería en la forma de cambio para todos los modelos dentro de my_app.
No todas las plantillas en contrib/admin/templates/admin pueden ser sobrescritas por aplicación o por modelo. Las siguientes sí pueden:
actions.html
app_index.html
change_form.html
change_form_object_tools.html
change_list.html
change_list_object_tools.html
change_list_results.html
date_hierarchy.html
delete_confirmation.html
object_history.html
pagination.html
popup_response.html
prepopulated_fields_js.html
search_form.html
formulario_de_búsqueda.html
Para aquellos templates que no pueden sobrescribirse de esta manera, todavía puedes sobrescribirlos para tu proyecto completo colocando la nueva versión en tu directorio templates/admin. Esto es particularmente útil para crear páginas personalizadas 404 y 500.
Nota
Algunos de los templates del administrador, como change_list_results.html, se utilizan para renderizar etiquetas de inclusión personalizadas. Estas pueden sobrescribirse, pero en tales casos probablemente serías mejor crear tu propia versión de la etiqueta en cuestión y darle un nombre diferente. De esta manera puedes utilizarla selectivamente.
Si deseas cambiar los templates de índice, inicio de sesión o cierre de sesión, es mejor crear tu propia instancia de AdminSite (ver más abajo) y cambiar las propiedades AdminSite.index_template , AdminSite.login_template o AdminSite.logout_template.
El administrador utiliza variables CSS para definir colores y fuentes. Esto permite cambiar temas sin tener que sobrescribir muchas reglas CSS individuales. Por ejemplo, si preferías el púrpura en lugar del azul podrías agregar una sobrescritura de admin/base.html a tu proyecto:
{% extends 'admin/base.html' %}
{% block extrastyle %}{{ block.super }}
<style>
html[data-theme="light"], :root {
--primary: #9774d5;
--secondary: #785cab;
--link-fg: #7c449b;
--link-selected-fg: #8f5bb2;
}
</style>
{% endblock %}
La lista de variables CSS se define en django/contrib/admin/static/admin/css/base.css.
Las variables de modo oscuro, respetando la consulta de medios prefers-color-scheme, están definidas en django/contrib/admin/static/admin/css/dark_mode.css. Esto está vinculado al documento en {% block dark-mode-vars %}.
extrabody block¶Puedes agregar contenido HTML personalizado, JavaScript u otros elementos que aparezcan justo antes del cierre </body> de las plantillas que extiendan admin/base.html extendiendo el bloque extrabody. Por ejemplo, si deseas mostrar un aviso al cargar la página puedes agregar una sobrescritura de la plantilla admin/base.html en tu proyecto:
{% extends 'admin/base.html' %}
{% block extrabody %}
{{ block.super }}
<script>
document.addEventListener('DOMContentLoaded', function() {
window.alert('Welcome!');
});
</script>
{% endblock extrabody %}
AdminSite objects¶Una instancia de sitio administrativo de Django está representada por una instancia de django.contrib.admin.sites.AdminSite; por defecto, se crea una instancia de esta clase como django.contrib.admin.site y puedes registrar tus modelos y instancias de ModelAdmin con ella.
Si deseas personalizar el sitio administrativo predeterminado, puedes sobrescribirlo.
Al construir una instancia de un sitio administrativo AdminSite, puedes proporcionar un nombre de instancia único utilizando la argumento name en el constructor. Este nombre de instancia se utiliza para identificar la instancia, especialmente cuando se invocan las URL del sitio administrativo. Si no se proporciona ningún nombre de instancia, se utilizará como nombre predeterminado admin. Consulta Personalizando la clase AdminSite para un ejemplo de personalización de la clase AdminSite.
Un conjunto débil ``WeakSet contiene todas las instancias de sitios administrativos.
AdminSite attributes¶Las plantillas pueden sobrescribir o extender los templates base del sitio administrativo según se describe en Sobreescribir plantillas administrativas.
El texto que poner en la parte superior de cada página del sitio administrativo, como un <div> (una cadena). Por defecto, esto es «Django administration».
El texto para poner al final de cada página administrativa <title> (una cadena). Por defecto, esto es «Django site admin».
La URL para el enlace «Ver sitio» en la parte superior de cada página administrativa. Por defecto, site_url es /. Establezca a None para eliminar el enlace.
Para sitios que corren en una subruta, el método each_context() verifica si la solicitud actual tiene request.META['SCRIPT_NAME'] configurado y utiliza ese valor si site_url no está configurado a algo diferente de /.
El texto para poner en la parte superior de la página administrativa principal (una cadena). Por defecto, esto es «Administración del sitio».
Ruta a un plantilla personalizada que se utilizará por la vista principal de índice del sitio administrativo.
Ruta a una plantilla personalizada que se utilizará por la vista de índice de aplicación del sitio administrativo.
La cadena para mostrar valores vacíos en la lista de cambios del sitio administrativo. Por defecto, es un guión. El valor también puede sobrescribirse en una base por ModelAdmin y en un campo personalizado dentro de un ModelAdmin estableciendo un atributo empty_value_display en el campo. Consulte ModelAdmin.empty_value_display para ejemplos.
Un valor booleano que determina si mostrar la barra lateral de navegación en pantallas más grandes. Por defecto, está configurado a True.
Un valor booleano que determina si agregar una vista final de captura general para el sitio administrativo que redirige usuarios no autenticados a la página de inicio de sesión. Por defecto, está configurado a True.
Advertencia
No se recomienda establecer esto en False ya que la vista protege contra un posible problema de privacidad de enumeración de modelos.
Ruta a un plantilla personalizada que se utilizará en la vista de inicio de sesión del sitio administrativo.
Clase heredada de AuthenticationForm que se utilizará en la vista de inicio del sitio administrativo.
Ruta a un plantilla personalizada que se utilizará por la vista de cierre de sesión del sitio administrativo.
Ruta a un plantilla personalizada que se utilizará en la vista de cambio de contraseña del sitio administrativo.
Ruta a un plantilla personalizada que se utilizará en la vista de cambio de contraseña del sitio administrativo.
AdminSite¶Devuelve un diccionario de variables para incluir en el contexto del template para cada página del sitio administrativo.
Incluye las siguientes variables y valores por defecto:
site_header: AdminSite.site_header
site_title: AdminSite.site_title
site_url: AdminSite.site_url
has_permission: AdminSite.has_permission()
available_apps: una lista de aplicaciones del registro de aplicaciones <ref/applications/> disponibles para el usuario actual. Cada entrada en la lista es un diccionario que representa a la aplicación con las siguientes claves:
app_label: la etiqueta de la aplicación
app_url: la URL del índice de la aplicación en la administración
has_module_perms: un booleano que indica si se permite mostrar y acceder a la página de índice del módulo para el usuario actual
models: una lista de los modelos disponibles en la aplicación
Cada modelo es un diccionario con las siguientes claves:
model: la clase del modelo
object_name: nombre de clase del modelo
nombre: nombre plural del modelo
perms: un dict que rastrea permisos de add, change, delete, y view
admin_url: URL de la lista de cambios administrativa para el modelo
add_url: URL administrativa para agregar una nueva instancia del modelo
is_popup: si la página actual se muestra en una ventana emergente
is_nav_sidebar_enabled: AdminSite.enable_nav_sidebar
log_entries: AdminSite.get_log_entries()
Devuelve una lista de aplicaciones del registro de aplicaciones <ref/applications/> disponible para el usuario actual. Puedes pasar opcionalmente un argumento app_label para obtener detalles para una sola app. Cada entrada en la lista es un diccionario que representa una aplicación con las siguientes claves:
app_label: la etiqueta de la aplicación
app_url: la URL del índice de la aplicación en la administración
has_module_perms: un booleano que indica si se permite mostrar y acceder a la página de índice del módulo para el usuario actual
models: una lista de los modelos disponibles en la aplicación
nombre: nombre de la aplicación
Cada modelo es un diccionario con las siguientes claves:
model: la clase del modelo
object_name: nombre de clase del modelo
nombre: nombre plural del modelo
perms: un dict que rastrea permisos de add, change, delete, y view
admin_url: URL de la lista de cambios administrativa para el modelo
add_url: URL administrativa para agregar una nueva instancia del modelo
Los textos traducidos son:
Devuelve True si el usuario para la solicitud dada HttpRequest tiene permiso para ver al menos una página en el sitio administrativo. Por defecto, requiere que tanto User.is_active como User.is_staff sean True.
Registra la clase de modelo dada (o iterable de clases) con la clase administrativa dada. La clase administrativa por defecto es ModelAdmin (las opciones administrativas predeterminadas). Si se dan argumentos clave – por ejemplo list_display – se aplicarán como opciones a la clase administrativa.
Lanza ImproperlyConfigured si el modelo es abstracto y django.contrib.admin.exceptions.AlreadyRegistered si un modelo ya está registrado.
Desregistra la clase de modelo dada (o iterable de clases).
Lanza django.contrib.admin.exceptions.NotRegistered si un modelo no está registrado.
AdminSite a tu URLconf¶El último paso para configurar el administrador Django es conectar tu instancia de AdminSite a tu URLconf. Haz esto apuntando una URL dada al método AdminSite.urls. No es necesario utilizar include().
In this example, we register the default AdminSite instance
django.contrib.admin.site at the URL /admin/
# urls.py
from django.contrib import admin
from django.urls import path
urlpatterns = [
path("admin/", admin.site.urls),
]
AdminSite¶Si deseas configurar tu propio sitio administrativo con comportamiento personalizado, estás libre de sobreescribir o agregar cualquier cosa que desees. Luego, crea una instancia de tu subclase AdminSite (de la misma manera en que instancias cualquier otra clase de Python) y registra tus modelos y subclases ModelAdmin con ella en lugar del sitio predeterminado. Finalmente, actualiza myproject/urls.py para referenciar a tu subclase AdminSite.
myapp/admin.py¶from django.contrib import admin
from .models import MyModel
class MyAdminSite(admin.AdminSite):
site_header = "Monty Python administration"
admin_site = MyAdminSite(name="myadmin")
admin_site.register(MyModel)
myproject/urls.py¶from django.urls import path
from myapp.admin import admin_site
urlpatterns = [
path("myadmin/", admin_site.urls),
]
Ten en cuenta que no deseas la autodiscovery de módulos admin cuando utilizas tu propio sitio administrativo, ya que probablemente estarás importando todos los módulos admin por aplicación en tu módulo myproject.admin. Esto significa que debes poner 'django.contrib.admin.apps.SimpleAdminConfig' en lugar de 'django.contrib.admin' en la configuración INSTALLED_APPS.
Puedes sobreescribir el sitio administrativo predeterminado django.contrib.admin.site estableciendo la atributo default_site de una configuración personalizada AppConfig al camino de importación a punto con o un callable que devuelve una instancia del sitio.
myproject/admin.py¶from django.contrib import admin
class MyAdminSite(admin.AdminSite): ...
myproject/apps.py¶from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = "myproject.admin.MyAdminSite"
myproject/settings.py¶INSTALLED_APPS = [
# ...
"myproject.apps.MyAdminConfig", # replaces 'django.contrib.admin'
# ...
]
Puedes crear múltiples instancias del sitio de administración en el mismo sitio web que utiliza Django. Crea múltiples instancias de AdminSite y coloca cada una en una dirección URL diferente.
En este ejemplo, las direcciones URL /basic-admin/ y /advanced-admin/ presentan versiones separadas del sitio de administración – utilizando las instancias de AdminSite myproject.admin.basic_site y myproject.admin.advanced_site, respectivamente:
# urls.py
from django.urls import path
from myproject.admin import advanced_site, basic_site
urlpatterns = [
path("basic-admin/", basic_site.urls),
path("advanced-admin/", advanced_site.urls),
]
Las instancias de AdminSite reciben un solo argumento en su constructor, su nombre, que puede ser cualquier cosa que desees. Este argumento se convierte en el prefijo para los nombres de URL con fines de reversarlos. Esto es necesario solo si estás utilizando más de una AdminSite.
Al igual que ModelAdmin, AdminSite proporciona un método get_urls() que se puede sobrescribir para definir vistas adicionales para el sitio. Para agregar una nueva vista a tu sitio de administración, extiende la base get_urls() método para incluir un patrón para tu nueva vista.
Nota
Cualquier vista que renderice los templates de administración o extienda el template de administración base debe establecer request.current_app antes de renderizar el template. Debe ser establecido a self.name si tu vista está en un AdminSite o self.admin_site.name si tu vista está en un ModelAdmin.
Puedes agregar una característica de restablecimiento de contraseña al sitio de administración agregando unas pocas líneas a tu URLconf. Específicamente, agrega estos cuatro patrones:
from django.contrib import admin
from django.contrib.auth import views as auth_views
path(
"admin/password_reset/",
auth_views.PasswordResetView.as_view(
extra_context={"site_header": admin.site.site_header}
),
name="admin_password_reset",
),
path(
"admin/password_reset/done/",
auth_views.PasswordResetDoneView.as_view(
extra_context={"site_header": admin.site.site_header}
),
name="password_reset_done",
),
path(
"reset/<uidb64>/<token>/",
auth_views.PasswordResetConfirmView.as_view(
extra_context={"site_header": admin.site.site_header}
),
name="password_reset_confirm",
),
path(
"reset/done/",
auth_views.PasswordResetCompleteView.as_view(
extra_context={"site_header": admin.site.site_header}
),
name="password_reset_complete",
),
Este asume que has agregado el administrador en admin/ y requiere que pongas las URLS que comienzan con ^admin/ antes de la línea que incluye la aplicación del administrador misma.
La presencia de la URL denominada admin_password_reset provocará que aparezca un enlace «¿Has olvidado tu contraseña?» en la página de inicio del administrador por defecto debajo de la caja de texto de contraseña.
La clase LogEntry registra las adiciones, cambios y eliminaciones de objetos realizadas a través de la interfaz administrativa.
LogEntry¶La fecha y la hora del acción.
El usuario (una instancia de AUTH_USER_MODEL) que realizó la acción.
El tipo de contenido (ContentType) del objeto modificado.
La representación textual de la clave primaria del objeto modificado.
El objeto repr() después de la modificación.
El tipo de acción registrada: ADICIÓN, CAMBIO, ELIMINACIÓN.
Por ejemplo, para obtener una lista de todas las adiciones realizadas a través del panel administrativo:
from django.contrib.admin.models import ADDITION, LogEntry
LogEntry.objects.filter(action_flag=ADDITION)
La descripción detallada de la modificación. En el caso de una edición, por ejemplo, el mensaje contiene una lista de los campos editados. El sitio administrativo de Django formatea este contenido como una estructura JSON, para que get_change_message() pueda recomponer un mensaje traducido en el idioma actual del usuario. Es posible que el código personalizado establezca esto como una cadena simple aunque se le aconseja utilizar el método get_change_message() para recuperar este valor en lugar de accederlo directamente.
LogEntry métodos¶Formatea y traduce change_message al idioma actual del usuario. Los mensajes creados antes de Django 1.10 siempre se mostrarán en el idioma en el que fueron registrados.
Cuando un sitio administrativo AdminSite está desplegado, las vistas proporcionadas por ese sitio están accesibles utilizando el sistema de reversión de URL de Django:ref:URL <naming-url-patterns>.
El sitio administrativo AdminSite proporciona los siguientes patrones de URL nombrados:
Página |
Nombre de URL |
Parámetros |
|---|---|---|
Índice |
index |
|
Iniciar sesión |
login |
|
Cerrar sesión |
logout |
|
Cambio de contraseña |
password_change |
|
Cambiar contraseña realizada. |
cambiar_contraseña_realizada |
|
i18n JavaScript |
jsi18n |
|
Página de índice de la aplicación |
app_list |
app_label |
Redireccionar a la página del objeto |
view_on_site |
content_type_id, object_id |
Cada instancia de ModelAdmin proporciona un conjunto adicional de URLs nombradas:
Página |
Nombre de URL |
Parámetros |
|---|---|---|
Changelist |
|
|
Add |
|
|
History |
|
|
Delete |
|
|
Cambiar |
{{ app_label }}_{{ model_name }}_change |
|
La UserAdmin proporciona una URL nombrada:
Página |
Nombre de URL |
Parámetros |
|---|---|---|
Cambio de contraseña |
auth_user_password_change |
user_id |
Estas URLs nombradas se registran con el espacio de nombres de la aplicación admin, y con un espacio de nombres de instancia correspondiente al nombre del sitio.
Entonces, si deseabas obtener una referencia a la vista de cambio para un objeto Choice particular (de la aplicación polls) en el administrador por defecto, llamarías:
>>> from django.urls import reverse
>>> c = Choice.objects.get(...)
>>> change_url = reverse("admin:polls_choice_change", args=(c.id,))
Esto encontrará la primera instancia registrada de la aplicación del administrador (cualquiera sea el nombre de la instancia), y se resolverá a la vista para cambiar instancias poll.Choice en esa instancia.
Si deseas encontrar una URL en una instancia administrativa específica, proporciona el nombre de esa instancia como una pista current_app al llamado inverso. Por ejemplo, si específicamente querías la vista del administrador desde la instancia administrativa nombrada custom, necesitarías llamar:
>>> change_url = reverse("admin:polls_choice_change", args=(c.id,), current_app="custom")
Para más detalles, consulta la documentación sobre reversar URLs con espacio de nombres.
To permit una reversión más fácil de las URLs del administrador en plantillas, Django proporciona un filtro admin_urlname que toma como argumento una acción:
{% load admin_urls %}
<a href="{% url opts|admin_urlname:'add' %}">Add user</a>
<a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this user</a>
La acción en los ejemplos anteriores coincide con la última parte de los nombres de URL para instancias de ModelAdmin descritas anteriormente. La variable opts puede ser cualquier objeto que tenga atributos app_label y model_name y se proporciona normalmente por las vistas del administrador para el modelo actual.
display¶Este decorador se puede utilizar para establecer atributos específicos en funciones de visualización personalizadas que se pueden usar con list_display o readonly_fields:
@admin.display(
boolean=True,
ordering="-publish_date",
description="Is Published?",
)
def is_published(self, obj):
return obj.publish_date is not None
Esta es equivalente a establecer algunas atributos (con los nombres originales y más largos) directamente en la función:
def is_published(self, obj):
return obj.publish_date is not None
is_published.boolean = True
is_published.admin_order_field = "-publish_date"
is_published.short_description = "Is Published?"
También tenga en cuenta que el parámetro del decorador empty_value se mapea al atributo empty_value_display asignado directamente a la función. No se puede utilizar conjuntamente con boolean – son mutuamente excluyentes.
El uso de este decorador no es obligatorio para hacer una función de visualización, pero puede ser útil usarlo sin argumentos como un marcador en su código fuente para identificar el propósito de la función:
@admin.display
def published_year(self, obj):
return obj.publish_date.year
En este caso, no agregará atributos a la función.
staff_member_required¶Este decorador se utiliza en las vistas del administrador que requieren autorización. Una vista decorada con esta función tendrá el siguiente comportamiento:
Si el usuario está conectado, es un miembro del personal (User.is_staff=True) y está activo (User.is_active=True), se ejecutará la vista normalmente.
De lo contrario, la solicitud será redirigida a la URL especificada por el parámetro login_url, con el camino originalmente solicitado en una variable de cadena de consulta especificada por redirect_field_name. Por ejemplo: /admin/login/?next=/admin/polls/question/3/.
Ejemplo de uso:
from django.contrib.admin.views.decorators import staff_member_required
@staff_member_required
def my_view(request): ...
may 31, 2026