#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),
]
Идея здесь состоит в том, чтобы скопировать зарегистрированные модели с сайта администратора по умолчанию. Может быть, это нехорошо, но я не смог найти ничего другого, что работало бы.