I have a localized Django App, localisation works well and the configuration is ok…
For forms needs, I use __unicode__
method for model to render ModelChoiceFields, but how do I format localized date in the unicode return?
In this method I have no access to current timezone, how to display my TimeSpanList correctly to my users? Currently, it displays UTC. I tryed django.template.defaultfilters.date
and Simon Charette's django.utils.formats.localize
which didn't helped as they probably lacked contextual data…
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)
How to know current locale without current request object to localize those datetimes? (If there is a way)
note: to me __unicode__
seems like the only way to display entries in ModelChoiceField.
note 2: to me, Yuji 'Tomita' Tomita comment is the best current answer but it lacks a usable exemple…
Thanks for reminding me about this question. It's a bit involved for a complete answer.
I've created a demo method that shows this in action. Run test()
to see output.
The remaining challenge is getting the client timezone. This will probably be done with some JavaScript that adds a parameter to your GET/POST or adds a custom header to be read in the view.
Since this is an unknown, I just stubbed it out with a method that returns a random time zone. You should update it to reflect your client timezone retrieval method.
Here's a self documenting example:
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))