首页 > 解决方案 > 在 Django 项目中添加不同的主题模式

问题描述

我正在尝试在我的 Django 项目中为用户添加主题。用户可以在暗模式和亮模式之间进行选择。

所以在 base.html 中,我将链接设置如下:

    <link id="mystylesheet" href="{% static 'css/app-light.css' %}" type="text/css" rel="stylesheet">
        <!-- Mode -->
        <div id="mode" class="section" style="padding-top: 1rem; padding-bottom: 3rem;text-align: right">
            <button onclick="swapStyles('app-light.css')" type="button" class="btn btn-secondary">Light Mode</button>
            <button onclick="swapStyles('app-dark.css')" type="button" class="btn btn-dark">Dark Mode</button>
        </div>
        <!-- Mode -->

我已经使用以下 models.py 启动了一个名为 mode 的新应用程序:

class Setting(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="mode",null=True,blank=True)
    name = models.CharField(max_length=200, null=True)
    value = models.CharField(max_length=200)

    def __str__(self):
        return self.name

这是javascript

    <script type="text/javascript">

        function getCookie(name) {
            var cookieValue = null;
            if (document.cookie && document.cookie !== '') {
                var cookies = document.cookie.split(';');
                for (var i = 0; i < cookies.length; i++) {
                    var cookie = cookies[i].trim();
                    // Does this cookie string begin with the name we want?
                    if (cookie.substring(0, name.length + 1) === (name + '=')) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
        }
        var csrftoken = getCookie('csrftoken');

        var cssFile = "{% static 'css' %}"
        function swapStyles(sheet){
            document.getElementById('mystylesheet').href = cssFile + '/' + sheet
            localStorage.setItem('theme', sheet)

            updateTheme(sheet)
        }
        function loadSettings(){
            //Call data and set local storage

            var url = "{% url 'mode:user_settings' %}"
            fetch(url, {
                method:'GET',
                headers:{
                    'Content-type':'application/json'
                }
            })
            .then((response) => response.json())
            .then(function(data){

                console.log('Data:', data)

                var theme = data.value;

                if (theme == 'light.css' || null){
                    swapStyles('light.css')
                }else if(theme == 'dark.css'){
                    swapStyles('dark.css')
                }
            })
        }
        loadSettings()
        function updateTheme(theme){
            var url = "{% url 'mode:update_theme' %}"
            fetch(url, {
                method:'POST',
                headers:{
                    'Content-type':'application/json',
                    'X-CSRFToken':csrftoken,
                },
                body:JSON.stringify({'theme':theme})
            })
        }
    </script>

这是 urls.py

app_name = 'mode'

urlpatterns = [
    path('user_settings/', views.userSettings, name="user_settings"),
    path('update_theme/', views.updateTheme, name="update_theme"),
]

我很难设置用户设置views.py 以反映用户何时登录,但是,更新的主题工作正常。

def userSettings(request):
    user = request.user
    setting = getattr(user, 'setting', None)

def updateTheme(request):
    data = json.loads(request.body)
    theme = data['theme']

    user = request.user
    setting = Setting.objects.update_or_create(
        user=user, defaults={'value': theme}, name='theme')

    print('Request:', theme)
    return JsonResponse('Updated..', safe=False)

我的问题:如何将user settings当前登录的用户设置为默认设置为亮模式,如果他选择在所有页面的数据库中设置暗模式当它处于暗模式并且用户选择在数据库中设置的亮模式时。

标签: pythondjango

解决方案


您可以这样做的一种方法是;

  1. 为用户偏好定义模型
  2. 创建上下文处理器以将首选项传递给您的模板
  3. 在您的模板中为用户首选项添加一个检查,然后传递定义的css

然后,您可以在设置更改时强制刷新页面以“应用”新值。

这是一个例子


models.py

class Preferences(models.Model):
    
    themes = (
        ('light', 'Light Theme'),
        ('dark', 'Dark Theme'),
    )
    
    preference_id = models.AutoField(primary_key=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    
    theme = models.CharField(max_length=255, choices=themes)
    
    
    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['user'], name='One Entry Per User')
        ]

context processor

from apps.users.models import Preferences

def pref(request):
    if request.user.is_authenticated:
        _preferences = Preferences.objects.filter(user=request.user).last()
            
    else:
        _preferences = None
            
    return {
        'user_pref': _preferences,
    }

settings.py

TEMPLATES = [
    {
        'BACKEND': ...,
        'DIRS': ...,
        'OPTIONS': {
            'context_processors': [
                'context_processors.user_preferences_context.pref',
                ],
        },
    },
]

base.html

{% if user_pref.theme == 'dark' %}
<link href="{% static 'theme/css/themes/layout/header/base/dark.css' %}" rel="stylesheet" type="text/css" />
<link href="{% static 'theme/css/themes/layout/header/menu/dark.css' %}" rel="stylesheet" type="text/css" />
<link href="{% static 'theme/css/themes/layout/brand/dark.css' %}" rel="stylesheet" type="text/css" />
<link href="{% static 'theme/css/themes/layout/aside/dark.css' %}" rel="stylesheet" type="text/css" />
{% else %}
<link href="{% static 'theme/css/themes/layout/header/base/light.css' %}" rel="stylesheet" type="text/css" />
<link href="{% static 'theme/css/themes/layout/header/menu/light.css' %}" rel="stylesheet" type="text/css" />
<link href="{% static 'theme/css/themes/layout/brand/light.css' %}" rel="stylesheet" type="text/css" />
<link href="{% static 'theme/css/themes/layout/aside/light.css' %}" rel="stylesheet" type="text/css" />
{% endif %}

文件结构

project/
    -> apps
        -> Django Apps stored here
    -> context_processors
        -> Custom context processors stored here
    -> project
        -> settings.py
    manage.py

推荐阅读