Как использовать пользовательский класс AdminSite?

Каков наилучший способ реализовать собственный django.contrib.admin.sites.AdminSite ?

На самом деле у меня проблема с регистрацией INSTALLED_APPS в django.contrib.admin.autodiscover . Если я использую свой собственный класс urls.py в urls.py , на странице администратора не было приложений.

Я исправил это с помощью litte. Я написал этот класс:

 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) 

И реализовать свой пользовательский AdminSite вот так:

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

Поэтому я могу использовать этот site для urls.py

Кто-нибудь знает лучший способ? Поскольку я обращаюсь к var, начинающему с подчеркивания, это не более чем хак. Мне не нравятся хаки.

Изменить: Другой способ – переписать функцию django.contrib.admin.autodiscover , но в этом случае у меня будет избыточный код.

2 Solutions collect form web for “Как использовать пользовательский класс AdminSite?”

Цитата из https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#customizing-the-adminsite-class

Однако, если вы хотите настроить свой собственный административный сайт с помощью настраиваемого поведения, вы можете подклассифицировать AdminSite и переопределить или добавить что угодно. Затем просто создайте экземпляр вашего подкласса AdminSite (так же, как вы создадите экземпляр любого другого класса Python), и зарегистрируйте свои подклассы ModelAdmin и вместо него, вместо того, чтобы использовать значение по умолчанию .

Я предполагаю, что это самый явный подход, но это также означает, что вам нужно изменить код регистра в файлах admin.py приложений.

Нет необходимости использовать автообнаружение при использовании собственного экземпляра AdminSite, поскольку вы, вероятно, будете импортировать все модули admin.py для каждого приложения в свой модуль myproject.admin.

Предположение, похоже, заключается в том, что после того, как вы начнете писать свой собственный сайт администратора, он становится практически специфичным для проекта, и вы заранее знаете, какие приложения вы хотите включить.

Поэтому, если вы не хотите работать с хаком выше, я действительно вижу эти два варианта. Замените все вызовы регистров на свой собственный сайт администратора или зарегистрируйте модели явно в своем модуле adminsite.

Проблема

Использование пользовательского класса, полученного из django.contrib.admin.AdminSite для сайта администратора проекта, без необходимости писать собственный регистрационный код для регистрации моделей с новым классом. Когда я использую сторонние приложения со своими собственными моделями, я бы предпочел не редактировать собственный регистрационный код только потому, что модели были добавлены или удалены из этих приложений.

Решение

Вы должны переключить экземпляр, созданный с классом по умолчанию, используемым для сайта администратора, в свой собственный экземпляр, созданный с помощью собственного класса, до django.contrib.admin как autodiscover функция autodiscover . Я делаю это:

  1. Наличие приложения, которое будет выполнять переключатель. (Я использую свое проектное приложение с именем core для моих собственных целей.)

  2. Два варианта:

    1. Django 1.6 – 1.9: используйте __init__ приложения для выполнения переключения. В Django 1.8 вы получите предупреждение об устаревании из-за изменения в Django 1.9, приведенном ниже. Обратите внимание, что этот метод будет работать и с 1.9, потому что модули Django, загруженные приведенным ниже кодом, были изменены в 1.9, так что они больше не загружают модели. Когда я использую этот метод, файл core/__init__.py содержит:

       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 и более: используйте конфигурацию приложения для выполнения этого переключателя. По состоянию на Django 1.9, как говорится в релизе :

      Все модели должны быть определены внутри установленного приложения или объявить явную метку app_label. Кроме того, их невозможно импортировать до загрузки приложения. В частности, невозможно импортировать модели внутри корневого пакета приложения.

      Я предпочитаю ограничивать импорт, который я делаю на корневом уровне, чтобы избежать риска загрузки моделей. Хотя с версии 1.9 с использованием метода __init__ выше будет работать , нет никакой информации, если 1.10 или более поздняя версия внесут изменения, которые вызовут проблемы.

      Когда я использую этот метод, core/__init__.py устанавливает default_app_config = "core.apps.DefaultAppConfig" и у меня есть core/apps.py как это:

       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 

      Хотя этот метод можно использовать с версиями 1.7 и 1.8, немного рискованно использовать его с этими версиями. См. Примечания ниже.

  3. Размещение этого приложения раньше, чем django.contrib.admin в списке INSTALLED_APPS . (Это абсолютно необходимо для 1.7 и более поздних версий. В более ранних версиях Django это может сработать, даже если приложение позже django.contrib.admin . Однако см. Примечания ниже).

Примечания и оговорки

  • Приложение, которое выполняет переключатель, должно быть действительно первым приложением в списке INSTALLED_APPS чтобы свести к минимуму вероятность того, что что-то еще захватит значение site с django.contrib.admin до того, как будет выполнен переход. Если другому приложению удастся получить это значение до того, как коммутатор будет завершен, тогда другое приложение будет иметь ссылку на старый сайт. Веселость, несомненно, наступит.

  • Вышеуказанный метод не будет работать хорошо, если два приложения попытаются установить свой собственный новый класс админ-сайта по умолчанию. Это нужно будет обрабатывать в каждом конкретном случае.

  • Возможно, что будущий выпуск Django может нарушить этот метод.

  • Для версии до 1.9 я предпочитал использовать __init__ для переключения сайта с помощью конфигурации приложения, потому что документация по инициализации указывает, что метод ready() конфигураций приложений называется относительно поздним. Между тем, когда загружен модуль приложения и вызывается время ready() , модели загружены, и в некоторых случаях это может означать, что модуль захватил значение site из django.contrib.admin до того, как будет вызвана , Чтобы свести к минимуму риск, у меня есть код __init__ приложения.

    Я полагаю, что риск, существовавший в версиях 1.7 и 1.8, и который я избегал с помощью __init__ для выполнения переключателя сайта как можно раньше, не существует в 1.9. Всем запрещается загружать модули до загрузки всех приложений. Таким образом, включение в ready обратном вызове первого приложения, указанного в INSTALLED_APPS должно быть безопасным. Я модернизировал большой проект до 1.9 и использовал метод настройки приложения без каких-либо проблем.

  • Django - 404 страница, отображаемая для веб-сервера dev (http://127.0.0.1:8000/)
  • изменить значение формы администратора admin
  • Django Admin inline для рекурсивного ManyToMany
  • Django admin, пользовательское сообщение об ошибке?
  • Наследие Django admin Наследование возможно?
  • Приложение администратора Django для главной / подробной страницы
  • Используйте форму с пользовательским __init__ в Django Admin
  • Django: запретить can_delete в GenericStackedInline
  • Python - лучший язык программирования в мире.