Django (1.10) переопределяет AdminSite

#python #django

#python #django

Вопрос:

Я попытался переопределить класс AdminSite своим собственным пользовательским классом. Я следовал руководству из документации django: https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#customizing-adminsite но это не сработало. Чтобы быть конкретным, я хотел бы переопределить исходный AdminSite своим собственным классом, а не просто добавить еще один сайт администратора в мой проект.

Я создал свой пользовательский класс MyAdminSite, который наследуется от class

 from django.contrib.admin import AdminSite


class MyAdminSite(AdminSite):
    pass
  

Затем в моем приложении urls.py Я добавил:

 from django.conf.urls import url, include
import django.contrib.admin as admin
from .admin_site import MyAdminSite

admin.site = MyAdminSite()
admin.autodiscover()


urlpatterns = [
    url(r'^', admin.site.urls),
]
  

Казалось, это сработало, но модели администратора регистрируются на AdminSite вместо MyAdminSite.

Я попробовал три способа регистрации моделей на своем пользовательском сайте:

 @admin.register(Model)
class ModelAdmin(model.AdminModel):
...
  

Таким образом, модели регистрируются на исходном AdminSite.

Второй способ:

 @admin.site.register(Model):
class ModelAdmin(model.AdminModel):
...
  

Это не работает и вызывает исключение. Класс ModelAdmin не передается методу register .

Последний способ:

 class ModelAdmin(model.AdminModel):
...
admin.site.register(Model, ModelAdmin)
  

Это работает, но на сайте администратора я вижу только свои модели, а не модели от администратора Django (пользователи и группы).

Как я могу навсегда переопределить admin.site и зарегистрировать все модели на MyAdminSite?

Комментарии:

1. Как вы регистрируете свои модели на своем пользовательском сайте администратора?

2. Что в документах, на которые вы ссылаетесь, заставило вас думать, что это сработает?

3. Сайт docs был просто примером, и я знаю, что есть что-то еще, кроме того, что я хочу. Я также перепробовал множество других руководств и других методов, но ни один из них не работает.

4. В Django 2.1 будет возможность легко переопределить сайт администратора по умолчанию.

Ответ №1:

Из myapp/admin.py:

 from django.contrib.auth.models import Group, User
from django.contrib.auth.admin import GroupAdmin, UserAdmin
from django.contrib.admin import AdminSite
from django.contrib import admin

from .models import MyModel #This is my app's model

# Custom admin site
class MyAdminSite(AdminSite):
    site_header = 'My Project Title'
    site_title  = 'My Project Title Administration'
    index_title = 'My Project Title Administration'
    # You can add on more attributes if you need 
    # Check out https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#adminsite-objects

# Create admin_site object from MyAdminSite
admin_site = MyAdminSite(name='my_project_admin')

# Register the models
class MyModelAdmin(admin.ModelAdmin):
    list_display = ('id', 'description')

admin_site.register(MyModel, MyModelAdmin)

# Create and register all of your models
# ....

# This is the default Django Contrib Admin user / group object
# Add this if you need to edit the users / groups in your custom admin
admin_site.register(Group, GroupAdmin)
admin_site.register(User, UserAdmin)
  

Из myproject/urls.py

 from django.conf.urls import url
from django.contrib import admin
from myapp.admin import admin_site ##! Important..Import your object (admin_site) instead of your class (MyAdminSite)

urlpatterns = [
    url(r'^admin/', admin_site.urls), #Now all /admin/ will go to our custom admin
]
  

Ответ №2:

Я не нашел решения своей проблемы, но я нашел обходной путь.

Сначала нам нужно создать модуль в нашем приложении (например admin.py ), а затем расширить класс AdminSite:

 from django.contrib.admin import AdminSite

class MyAdminSite(AdminSite):
    ...
  

Затем в нижней части модуля нам нужно создать экземпляр нашего MyAdminSite и зарегистрировать встроенные модели из Django:

 site = MyAdminSite()
site.register(Group, GroupAdmin)
site.register(User, UserAdmin)
  

Необходимый импорт:

 from django.contrib.auth.models import Group, User
from django.contrib.auth.admin import GroupAdmin, UserAdmin
  

В нашем модуле URL-адреса сайта нам нужно переопределить исходный объект сайта:

 from .admin import site

admin.site = site
admin.autodiscover()
...
url(r'^admin/', admin.site.urls)
...
  

Последнее изменение, которое нам нужно сделать, это зарегистрировать наши модели. Одна вещь, которую мы должны помнить, это то, что мы не можем использовать register в качестве декоратора подобным образом:

 @admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
    ...
  

или:

 @admin.site.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
    ...
  

Нам нужно определить наш класс ModelAdmin, а затем вызвать register для нашего объекта MyAdminSite:

 class MyModelAdmin(admin.ModelAdmin):
    ...
admin.site.register(MyModel, MyModelAdmin)
  

Это единственное решение, которое работает для меня.

Комментарии:

1. Это полезно! Жаль, что нам приходится идти на такие меры, чтобы расширить AdminSite и заставить его работать должным образом…

2. @icarovirtual Так верно. В итоге я использовал этот ответ, хотя все, что мне нужно было сделать, это добавить 2 дополнительные контекстные переменные на index.html страницу моего администратора

Ответ №3:

Я столкнулся с аналогичной проблемой. Я использовал Django 2.1, и хук из комментариев выше у меня не сработал. А также я не смог импортировать GroupAdmin и UserAdmin, например

 from django.contrib.auth.models import Group, User
from django.contrib.auth.admin import GroupAdmin, UserAdmin
  

Импорт GroupAdmin или UserAdmin по какой-то причине нарушил код. Я не смог определить точную причину.

Итак, мой обходной путь был (в project/urls.py ):

 from django.conf.urls import include, url
from django.contrib.admin import site
from project.admin import myadmin

myadmin._registry.update(site._registry)

urlpatterns = [
    url(r'^admin/', myadmin.urls),
    ]
  

Идея здесь состоит в том, чтобы скопировать зарегистрированные модели с сайта администратора по умолчанию. Может быть, это нехорошо, но я не смог найти ничего другого, что работало бы.