Переключение темы администратора Django между Grappelli и Jazzmin Не работает (на основе сеанса)

Постановка задачи:

Я работаю над проектом электронной коммерции на Django и хочу, чтобы пользователи могли переключаться между двумя темами администратора: Grappelli и Jazzmin, используя Django сессии.

Я реализовал переключатель тем на основе сеанса, но:

  • Панель администратора по умолчанию всегда загружает Grappelli.
  • Появится кнопка переключения , но при нажатии на нее не будет применена правильная тема.
  • После переключения на Jazzmin я получаю сообщение об ошибке "Страница не найдена" (404).
<время работы/>

Настройка проекта

1. Установленные приложения (settings.py)

INSTALLED_APPS = [
    "grappelli",  #  Defaulting to Grappelli
    "jazzmin",  #  Want to switch between these two
    
    "colorfield",
    "core.apps.CoreConfig",  #  My core app
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django.contrib.humanize",
]

Grappelli загружается по умолчанию, даже если сессия должна переключиться на Jazzmin.

<время работы/>

2. Промежуточное программное обеспечение для динамического переключения тем (core/middleware.py)

from django.utils.deprecation import MiddlewareMixin

class DynamicAdminThemeMiddleware(MiddlewareMixin):
    def process_request(self, request):
        from django.conf import settings

        if request.session.get("admin_theme") == "grappelli":
            settings.INSTALLED_APPS = ["grappelli"] + [app for app in settings.INSTALLED_APPS if app != "jazzmin"]
        else:
            settings.INSTALLED_APPS = ["jazzmin"] + [app for app in settings.INSTALLED_APPS if app != "grappelli"]

Я подозреваю, что динамическое изменение settings.INSTALLED_APPS может оказаться неэффективным.
Требуется ли перезапуск Django, чтобы изменения INSTALLED_APPS вступили в силу?

Промежуточное программное обеспечение включено в settings.py:

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "core.middleware.DynamicAdminThemeMiddleware",  #  Custom middleware
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]
<время работы/>

3. Настройка URL-адреса (core/urls.py)

from django.urls import path
from core.views import switch_theme

urlpatterns = [
    path("switch_theme/", switch_theme, name="switch_theme"),  #  Theme switcher
]

Я что-то пропустил в конфигурации URL-адреса?

<время работы/>

4. Режим переключения тем (core/views.py)

from django.shortcuts import redirect

def switch_theme(request):
    current_theme = request.session.get("admin_theme", "jazzmin")

    if current_theme == "grappelli":
        # Switch to Jazzmin – redirect to /admin/
        request.session["admin_theme"] = "jazzmin"
        request.session.modified = True  #  Ensure session updates
        return redirect("/admin/")  #  Redirect to Django admin

    else:
        # Switch to Grappelli – redirect to /grappelli/
        request.session["admin_theme"] = "grappelli"
        request.session.modified = True  #  Ensure session updates
        return redirect("/grappelli/")

Сеанс обновляется, но тема переключается неправильно.
Переопределяет ли промежуточное программное обеспечение переключение тем на основе сеанса?

<время работы/>

Основной проект urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('grappelli/', include('grappelli.urls')),
    path('admin/', admin.site.urls),
    path("", include("core.urls")),
]
<время работы/>

5. Изменение шаблона администратора (templates/admin/base_site.html)

{% extends "admin/base.html" %}

{% block branding %}
  <h1>My Custom Admin Panel</h1>
{% endblock %}

{% block userlinks %}
  {{ block.super }}

  <p>DEBUG: Admin Theme is: {{ request.session.admin_theme }}</p>

  {% if request.session.admin_theme == "grappelli" %}
      <a href="{% url 'core:switch_theme' %}">Switch to Jazzmin</a>
  {% else %}
      <a href="{% url 'core:switch_theme' %}">Switch to Grappelli</a>
  {% endif %}
{% endblock %}

Переключатель появляется, но сеанс применяется неправильно.
Есть ли проблема с тем, как я ссылаюсь request.session.admin_theme?

<время работы/>

Проблема, с которой я столкнулся

  1. Тема всегда загружается как Grappelli
    • Даже когда сессия должна переключиться на Jazzmin.
  2. Нажатие кнопки "Сменить тему" приведет к перенаправлению на страницу 404
    • /admin/ неправильно загружается Jazzmin.
  3. Переключение не сохраняется
    • Несмотря на то, что request.session["admin_theme"] изменяется, применяемая тема остается неизменной.
<время работы/>

То, что Я Пробовал

  • Перезапустил сервер Django после изменения настроек:
    python manage.py runserver
    
  • Очищен кэш браузера и файлы cookie, чтобы обеспечить обновление сеансов.
  • Проверил обновления сеанса путем печати request.session.admin_theme.
  • Пробовал разные URL-адреса перенаправления (reverse("admin:index") вместо /admin/).
  • Проверенный INSTALLED_APPS заказ и выполнение промежуточного программного обеспечения.
<время работы/>

Вопросы

  1. Можно ли динамически изменять INSTALLED_APPS в промежуточном программном обеспечении, или Django требует перезапуска?
  2. Почему Jazzmin выдает ошибку 404 при переключении?
  3. Есть ли лучший способ динамически применять темы администрирования с помощью сеансов?
<время работы/>

Системная информация

  • Версия для Django: 5.1.3
  • Версия на Python: 3.12.5
  • Джазовая версия: 3.0.1
  • Версия Граппелли: 4.0.1
  • База данных: SQLite
<время работы/>

Ожидаемое поведение

  • /admin/ должен загрузиться Jazzmin.
  • /grappelli/ следует загрузить Граппелли.
  • При нажатии кнопки Переключить тему следует применить правильную тему без ошибок.
<время работы/>

**Мы будем очень признательны за любую помощь! Заранее спасибо! **

Поскольку INSTALLED_APPS не может быть изменен во время выполнения, лучший способ реализовать переключение тем - это:

  1. Определите два отдельных сайта администратора (один для Jazzmin, другой для Grappelli).

  2. Используйте переключатель на основе сеанса для динамического назначения активного сайта администратора.

  3. Обеспечьте правильную маршрутизацию URL-адресов, чтобы Django знал, какого администратора загружать.

Создайте собственный сайт администратора для Jazzmin и Grappelli

Изменить core/admin.py:

from django.contrib.admin import AdminSite
from django.conf import settings

class GrappelliAdminSite(AdminSite):
    site_header = "Grappelli Admin"
    site_title = "Grappelli Admin"
    index_title = "Welcome to Grappelli Admin"

class JazzminAdminSite(AdminSite):
    site_header = "Jazzmin Admin"
    site_title = "Jazzmin Admin"
    index_title = "Welcome to Jazzmin Admin"

# Instances of admin sites
grappelli_admin_site = GrappelliAdminSite(name="grappelli_admin")
jazzmin_admin_site = JazzminAdminSite(name="jazzmin_admin")

Регистрируйте модели на обоих сайтах администратора

В core/admin.py зарегистрируйте модели на обоих сайтах:

from django.contrib import admin
from .models import Product, Category
from .admin import grappelli_admin_site, jazzmin_admin_site

# Register your models with both admin sites
for model in [Product, Category]:
    admin.site.register(model)  # Default admin site
    grappelli_admin_site.register(model)
    jazzmin_admin_site.register(model)

Определите переключатель на основе URL-адреса для панели администратора

Изменить core/urls.py

from django.urls import path, include
from core.views import switch_theme
from core.admin import grappelli_admin_site, jazzmin_admin_site
from django.contrib import admin

urlpatterns = [
    path("switch_theme/", switch_theme, name="switch_theme"),  # Theme switcher
    
    # Route based on session theme
    path("grappelli-admin/", grappelli_admin_site.urls),
    path("jazzmin-admin/", jazzmin_admin_site.urls),
    
    # Default Django admin (fallback)
    path("admin/", admin.site.urls),
]

Реализуйте режим переключения тем

Изменить core/views.py:


from django.shortcuts import redirect

def switch_theme(request):
    # Toggle between themes
    current_theme = request.session.get("admin_theme", "jazzmin")

    if current_theme == "grappelli":
        request.session["admin_theme"] = "jazzmin"
        return redirect("/jazzmin-admin/")  # Redirect to Jazzmin admin
    else:
        request.session["admin_theme"] = "grappelli"
        return redirect("/grappelli-admin/")  # Redirect to Grappelli admin

Измените шаблон администратора для переключения темы

Изменить templates/admin/base_site.html:

{% extends "admin/base.html" %}

{% block branding %}
  <h1>My Custom Admin Panel</h1>
{% endblock %}

{% block userlinks %}
  {{ block.super }}

  <p>Current Admin Theme: {{ request.session.admin_theme }}</p>

  {% if request.session.admin_theme == "grappelli" %}
      <a href="{% url 'switch_theme' %}">Switch to Jazzmin</a>
  {% else %}
      <a href="{% url 'switch_theme' %}">Switch to Grappelli</a>
  {% endif %}
{% endblock %}

Ожидаемое поведение

  • /grappelli-admin/ → Загружает Grappelli Admin.

  • /jazzmin-admin/ → Загружает Jazzmin Admin.

  • Нажатие кнопки "Переключить тему" корректно переключает между Jazzmin и Grappelli.

Я надеюсь, что это поможет вам.

Вернуться на верх