如何在Django中从客户端自动获取用户的时区?

goqiplq2  于 2023-07-01  发布在  Go
关注(0)|答案(7)|浏览(160)

我想知道是否有一种方法可以自动检索用户的时区从客户端。特别是在登录时。
我尝试在登录页面中添加以下内容(使用auth.login):

{% get_current_timezone as TIME_ZONE %}

然后,在登录表单中添加以下内容:

<input type="hidden" name="next" value="/redirect/?tz={{ TIME_ZONE }}">

但是,tz始终是服务器的时区。

9vw9lbht

9vw9lbht2#

关于documentation
选择当前时区
当前时区相当于翻译的当前区域设置。但是,没有与Accept-Language HTTP头等效的东西,Django可以使用它来自动确定用户的时区。相反,Django提供了时区选择功能。使用它们来构建对您有意义的时区选择逻辑。
您可以尝试通过JavaScript使用getTimezoneOffset函数设置时区cookie,或者尝试做一些geoip魔术并按位置计算时区。可能最可靠的方法是直接询问用户并将此信息保存在用户配置文件/会话中。

tuwxkamq

tuwxkamq3#

我昨天在找山姆的事。最后,我最终把一个Django应用程序放在一起,按照上面BluesRockAddict的建议(即。使用getTimezoneOffset):
https://github.com/adamcharnock/django-tz-detect
我希望有人发现这有用。

0mkxixxg

0mkxixxg4#

django有一个很好的应用程序来激活时区https://pypi.python.org/pypi/django-visitor-information-middleware/0.1.0。它有两个中间件

时区中间件

  • 中间件为经过身份验证的用户激活时区。*
    访客信息中间件
  • 此中间件将以下键添加到request.visitor字典中:*

国家-访问者所在的国家。
city -访问者所在的城市
location.timezone -访问者所在位置的时区
location.unit_system -访问者所在位置使用的单位系统
user.timezone -当前通过身份验证的用户的时区
user.unit_system -当前认证用户的单位系统。
cookie_notice -如果应该为当前访问者显示cookie同意通知,则为True。

Note: Location of the user is determined based on the user's IP address.
eoigrqb6

eoigrqb65#

我目前创建了一个中间件类(遵循Django的文档),其中我依赖于MaxMind geoip数据库(http://dev.maxmind.com/geoip/legacy/geolite)和GeoDjango(https://docs.djangoproject.com/en/1.5/ref/contrib/gis/)来检索用户的国家代码,然后使用pytz动态设置时区:

class TimezoneMiddleware(object):

    def __getUserTimeZone(self, request):
        info = IPResolver(request).getGeoInfo()
        return pytz.country_timezones[info['country_code']][0]

    def process_request(self, request):
        try:
            tz = self.__getUserTimeZone(request)
            timezone.activate(tz)
            logger.debug('Time zone "%s" activated' % str(tz))
        except Exception as e:
            logger.error('Unable to set timezone: %s' % str(e))

pytz.country_timezones返回给定国家的可用时区集合,因此我基本上选择返回的第一个时区。
IPResolver是我在django.contrib.gis.utils.GeoIP之上编写的个人实用程序类

p1iqtdky

p1iqtdky6#

您可以使用django-tz-detect,它可以自动和动态地为每个用户检测和设置时区,而不是在settings.py中只使用一个设置为TIME_ZONE的时区。
首先,安装django-tz-detect,如下所示。* 我使用Django 4.2.1

pip install django-tz-detect

最后,将tz_detectTimezoneMiddleware分别设置为settings.py中的INSTALLED_APPS和MIDDLEWARE,如下所示。* 确保django.template.context_processors.request设置为TEMPLATES的OPTIONS的context_processors

# "core/settings.py"

INSTALLED_APPS = [
    ...
    'tz_detect' # Here
]

MIDDLEWARE = [
    ...
    'tz_detect.middleware.TimezoneMiddleware', # Here
]

...

TEMPLATES = [
    {
        ...
        'DIRS': [
            BASE_DIR / 'templates'
        ],
        ...
        'OPTIONS': {
            'context_processors': [
                ...
                'django.template.context_processors.request', # Here
                ...
            ],
        },
    },
]

实际上,通过上面的这些步骤,django-tz-detect对我来说工作正常,但如果它不工作,请执行下面的其他步骤。
因此,将下面的路径添加到core/urls.py中的urlpatterns,如下所示:

# "core/urls.py"

urlpatterns = [
    path('admin/', admin.site.urls),
    path('my_app1/', include('my_app1.urls')),
    path('tz_detect/', include('tz_detect.urls')) # Here
]

然后,加载tz_detect.py,然后在templates/base.html中的</body>标记之前使用tz_detect标记,如下所示:

{% "templates/base.html" %}

{% load tz_detect %}
...
{% tz_detect %}
</body>

最后,将base.html从虚拟环境中的django/contrib/admin/templates/admin/base.html复制到templates/admin/,然后加载tz_detect.py,然后在templates/admin/base.html中的</body>标记之前使用tz_detect标记,如下所示:

{% "templates/admin/base.html" %}
                               {% ↓ Here ↓ %}
{% load i18n static i18n_switcher tz_detect  %}<!DOCTYPE html>
...
<!-- END SVGs -->
{% tz_detect %}
</body>
vd2z7a6w

vd2z7a6w7#

我只是在我的程序中这样做。在我的js中:

<script> 
  var today = new Date()
  var offset = today.getTimezoneOffset()
  const serializedData = 'csrfmiddlewaretoken={{ csrf_token }}&tz_offset= ' 
  + offset.toString() 
</script>

在Django方面:

def your_function(request):
    tz_offset = request.POST.get('tz_offset')
    now = datetime.datetime.now() - timedelta(minutes=int(tz_offset))
    return now

我将serializedData传递给POST请求,然后在函数中访问它

<script>
   function update_transaction(serializedData){
    $.post('{% url "your_url" %}', serializedData, function(data){
        //do stuff
    });
}
</script>

相关问题