如何在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
相关产品推荐
相关产品推荐

