Unable to Render Flask-Admin Edit Form Fields for Variables Stored as JSON
OpenSourceSimon opened this issue ยท 1 comments
Hey GitHub community ๐,
I'm encountering an issue with rendering Flask-Admin edit form fields for variables stored as JSON in a PostgreSQL database. I have a table called variables
where each row represents a variable, and its attributes are stored as JSON in the label
column. I'm using Flask-Admin to provide an interface for users to edit these variables.
This is a simplified version of my database table:
Variable | Value |
---|---|
User1 | {"name": "Name", "email": "test@example.com"} |
Region1 | {"region": "Europe", "name": "DHL", "color": "blue"} |
Here's many of the versions of code I've tried:
import json
from flask_admin.form import BaseForm
from wtforms import StringField
from wtforms.validators import InputRequired
from flask_admin.contrib.sqla import ModelView
class VariableDatabase(db_user.Model):
__tablename__ = "variables"
name = db_user.Column(db_user.Integer, primary_key=True)
label = db_user.Column(db_user.String, nullable=False)
class VariableForm(BaseForm):
def __init__(self, formdata=None, obj=None, prefix='', **kwargs):
super(VariableForm, self).__init__(formdata=formdata, obj=obj, prefix=prefix, **kwargs)
if obj is not None:
try:
print("Label:", obj.label)
value = json.loads(obj.label)
print("Decoded JSON:", value)
for key in value.keys():
field_name = key
field_label = key.capitalize() # Set field label
setattr(self, key, StringField(field_label, validators=[InputRequired()], default=value[key]))
print("Field:", getattr(self, key))
except json.JSONDecodeError as e:
print("JSON Decode Error:", e)
# Just render the form with the default fields
pass
def populate_obj(self, obj):
super(VariableForm, self).populate_obj(obj)
obj.label = json.dumps({field: getattr(self, field).data for field in self._fields})
class VariableView(ModelView):
form = VariableForm
# Register the view
admin.add_view(VariableView(VariableDatabase, db_user.session, name="Variabelen"))
The VariableForm
dynamically creates form fields based on the JSON attributes stored in the label
column of the VariableDatabase
model. However, when I visit the edit page in Flask-Admin, the edit form doesn't render any fields.
I've verified that the form fields are being created correctly in the VariableForm
class, but they are not appearing in the Flask-Admin interface.
Could you please provide guidance on how to resolve this issue? I'd like to ensure that users can edit the variables directly in Flask-Admin without needing knowledge of JSON.
Finally found a solution after months:
Variable = Base.classes.variables
class VariableView(ModelView):
list_columns = ["variable", "value"]
form_columns = ["variable", "value"]
column_default_sort = ("variable", False)
column_filters = ["variable"]
column_sortable_list = ["variable"]
column_searchable_list = ["variable"]
column_formatters = {
"variable": lambda view, context, model, name: model.variable.replace(
"_", " "
).capitalize(),
}
def edit_form(self, obj):
class VariableForm(FlaskForm):
pass
setattr(
VariableForm,
"variable",
StringField("Variable", validators=[Optional()], default=obj.variable),
)
try:
json_data = json.loads(obj.value)
for key in json_data:
setattr(
VariableForm,
key,
StringField(
key.capitalize(),
validators=[Optional()],
default=json_data[key],
),
)
except json.decoder.JSONDecodeError:
setattr(
VariableForm,
"Value",
StringField("Label", validators=[Optional()], default=obj.value),
)
return VariableForm(obj=obj)
def on_model_change(self, form, model, is_created):
# Update the model with the data from the form
json_output = {}
for field in form:
if field.name == "value":
return model
if field.name != "variable" and field.name != "csrf_token":
json_output[field.name] = field.data
model.value = json.dumps(json_output)
return model
admin.add_view(VariableView(Variable, user.session, name="Variables"))