I'm attempting to dynamically add translatable fields for my forms.ModelForm
, depending on whether the customer has enabled the language or not. However, the translated value isn't saved to the model.
from copy import deepcopy
from django import forms
from modeltranslation.fields import TranslationField
class DefaultModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if user := self.request and self.request.user:
company = user.company
app_setting = company.settings
default_lang = settings.MODELTRANSLATION_DEFAULT_LANGUAGE # "en"
default_search = f"_{default_lang}"
to_add = []
"""Set field_order to the same order as set in Meta.fields, unless already set"""
if self.field_order is None:
self.field_order = list(self.Meta.fields)
for modelfield in self._meta.model._meta.fields:
"""If we found a default translation field, add it to the list"""
if (
(formfield := self.fields.get(modelfield.name, None))
and modelfield.name.endswith(default_search)
and isinstance(modelfield, TranslationField)
):
to_add.append(
{
"position": self.field_order.index(modelfield.name),
"formfield": deepcopy(formfield),
"name": modelfield.name.removesuffix(default_search), # "description"
"languages": app_setting.get_additional_language_codes, # ["es"]
}
)
for addable in to_add:
for lang in addable.get("languages"):
field_name = f"{addable.get('name')}_{lang}" # "description_es"
formfield = addable.get("formfield")
formfield.label = formfield.label.replace(f"[{default_lang}]", f"[{lang}]")
formfield.required = False
formfield.initial = getattr(self.instance, field_name, "")
self.fields[field_name] = formfield
self.field_order.insert(addable.get("position", 0) + 1, field_name)
self.order_fields(self.field_order)
This code allows me to render the fields accordingly. If the customer has selected to show e.g. "es"
(Spanish), the translatable field ("description_en"
) will be copied and I create a new field ("description_es"
) in the right position inside the field_order
. So far, all is well.
But when I POST the form, this is what happens inside my view:
def form_valid(self, form):
is_updating = True if form.instance.pk else False
self.object = form.save()
if is_updating:
# Todo: print message
pass
breakpoint()
"""
(Pdb++) form.is_valid()
True
(Pdb++) form.cleaned_data
{'company': <Company: Test>, 'description_en': 'I have a library!', 'description_es': 'Tengo una biblioteca!'}
(Pdb++) self.object = form.save()
(Pdb++) self.object
<Venue: TestVenue>
(Pdb++) self.object.description_en
'I have a library!'
(Pdb++) self.object.description_es
''
"""
return super().form_valid(form)
Here is what I don't understand: why isn't the description_es
value saved to the object?