From fc6d41fdb3df17b0c7c58c2d461e3a3af12bd096 Mon Sep 17 00:00:00 2001 From: Yurchenko Sergey Date: Sat, 12 Feb 2022 04:49:08 +0300 Subject: [PATCH] serialize_according_to_widget (#472) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Сергей Юрченко --- constance/admin.py | 16 +++++++++++++--- example/cheeseshop/fields.py | 24 ++++++++++++++++++++++++ example/cheeseshop/settings.py | 6 ++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 example/cheeseshop/fields.py diff --git a/constance/admin.py b/constance/admin.py index 48f516e..0710edd 100644 --- a/constance/admin.py +++ b/constance/admin.py @@ -202,11 +202,16 @@ class ConstanceAdmin(admin.ModelAdmin): def get_config_value(self, name, options, form, initial): default, help_text = options[0], options[1] + field_type = None + if len(options) == 3: + field_type = options[2] # First try to load the value from the actual backend value = initial.get(name) # Then if the returned value is None, get the default if value is None: value = getattr(config, name) + + form_field = form[name] config_value = { 'name': name, 'default': localize(default), @@ -214,12 +219,17 @@ class ConstanceAdmin(admin.ModelAdmin): 'help_text': _(help_text), 'value': localize(value), 'modified': localize(value) != localize(default), - 'form_field': form[name], + 'form_field': form_field, 'is_date': isinstance(default, date), 'is_datetime': isinstance(default, datetime), - 'is_checkbox': isinstance(form[name].field.widget, forms.CheckboxInput), - 'is_file': isinstance(form[name].field.widget, forms.FileInput), + 'is_checkbox': isinstance(form_field.field.widget, forms.CheckboxInput), + 'is_file': isinstance(form_field.field.widget, forms.FileInput), } + if field_type and field_type in settings.ADDITIONAL_FIELDS: + serialized_default = form[name].field.prepare_value(default) + config_value['default'] = serialized_default + config_value['raw_default'] = serialized_default + config_value['value'] = form[name].field.prepare_value(value) return config_value diff --git a/example/cheeseshop/fields.py b/example/cheeseshop/fields.py new file mode 100644 index 0000000..c61d2f6 --- /dev/null +++ b/example/cheeseshop/fields.py @@ -0,0 +1,24 @@ +import json +from django.forms import fields, widgets + + +class JsonField(fields.CharField): + widget = widgets.Textarea + + def __init__(self, rows: int = 5, **kwargs): + self.rows = rows + super().__init__(**kwargs) + + def widget_attrs(self, widget: widgets.Widget): + attrs = super().widget_attrs(widget) + attrs['rows'] = self.rows + return attrs + + def to_python(self, value): + if value: + return json.loads(value) + else: + return {} + + def prepare_value(self, value): + return json.dumps(value) diff --git a/example/cheeseshop/settings.py b/example/cheeseshop/settings.py index 6a88a85..76308e6 100644 --- a/example/cheeseshop/settings.py +++ b/example/cheeseshop/settings.py @@ -102,6 +102,7 @@ CONSTANCE_ADDITIONAL_FIELDS = { } ], 'email': ('django.forms.fields.EmailField',), + 'json_field': ['cheeseshop.fields.JsonField'] } CONSTANCE_CONFIG = { @@ -112,6 +113,11 @@ CONSTANCE_CONFIG = { 'DATE_ESTABLISHED': (date(1972, 11, 30), "the shop's first opening"), 'MY_SELECT_KEY': ('yes', 'select yes or no', 'yes_no_null_select'), 'MULTILINE': ('Line one\nLine two', 'multiline string'), + 'JSON_DATA': ( + {'a': 1_000, 'b': 'test', 'max': 30_000_000}, + 'Some test data for json', + 'json_field', + ), } CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'