我有一个本地化的Django App,本地化效果很好,配置还可以......
对于表单需求,我使用模型的__unicode__
方法来呈现ModelChoiceFields,但是如何在unicode返回中格式化本地化日期?
在这种方法中,我无法访问当前时区,如何正确地向我的用户显示我的TimeSpanList?目前,它显示UTC。我试过django.template.defaultfilters.date
和Simon Charette的django.utils.formats.localize
,因为他们可能缺乏上下文数据而没有帮助......
class TimeSpan(models.Model):
start = models.DateTimeField(_("start"))
end = models.DateTimeField(_("end"))
def __unicode__(self):
return u"from UTC:{0} to UTC:{1}".format(self.start, self.end)
class TimeSpanChooserForm(forms.Form):
time_span = forms.ModelChoiceField(
label=_("time span"), queryset=TimeSpan.objects.all())
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
super(TimeSpanChooserForm, self).__init__(*args, **kwargs)
如何知道没有当前请求对象的当前区域设置来本地化这些日期时间? (如果有办法)
注意:对我来说__unicode__
似乎是在ModelChoiceField中显示条目的唯一方法。
答案 0 :(得分:4)
感谢您提醒我这个问题。有一点完整的答案。
我已经创建了一个演示方法,可以显示这一点。运行test()
以查看输出。
剩下的挑战是获取客户端时区。这可能是通过一些JavaScript向您的GET / POST添加参数或添加要在视图中读取的自定义标头来完成的。
由于这是未知的,我只是使用返回随机时区的方法将其删除。您应该更新它以反映您的客户端时区检索方法。
这是一个自我记录的例子:
from django.utils.formats import localize
class TimeSpan(models.Model):
start = models.DateTimeField("start")
end = models.DateTimeField("end")
def __unicode__(self):
return u"from UTC:{0} to UTC:{1}".format(self.start, self.end)
from django import forms
class TimeSpanChooserForm(forms.Form):
time_span = forms.ModelChoiceField(
label=("time span"), queryset=TimeSpan.objects.all())
def __init__(self, *args, **kwargs):
# get request and TZ from view. This is a special form..
self.request = kwargs.pop("request", None)
self.tz = kwargs.pop('tz', None)
super(TimeSpanChooserForm, self).__init__(*args, **kwargs)
# modify the choices attribute to add custom labels.
self.fields['time_span'].choices = [
self.make_tz_aware_choice(self.request, timespan) for timespan in self.fields['time_span'].queryset
]
def make_tz_aware_choice(self, request, timespan):
""" Generate a TZ aware choice tuple.
Must return (value, label). In the case of a ModelChoiceField, (instance id, label).
"""
start = timespan.start.replace(tzinfo=self.tz)
end = timespan.end.replace(tzinfo=self.tz)
label = "From {tz} {start} to: {tz} {end}".format(
start=start,
end=end,
tz=self.tz,
)
return (timespan.id, label)
import random
import pytz
from django import http
from django import template
def view(request):
""" Render a form with overridden choices respecting TZ
"""
def get_tz_from_request(request):
""" Get the client timezone from request.
How you do this is up to you. Likely from JS passed as a parmeter.
"""
random_timezone = random.choice(pytz.all_timezones)
return pytz.timezone(random_timezone)
form = TimeSpanChooserForm(request.POST or None, request=request, tz=get_tz_from_request(request))
ctx = template.Context({
'form': form,
})
rendered_template = template.Template("{{ form }}").render(ctx)
return http.HttpResponse(rendered_template)
def test():
from django.test import RequestFactory
rf = RequestFactory()
r = rf.get('/')
for i in range(10):
print str(view(r))
答案 1 :(得分:0)
您可以使用django.utils.formats.localize
功能。
from django.db import models
from django.utils.formats import localize
from django.utils.translation import ugettext
class TimeSpan(models.Model):
start = models.DateTimeField(_('start'))
end = models.DateTimeField(_('end'))
def __unicode__(self):
return ugettext("from %(start)s to %(end)s") % {
'start': localize(self.start),
'end': localize(self.end),
}
您可以使用这些操作测试以下工作。
from django.utils import timezone
from django.utils.translation import override
with override('fr'):
print(TimeSpan(start=timezone.now(), end=timezone.now()))
with override('en'):
print(TimeSpan(start=timezone.now(), end=timezone.now()))
两者都应该显示不同的格式。
如果您想确保日期显示在特定时区,您必须确保设置中的USE_TZ = True
并将TIME_ZONE
设置为您要使用的设置。您可以使用使用所需时区调用django.utils.timezone.activate
的中间件为每个请求设置此时区。
你也可以使用django-sundial包来处理这件事。
答案 2 :(得分:-2)
试试这个:
def __unicode__(self):
return u'%s %s'%(self.start,self.end)
使用此购买它将返回组合的开始和结束日期时间对象。这对我有用