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

如何在Django Machina论坛中显示用户本地时区的帖子时间?

实现Django-Machina论坛帖子时间按用户本地时区显示

核心问题分析

你当前的localtime过滤器无效,是因为Django默认使用settings.TIME_ZONE作为当前请求的时区,即使开启了USE_TZ=True,也不会自动切换到用户本地时区。要实现需求,需要获取并激活用户的时区,让localtime过滤器基于该时区渲染时间。


具体实现步骤

1. 存储用户时区偏好(针对登录用户)

如果论坛支持用户登录,在用户模型中添加时区字段,让用户自行设置偏好:

# 你的app/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from pytz import all_timezones

class CustomUser(AbstractUser):
    # 提供所有时区选项供用户选择
    timezone = models.CharField(
        max_length=100,
        choices=[(tz, tz) for tz in all_timezones],
        default='UTC'
    )

记得在settings.py中配置自定义用户模型:

AUTH_USER_MODEL = 'your_app.CustomUser'

2. 编写中间件激活用户时区

创建中间件,在每次请求时根据用户设置(或浏览器时区)激活对应时区:

# 你的app/middleware.py
from django.utils import timezone
import pytz

class UserTimezoneMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # 优先使用登录用户的时区设置
        user_timezone = None
        if request.user.is_authenticated:
            user_timezone = request.user.timezone
        # 未登录用户尝试从Cookie读取浏览器时区
        else:
            user_timezone = request.COOKIES.get('user_timezone')
        
        # 验证时区有效性并激活
        if user_timezone and user_timezone in pytz.all_timezones:
            timezone.activate(user_timezone)
        else:
            timezone.deactivate()
        
        response = self.get_response(request)
        return response

将中间件添加到settings.py的MIDDLEWARE列表中,注意要放在AuthenticationMiddleware之后:

MIDDLEWARE = [
    # ... 其他中间件
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'your_app.middleware.UserTimezoneMiddleware',
    # ...
]

3. 自动获取未登录用户的浏览器时区

通过JS获取浏览器时区并存入Cookie,让未登录用户也能看到本地时间:

<!-- 在论坛基础模板(如base.html)中添加 -->
<script>
document.addEventListener('DOMContentLoaded', () => {
    if (!document.cookie.includes('user_timezone')) {
        // 获取浏览器默认时区
        const browserTz = Intl.DateTimeFormat().resolvedOptions().timeZone;
        // 存入Cookie,有效期1年
        document.cookie = `user_timezone=${browserTz}; path=/; max-age=31536000`;
        // 刷新页面使时区生效
        window.location.reload();
    }
});
</script>

4. 修改Django-Machina模板中的时间渲染

找到Django-Machina对应显示时间的模板文件(比如machina/forum_conversation/templates/forum_conversation/posts_list.html中渲染帖子时间的部分),确保时间字段使用localtime过滤器:

<small>{{ post.created|localtime }}</small>

如果需要自定义时间格式,可以搭配date过滤器:

<small>{{ post.created|localtime|date:"Y-m-d H:i:s" }}</small>

验证效果

在模板中再次使用测试代码:

{% get_current_timezone as TIME_ZONE %}
当前时区:{{ TIME_ZONE }}

此时应该显示用户设置的时区(或浏览器时区),localtime过滤器也会基于该时区渲染时间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 20:33:35