You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django+Bootstrap基础模板中实现主题切换及自定义?

Django + Bootstrap 主题切换与自定义方案

问题1:完善主题下拉菜单的选中状态与切换触发

模板动态渲染与事件绑定

修改下拉菜单代码,根据当前theme变量动态显示选中主题的文本和图标,同时给每个切换按钮添加标识和点击事件:

<li class="nav-item dropdown">
    <button class="nav-link dropdown-toggle" id="navbarThemeDropdown" type="button" data-bs-toggle="dropdown" aria-expanded="false">
        Theme: 
        {% if theme == 'light' %}
            Light <i class="bi bi-sun-fill"></i>
        {% elif theme == 'dark' %}
            Dark <i class="bi bi-moon-fill"></i>
        {% elif theme == 'custom' %}
            Custom <i class="bi bi-palette-fill"></i>
        {% endif %}
    </button>
    <div class="dropdown-menu" aria-labelledby="navbarThemeDropdown">
        <button class="dropdown-item d-flex justify-content-between theme-switcher" data-theme="light" type="button">
            Light <i class="bi bi-sun-fill"></i>
        </button>
        <button class="dropdown-item d-flex justify-content-between theme-switcher" data-theme="dark" type="button">
            Dark <i class="bi bi-moon-fill"></i>
        </button>
        <button class="dropdown-item d-flex justify-content-between theme-switcher" data-theme="custom" type="button">
            Custom <i class="bi bi-palette-fill"></i>
        </button>
    </div>
</li>

问题2:主题Cookie的设置与默认值处理

前端JS实现即时切换与Cookie管理

在基础模板底部添加JS代码,处理无Cookie时的默认设置,以及主题切换的Cookie写入和页面主题更新:

<script>
    // 初始化:无Cookie时默认设置为light
    if (!document.cookie.includes('theme=')) {
        document.cookie = 'theme=light; path=/; max-age=31536000'; // 有效期1年
        document.documentElement.setAttribute('data-bs-theme', 'light');
    }

    // 绑定主题切换事件
    document.querySelectorAll('.theme-switcher').forEach(button => {
        button.addEventListener('click', function() {
            const selectedTheme = this.getAttribute('data-theme');
            // 写入Cookie,根路径确保全站生效
            document.cookie = `theme=${selectedTheme}; path=/; max-age=31536000`;
            // 更新页面主题属性
            document.documentElement.setAttribute('data-bs-theme', selectedTheme);
            // 更新下拉按钮显示文本
            const dropdownBtn = document.getElementById('navbarThemeDropdown');
            let themeText = '', themeIcon = '';
            switch(selectedTheme) {
                case 'light':
                    themeText = 'Light';
                    themeIcon = '<i class="bi bi-sun-fill"></i>';
                    break;
                case 'dark':
                    themeText = 'Dark';
                    themeIcon = '<i class="bi bi-moon-fill"></i>';
                    break;
                case 'custom':
                    themeText = 'Custom';
                    themeIcon = '<i class="bi bi-palette-fill"></i>';
                    break;
            }
            dropdownBtn.innerHTML = `Theme: ${themeText} ${themeIcon}`;
        });
    });
</script>

后端上下文处理器优化

调整现有处理器,让登录用户优先使用数据库存储的主题(后续问题3适配):

def theme(request):
    if request.user.is_authenticated:
        return {'theme': request.user.profile.theme}
    return {'theme': request.COOKIES.get('theme', 'light')}

问题3:登录用户自定义主题的存储与变量注入

1. 扩展用户模型存储颜色字段

创建与User关联的Profile模型,存储主题类型和自定义颜色:

# models.py
from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    theme = models.CharField(max_length=10, default='light')  # 存储light/dark/custom
    navbar_bg = models.CharField(max_length=7, default='#ffffff')  # 十六进制颜色值
    body_bg = models.CharField(max_length=7, default='#f8f9fa')
    card_bg = models.CharField(max_length=7, default='#ffffff')

    def __str__(self):
        return self.user.username

执行python manage.py makemigrations和python manage.py migrate创建数据表。

2. 上下文处理器注入自定义颜色

修改处理器,将登录用户的自定义颜色传递到模板:

def theme(request):
    context = {}
    if request.user.is_authenticated:
        profile = request.user.profile
        context['theme'] = profile.theme
        context['custom_colors'] = {
            'navbar_bg': profile.navbar_bg,
            'body_bg': profile.body_bg,
            'card_bg': profile.card_bg
        }
    else:
        context['theme'] = request.COOKIES.get('theme', 'light')
    return context

3. 模板内联样式注入变量

在基础模板的<head>中添加内联样式,当主题为custom时加载用户自定义颜色:

<head>
    <!-- 其他资源引入 -->
    <style>
        {% if theme == 'custom' and user.is_authenticated %}
        [data-bs-theme="custom"] {
            --navbar-bg: {{ custom_colors.navbar_bg }};
            --body-bg: {{ custom_colors.body_bg }};
            --card-bg: {{ custom_colors.card_bg }};
            --bs-body-bg: var(--body-bg);
            --bs-navbar-bg: var(--navbar-bg);
            --bs-card-bg: var(--card-bg);
        }
        {% endif %}
    </style>
</head>

4. 账户设置页面的颜色配置表单

创建表单让用户修改自定义颜色:

# forms.py
from django import forms
from .models import UserProfile

class CustomThemeForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ['navbar_bg', 'body_bg', 'card_bg']
        widgets = {
            'navbar_bg': forms.TextInput(attrs={'type': 'color'}),
            'body_bg': forms.TextInput(attrs={'type': 'color'}),
            'card_bg': forms.TextInput(attrs={'type': 'color'}),
        }

编写视图处理表单提交:

# views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from .forms import CustomThemeForm

@login_required
def custom_theme_settings(request):
    profile = request.user.profile
    if request.method == 'POST':
        form = CustomThemeForm(request.POST, instance=profile)
        if form.is_valid():
            form.save()
            # 设置Cookie为custom,确保即时生效
            response = redirect('settings')
            response.set_cookie('theme', 'custom', max_age=31536000, path='/')
            return response
    else:
        form = CustomThemeForm(instance=profile)
    return render(request, 'settings/custom_theme.html', {'form': form})

内容的提问来源于stack exchange,提问作者Kanapek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 12:36:13