Skip to content

Commit

Permalink
Add support for frozen fields
Browse files Browse the repository at this point in the history
This adds to new fields to the BaseModelView: `allow_frozen_fields` and
`excluded_frozen_fields`. Setting `allow_frozen_fields` to True adds
another button to the create and the edit view which acts like
"Save and Add Another", but "freezes" the fields (i.e.,
doesn't reset their contents).

`excluded_frozen_fields` can be used to specify fields
which should always be cleared (e.g., password fields).
  • Loading branch information
falko17 committed May 11, 2021
1 parent 829c8e7 commit b7243d4
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 2 deletions.
4 changes: 4 additions & 0 deletions doc/api/mod_model.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
form_widget_args, form_extra_fields,
form_ajax_refs, form_create_rules,
form_edit_rules,
allow_frozen_fields, exclude_frozen_fields
page_size, can_set_page_size

.. autoattribute:: can_create
Expand Down Expand Up @@ -55,6 +56,9 @@
.. autoattribute:: form_create_rules
.. autoattribute:: form_edit_rules

.. autoattribute:: allow_frozen_fields
.. autoattribute:: exclude_frozen_fields

.. autoattribute:: action_disallowed_list

.. autoattribute:: page_size
Expand Down
56 changes: 54 additions & 2 deletions flask_admin/model/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import csv
import mimetypes
import time
from typing import Optional, cast, Type
from typing import Optional, cast, Type, List

from math import ceil
import inspect
Expand Down Expand Up @@ -749,6 +749,31 @@ class MyModelView(ModelView):
Customized rules for the create form. Override `form_rules` if present.
"""

allow_frozen_fields = False
"""
If true, renders an additional button in the create and edit form which
acts like "Save and Add Another", but keeps ("freezes") field contents
instead of clearing them.
Fields in `excluded_frozen_fields` will never be frozen.
"""

excluded_frozen_fields: List[str] = []
"""
If `allow_frozen_fields` is set to `True` and the user clicks on
the corresponding button, only fields whose name is not included
in this list will be frozen.
In other words, add any fields here which shall be cleared even if the user
clicks on "Save And Add Another (Freeze Fields)", such as password fields.
Example::
class MyModelView(BaseModelView):
excluded_frozen_fields = ('password', 'confirm_password')
"""

# Actions
action_disallowed_list = ObsoleteAttr('action_disallowed_list',
'disallowed_actions',
Expand Down Expand Up @@ -871,6 +896,10 @@ def _refresh_forms_cache(self):
else:
self.column_editable_list = {}

# Initialize frozen fields
if not hasattr(self, "_frozen_id"):
self._frozen_id = None

def _refresh_filters_cache(self):
self._filters = self.get_filters()

Expand Down Expand Up @@ -2124,10 +2153,22 @@ def create_view(self):
if not self.can_create:
return redirect(return_url)

form = self.create_form()
# handle frozen fields, coming from an edit form
existing_model = None
if self._frozen_id:
existing_model = self.get_one(self._frozen_id)
self._frozen_id = None

form = self.create_form(obj=existing_model)
if not hasattr(form, '_validated_ruleset') or not form._validated_ruleset:
self._validate_form_instance(ruleset=self._form_create_rules, form=form)

if existing_model is not None:
# we need to reset excluded frozen fields here.
for field in self.excluded_frozen_fields:
if field in form.data:
getattr(form, field).data = ""

if self.validate_form(form):
# in versions 1.1.0 and before, this returns a boolean
# in later versions, this is the model itself
Expand All @@ -2136,6 +2177,14 @@ def create_view(self):
flash(gettext('Record was successfully created.'), 'success')
if '_add_another' in request.form:
return redirect(request.url)
elif '_freeze_fields' in request.form and self.allow_frozen_fields:
# we need to do is reset the excluded fields and then persist
# the frozen fields.
for field in self.excluded_frozen_fields:
if field in form.data:
getattr(form, field).data = ""
self._frozen_id = self.get_pk_value(model)
return redirect(request.url)
elif '_continue_editing' in request.form:
# if we have a valid model, try to go to the edit view
if model is not True:
Expand Down Expand Up @@ -2189,6 +2238,9 @@ def edit_view(self):
flash(gettext('Record was successfully saved.'), 'success')
if '_add_another' in request.form:
return redirect(self.get_url('.create_view', url=return_url))
elif '_freeze_fields' in request.form and self.allow_frozen_fields:
self._frozen_id = self.get_pk_value(model)
return redirect(self.get_url('.create_view', url=return_url))
elif '_continue_editing' in request.form:
return redirect(self.get_url('.edit_view', id=self.get_pk_value(model)))
else:
Expand Down
3 changes: 3 additions & 0 deletions flask_admin/templates/bootstrap4/admin/lib.html
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ <h3>{{ text }}</h3>
{% if admin_view.can_create %}
<input name="_add_another" type="submit" class="btn btn-secondary" value="{{ _gettext('Save and Add Another') }}" />
{% endif %}
{% if admin_view.can_create and admin_view.allow_frozen_fields %}
<input name="_freeze_fields" type="submit" class="btn btn-secondary" value="{{ _gettext('Save and Add Another (Freeze Fields)') }}" />
{% endif %}
{% if admin_view.can_edit %}
<input name="_continue_editing" type="submit" class="btn btn-secondary" value="{{ _gettext('Save and Continue Editing') }}" />
{% endif %}
Expand Down
Binary file modified flask_admin/translations/de/LC_MESSAGES/admin.mo
Binary file not shown.
5 changes: 5 additions & 0 deletions flask_admin/translations/de/LC_MESSAGES/admin.po
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,11 @@ msgstr "Abbrechen"
msgid "Save and Add Another"
msgstr "Speichern und neuer Eintrag"

#: ../flask_admin/templates/bootstrap2/admin/lib.html:263
#: ../flask_admin/templates/bootstrap3/admin/lib.html:254
msgid "Save and Add Another (Freeze Fields)"
msgstr "Speichern und neuer Eintrag (Felder einfrieren)"

#: ../flask_admin/templates/bootstrap2/admin/lib.html:259
#: ../flask_admin/templates/bootstrap3/admin/lib.html:250
msgid "Save and Continue Editing"
Expand Down

0 comments on commit b7243d4

Please sign in to comment.