hvad.forms
¶
TranslatableModelFormMetaclass¶
-
class
hvad.forms.
TranslatableModelFormMetaclass
¶ Metaclass of
TranslatableModelForm
.-
__new__
(cls, name, bases, attrs)¶ Uses Django’s internal
fields_for_model
to get translated fields for model and fields declarations, then lets Django handle the other fields. Once it is done, it merges the translated fields, preserving order.Special handling is done to:
- Prevent
language_code
from being used in any way by a field. This is because the form uses thelanguage_code
key in thecleaned_data
dictionary. - Prevent
master
from being recognized as a translated field. It is still a valid field name though. - Prevent the translations accessor from being used as a field.
- Prevent
-
TranslatableModelForm¶
-
class
hvad.forms.
BaseTranslatableModelForm
(BaseModelForm)¶ The actual class supporting the features and methods, but lacking metaclass sugar. Inherited by
TranslatableModelForm
to attach the metaclass. Details are documented on that class.
-
class
hvad.forms.
TranslatableModelForm
(BaseTranslatableModelForm)¶ Main form for editing
TranslatableModel
instances. As with regular djangoForm
classes, it can be used either directly or by passing it totranslatable_modelform_factory()
.As an extension to regular forms, it handles translation and can be bound to a language. Binding to a language is done by setting
language
on the class (not the instance), either by inheriting it manually or using the factory function. Once bound to a language, the form is in enforce mode: all manipulations will be done using that language exclusively.-
__metaclass__
¶
-
language
¶ The language the form is bound to. This is a class attribute. If present, the form is in enforce mode and will only deal with the specified language. See each method for the exact effects.
-
__init__
(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=ErrorList, label_suffix=':', empty_permitted=False, instance=None)¶ If this class is initialized with an instance, that has a translation loaded, it updates
initial
to also contain the data from the Translations Model.If the form is not bound to a language, it will use the data from the instance. If the instance has no translation loaded, an attempt will be made at loading the current language, and if that fails the fields will be blank.
If the form is in enforce mode and the instance does not have the correct translation loaded, then:
- it will attempt to load it from the database.
- if that fails, it will try to use the loaded translation on the instance.
- if that fails (instance is untranslated), it will use default values.
This process results in new translations being pre-populated with data from another language. Simply pass an instance in that language, or an untranslated instance if the behavior is not desired.
-
clean
(self)¶ If the form is in enforce mode, namely if it has a
language
property, apply the it tocleaned_data
. As usual, the special valueNone
is replaced by current language.If the form is not bound to a language, this method does nothing. It is then possible to either use
save()
in unbound mode or set the language code manually incleaned_data['language_code']
.Note
A missing language is not the same as
None
. WhileNone
will be replaced by current language and applied tocleaned_data
, a missing language will not apply any language at all.
-
_post_clean
(self)¶ Loads a translation appropriate to the form mode. It is the very same that will be loaded by
save()
. Doing it twice is needed because:- it must be done in
_post_clean
so that the correct translation is available for modifications. For instance, if the view updates some translated fields in between the call tois_valid()
andsave()
, or if a form defines a customsave()
. - it must also be done in
save
to ensure the language is correctly enforced when in enforce mode.
This double check has no cost: unless the instance is changed by the view, the
save()
check will see the translation is correct and do nothing.- it must be done in
-
save
(self, commit=True)¶ Saves both the Shared Model and Translations Model and returns a combined model.
The target language is determined as follows:
- If a language is defined in
cleaned_data
, that language is used. - Else, if the instance has a translation loaded, its language is used.
- Else, the current language is used.
Once the language is determined, the following happen:
- If the object does not exist, it is created.
- If the object exists but not in the target language, its shared fields are updated and a new translation is created.
- If the object exists in the target language, it is updated.
Note
The enforce mode has no direct impact on this method. Rather, it affects the behavior of
clean()
, which places relevant language (or lack thereof) incleaned_data
.- If a language is defined in
-
-
hvad.forms.
translatable_modelform_factory
(language, model, form=TranslatableModelForm, **kwargs)¶ Attaches a language and a model class to the specified form and returns the resulting class. Additional arguments are any arguments accepted by Django’s
modelform_factory()
, includingfields
andexclude
.Having a language attached, the returned form is in enforce mode.
-
hvad.forms.
translatable_modelformset_factory
(language, model, form=TranslatableModelForm, **kwargs)¶ Creates a formset class, allowing edition a collection of instances of
model
, all of them in the specifiedlanguage
. Additional arguments are any argument accepted by Django’smodelformset_factory()
.Having a language attached, the returned formset is in enforce mode.
-
hvad.forms.
translatable_inlineformset_factory
(language, parent_model, model, form=TranslatableModelForm, **kwargs)¶ Creates an inline formset, allowing edition of a collection of instances of
model
attached to an instance ofparent_model
, all of those objects being in the specifiedlanguage
. Additional arguments are any argument accepted by Django’sinlineformset_factory()
.Having a language attached, the returned formset is in enforce mode.
BaseTranslationFormSet¶
-
class
hvad.forms.
BaseTranslationFormSet
(BaseInlineFormSet)¶ -
instance
¶ An instance of a
TranslatableModel
that the formset works on the translations of. Its untranslatable fields will be used while validating and saving the translations.
-
order_translations
(self, qs)¶ Is given a queryset over the Translations Model, that it should alter and return. This is used for adding order_by clause that will define the order in which languages will show up in the formset.
Default implementation orders by language_code. If overriding this method, the default implementation should not be called.
-
clean
(self)¶ Performs translation-specific cleaning of the form. Namely, it combines each form’s translation with
instance
then callsfull_clean()
on the full object.It also ensures the last translation of an object cannot be deleted (unless adding a new translation at the same time).
-
_save_translation
(self, form, commit=True)¶ Saves one of the formset’s forms to the database. It is used by both
save_new()
andsave_existing()
. It works by combining the form’s translation withinstance
’s untranslatable fields, then saving the whole object, triggering any customsave()
method or related signal handlers.
-
save_new
(self, form, commit=True)¶ Saves a new translation. Called from
save()
.
-
save_existing
(self, form, instance, commit=True)¶ Saves an existing, updated translation. Called from
save()
.
-
add_fields
(self, form, index)¶ Adds a language_code field if it is not defined on the translation form.
-