tutorial theme template superusuario password makemigrations create crear python django django-admin

python - theme - ¿Cómo usar la clase AdminSite personalizada?



django makemigrations (3)

¿Cuál es la mejor manera de implementar mi propio django.contrib.admin.sites.AdminSite ?

En realidad me sale un problema con el registro de INSTALLED_APPS en django.contrib.admin.autodiscover . Si uso mi clase personalizada de AdminSite en urls.py , no se mostraron aplicaciones en la página de administración.

He arreglado esto con un pequeño truco. Escribí esta clase:

from django.contrib.admin.sites import site as default_site class AdminSiteRegistryFix( object ): '''''' This fix links the ''_registry'' property to the orginal AdminSites ''_registry'' property. This is necessary, because of the character of the admins ''autodiscover'' function. Otherwise the admin site will say, that you havn''t permission to edit anything. '''''' def _registry_getter(self): return default_site._registry def _registry_setter(self,value): default_site._registry = value _registry = property(_registry_getter, _registry_setter)

E implementa mi AdminSite personalizado de esta manera:

from wltrweb.hacks.django.admin import AdminSiteRegistryFix from django.contrib.admin import AdminSite class MyAdminSite( AdminSite, AdminSiteRegistryFix ): # do some magic pass site = MyAdminSite()

Así que puedo usar este site para urls.py

¿Alguien sabe de una manera mejor? Desde que accedo a una var, comenzando con un guión bajo, no es más que un hack. No me gustan los hacks

Edición: Otra forma sería reescribir la función django.contrib.admin.autodiscover , pero en este caso tendría un código redundante.


El problema

Usar una clase personalizada derivada de django.contrib.admin.AdminSite para el sitio de administración de un proyecto, sin tener que escribir un código de registro personalizado para registrar modelos con la nueva clase. Cuando uso aplicaciones de terceros con sus propios modelos, prefiero no tener que editar el código de registro personalizado solo porque los modelos se agregaron o eliminaron de estas aplicaciones.

La solución

django.contrib.admin cambiar la instancia creada con la clase predeterminada utilizada para el sitio de administración a su propia instancia, creada con su propia clase antes de django.contrib.admin la función de autodiscover django.contrib.admin . Hago esto por:

  1. Tener una aplicación que realice el cambio. (Utilizo mi aplicación específica del proyecto llamada core para mis propios propósitos).

  2. Dos opciones:

    1. Django 1.6 a 1.9: use __init__ de la aplicación para realizar el cambio. En Django 1.8, recibirá una advertencia de desaprobación debido al cambio en Django 1.9 citado a continuación. Tenga en cuenta que este método también funcionará con 1.9 porque los módulos de Django cargados por el código que se muestra a continuación se han modificado en 1.9 para que ya no carguen modelos. Cuando uso este método, mi archivo core/__init__.py contiene:

      from django.contrib import admin from django.contrib.admin import sites class MyAdminSite(admin.AdminSite): pass mysite = MyAdminSite() admin.site = mysite sites.site = mysite

    2. Django 1.9 y superior: use la configuración de la aplicación de la aplicación para realizar el cambio. A partir de Django 1.9, como indican las notas de la versión :

      Todos los modelos deben definirse dentro de una aplicación instalada o declarar una app_label explícita. Además, no es posible importarlos antes de que se cargue su aplicación. En particular, no es posible importar modelos dentro del paquete raíz de una aplicación.

      Prefiero limitar las importaciones que hago en el nivel raíz para evitar el riesgo de cargar modelos. Si bien a partir de la versión 1.9, el método __init__ anterior funcionará , no se sabe si 1.10 o una versión posterior introducirá un cambio que causará problemas.

      Cuando uso este método, el core/__init__.py establece default_app_config = "core.apps.DefaultAppConfig" y tengo un core/apps.py como este:

      from django.apps import AppConfig class DefaultAppConfig(AppConfig): name = ''core'' def ready(self): from django.contrib import admin from django.contrib.admin import sites class MyAdminSite(admin.AdminSite): pass mysite = MyAdminSite() admin.site = mysite sites.site = mysite

      Si bien es posible usar este método con las versiones 1.7 y 1.8, es un poco arriesgado usarlo con esas versiones. Vea las notas a continuación.

  3. Colocar esta aplicación antes que django.contrib.admin en la lista INSTALLED_APPS . (Esto es absolutamente necesario para 1.7 y versiones posteriores. En versiones anteriores de Django, podría funcionar bien incluso si la aplicación es posterior a django.contrib.admin . Sin embargo, consulte las notas a continuación).

Notas y advertencias

  • La aplicación que realiza el cambio debería ser la primera en la lista de INSTALLED_APPS para minimizar la posibilidad de que otra cosa tome el valor del site de django.contrib.admin antes de que se django.contrib.admin el cambio. Si otra aplicación logra obtener ese valor antes de que se haga el cambio, esa otra aplicación tendrá una referencia al sitio anterior. Seguramente se producirá la hilaridad.

  • El método anterior no funcionará bien si dos aplicaciones intentan instalar su propia nueva clase de sitio de administración predeterminada. Esto tendría que manejarse caso por caso.

  • Es posible que una futura versión de Django pueda romper este método.

  • Para la versión anterior a 1.9, preferí usar __init__ para cambiar de sitio usando la configuración de la aplicación porque la documentación sobre la inicialización indica que el método ready() de las configuraciones de la aplicación se llama relativamente tarde. Entre el momento en que se carga el módulo de una aplicación y se llama el tiempo ready() , se han cargado los modelos, y en algunos casos, podría significar que un módulo ha tomado el valor del site de django.contrib.admin antes de que se llame ready . Para minimizar el riesgo, tengo el código __init__ la aplicación para hacer el cambio.

    Creo que el riesgo que existía en la versión 1.7 y 1.8 y que evité al usar __init__ para realizar el cambio de sitio lo antes posible no existe en 1.9. Todos tienen prohibido cargar módulos antes de que se carguen todas las aplicaciones. Por lo tanto, hacer el cambio en la devolución de llamada de la primera aplicación que aparece en INSTALLED_APPS debería ser seguro. Actualicé un proyecto grande a 1.9 y utilicé el método de configuración de la aplicación, sin ningún problema.


Cotización desde https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#customizing-the-adminsite-class

Sin embargo, si desea configurar su propio sitio administrativo con comportamiento personalizado, puede subclasificar AdminSite y anular o agregar lo que desee. Luego, simplemente cree una instancia de su subclase AdminSite (de la misma manera que crearía una instancia de cualquier otra clase de Python), y registre sus modelos y subclases ModelAdmin en lugar de usar la predeterminada .

Supongo que ese es el enfoque más explícito, pero también significa que necesita cambiar el código de registro en los archivos admin.py de sus aplicaciones.

Realmente no hay necesidad de usar la detección automática cuando use su propia instancia AdminSite ya que probablemente importará todos los módulos admin.py por aplicación en su módulo myproject.admin.

El supuesto parece ser que, una vez que comience a escribir su sitio de administración personalizado, se volverá más o menos específico del proyecto y sabrá de antemano qué aplicaciones desea incluir.

Entonces, si no quieres trabajar con el truco anterior, solo veo estas dos opciones. Reemplace todas las llamadas de registro a su sitio de administración personalizado o registre los modelos explícitamente en su módulo de administración.


Desde Django 2.1, hay una solución "lista para https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#overriding-the-default-admin-site ": https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#overriding-the-default-admin-site

from django.contrib import admin class MyAdminSite(admin.AdminSite): ...

El intercambio del sitio de administración personalizado ahora se realiza agregando su propio AdminConfig a las aplicaciones instaladas.

from django.contrib.admin.apps import AdminConfig class MyAdminConfig(AdminConfig): default_site = ''myproject.admin.MyAdminSite''


INSTALLED_APPS = [ ... ''myproject.apps.MyAdminConfig'', # replaces ''django.contrib.admin'' ... ]

Tenga en cuenta la diferencia entre AdminConfig y SimpleAdminConfig, donde este último no desencadena admin.autodiscover() . Actualmente estoy usando esta solución en un proyecto.