Sindri Guðmundsson Sindri Guðmundsson - 3 months ago 29
Python Question

Django form field label translations

I have a baseform with over 20 fields. Then I have about 15 other forms inheriting from that form, passing in a parameter called fields which the baseform uses to delete all other fields. Best explain via example:

class BaseForm(forms.Form):
reportid = forms.HiddenInput()
fromdate = forms.DateField(label=_("From"), widget=widgets.AdminDateWidget())
todate = forms.DateField(label=_("To"), widget=widgets.AdminDateWidget())
sort_by = forms.ChoiceField(label=_("Sort by"), choices=[])

def __init__(self, *args, **kwargs):
fields = kwargs.pop('fields')
***del self.fields[field] for field not in fields***

class SubForm(forms.Form):
def __init__(self, *args, **kwargs):
fields = ['reportid', 'todate']
super(SubForm, self).__init__(fields=fields, *args, **kwargs)

The resulting form would then look like this:

class SubForm(forms.Form):
reportid = forms.HiddenInput()
todate = forms.DateField(label=_("To"), widget=widgets.AdminDateWidget())

My problem is that when the BaseForm is initialized for the first time, the labels are bound to the fields with the active language, and when another user logs in with another language setting (or the current user changes languages) the field labels don't update.

I've come to a solution using a dict like this:

labels = {
'todate': lambda: _("To"),
'fromdate': lambda: _("From"),

and then when initializing the baseform looping through all fields and setting

self.fields[field].widget.label = labels[field]()

Do I have any nicer (read: more pythonic) way of achieving this?


Django provides _lazy variants of the translation functions (for example ugettext_lazy) so you can ark strings for translations at the access time (as opposed to when the translation function is called).

It's documented in details at