In this technical article, Studio theYANG introduces an innovative approach to implement ephemeral settings in Django admin interface via a case study of our project. This purely client-side approach eliminates the need of creating database entries and thus provides good performance and maintainability.
Using ephemeral settings is a decent choice for UX purposes when there are too many facets of an instance to be edited. In the latest development of SOCODEVI’s ImpactCoop project, we needed to make it possible for admin users to edit translations in more than 5 languages of Django inline instances on the edit page of the parent instance.
The design choice was to insert a field of checkboxes to allow the user to select the languages that the user wants to edit. For example, if the user checks “French” and “English” and clicks on the “Save” button, the inline objects will only display the text boxes for French and English translations but no other languages.
Intensively involved into the development of this part, Studio theYANG identified following precision that was hidden under the design choice:
- This field of checkboxes for language selection is important for a user’s current session, but is totally unnecessary to be stored into the database as a part of the user profile.
- The update of this field should not interfere with the update of translations. For example, the user may edit some French translations with “French” option checked, but if the user unchecks “French” and checks another language, the edited French translations are expected to be saved; on the other hand, the fact that the browser won’t submit the translations of unchecked languages cannot mean that the server will clear these unsubmitted translations.
- There should be a mechanism for error handling of this field in the case that the user unchecks all languages. The error handling logic cannot interfere with the update of translations.
- The checked language by default is the one chosen by the user in the user profile.
The point 1) indicates that the language selection field is ephemeral and should be stored in user session or cookies. It is all because the language selection will never affect the value of translations stored in the database; it is simply a UI enhancement.
With this basis in mind, Studio theYANG started looking into the injection of this logic into a typical setting of a ModelAdmin with Inlines. Such a ModelAdmin renders the main form and the Inlines separately, and validates and saves them separately.
The first step was undoubtedly to create the data storage layer: hardcoding a unique session key and writing “getter/setter” with parameters request.session and obj (the parent instance under edit). In the getter, a default language of the authenticated user is assigned if the session key points to nothing.
The next step was to render the ephemeral field. This is naturally implemented as an extended field on the Django ModelForm. However, when we provide the initial value of this field, we need to check request object and the instance to be rendered, which are not passed to a typical top-level ModelForm class. Thus we have to construct the form class in get_form method.
The third step was to render the inline instances based on the selected languages. Same as above, we need to build the Inline class in get_inline_instances method to have access to request object and the parent instance to be rendered. Before building the Inline class, we need to construct the ModelForm class for the `Inline` class, where we include or exclude fields according to selected languages.
Through the first three steps, we have completed the rendering, and we now switch to the validation and update. In Django, we need to remember that the ModelAdmin class is instantiated again when submitting a POST request for updating the form. Thus there is a complete procedure of:
- Validate the main form;
- Validate every inline form;
- With all validations passed,
ModelAdminbegins to save the main form and every inline form.
When implementing the update of this ephemeral setting, we need to ensure that the inline forms are instantiated with original value of this setting. Here, Studio theYANG created a working-in-progress session key to hold the updated value between 1) and 3): when the main form is validated, the updated languages are temporarily stored in this working-in-progress session key, which happens in the save method of the main ModelForm. When do we commit this temporary value? It is in save_model method of the ModelAdmin. In this way, we avoid tempering with unsaved instance objects but manage the update of ephemeral settings in a clear manner.
Finally, see it in action:


We hope this case study can shed light on innovative developments of Django admin interface. Please let us know if you are interested in making it happen for your specific needs.
