- Introduction of retrievers - Ensuring processing information is collected from Catalog iso Tenant - Introduction of a generic Form class to enable dynamic fields based on a configuration - Realisation of Retriever functionality to support dynamic fields
93 lines
3.9 KiB
Python
93 lines
3.9 KiB
Python
from flask_wtf import FlaskForm
|
|
from wtforms import IntegerField, FloatField, BooleanField, StringField, validators
|
|
from flask import current_app
|
|
|
|
class DynamicFormBase(FlaskForm):
|
|
def __init__(self, formdata=None, *args, **kwargs):
|
|
super(DynamicFormBase, self).__init__(*args, **kwargs)
|
|
# Maps collection names to lists of field names
|
|
self.dynamic_fields = {}
|
|
# Store formdata for later use
|
|
self.formdata = formdata
|
|
|
|
def add_dynamic_fields(self, collection_name, config, initial_data=None):
|
|
"""Add dynamic fields to the form based on the configuration."""
|
|
self.dynamic_fields[collection_name] = []
|
|
for field_name, field_def in config.items():
|
|
current_app.logger.debug(f"{field_name}: {field_def}")
|
|
# Prefix the field name with the collection name
|
|
full_field_name = f"{collection_name}_{field_name}"
|
|
field_type = field_def.get('type')
|
|
description = field_def.get('description', '')
|
|
required = field_def.get('required', False)
|
|
default = field_def.get('default')
|
|
|
|
# Determine validators
|
|
field_validators = [validators.InputRequired()] if required else [validators.Optional()]
|
|
|
|
# Map the field type to WTForms field classes
|
|
field_class = {
|
|
'int': IntegerField,
|
|
'float': FloatField,
|
|
'boolean': BooleanField,
|
|
'string': StringField,
|
|
}.get(field_type, StringField)
|
|
|
|
# Create the field instance
|
|
unbound_field = field_class(
|
|
label=description,
|
|
validators=field_validators,
|
|
default=default
|
|
)
|
|
|
|
# Bind the field to the form
|
|
bound_field = unbound_field.bind(form=self, name=full_field_name)
|
|
|
|
# Process the field with formdata
|
|
if self.formdata and full_field_name in self.formdata:
|
|
# If formdata is available and contains the field
|
|
bound_field.process(self.formdata)
|
|
elif initial_data and field_name in initial_data:
|
|
# Use initial data if provided
|
|
bound_field.process(formdata=None, data=initial_data[field_name])
|
|
else:
|
|
# Use default value
|
|
bound_field.process(formdata=None, data=default)
|
|
|
|
# Set collection name attribute for identification
|
|
# bound_field.collection_name = collection_name
|
|
|
|
# Add the field to the form
|
|
setattr(self, full_field_name, bound_field)
|
|
self._fields[full_field_name] = bound_field
|
|
self.dynamic_fields[collection_name].append(full_field_name)
|
|
|
|
def get_static_fields(self):
|
|
"""Return a list of static field instances."""
|
|
# Get names of dynamic fields
|
|
dynamic_field_names = set()
|
|
for field_list in self.dynamic_fields.values():
|
|
dynamic_field_names.update(field_list)
|
|
|
|
# Return all fields that are not dynamic
|
|
return [field for name, field in self._fields.items() if name not in dynamic_field_names]
|
|
|
|
def get_dynamic_fields(self):
|
|
"""Return a dictionary of dynamic fields per collection."""
|
|
result = {}
|
|
for collection_name, field_names in self.dynamic_fields.items():
|
|
result[collection_name] = [getattr(self, name) for name in field_names]
|
|
return result
|
|
|
|
def get_dynamic_data(self, collection_name):
|
|
"""Retrieve the data from dynamic fields of a specific collection."""
|
|
data = {}
|
|
if collection_name not in self.dynamic_fields:
|
|
return data
|
|
prefix_length = len(collection_name) + 1 # +1 for the underscore
|
|
for full_field_name in self.dynamic_fields[collection_name]:
|
|
original_field_name = full_field_name[prefix_length:]
|
|
field = getattr(self, full_field_name)
|
|
data[original_field_name] = field.data
|
|
return data
|