From f10bb6f39522ea5b96036d6637f3e068a1e2f3f0 Mon Sep 17 00:00:00 2001 From: Josako Date: Wed, 26 Nov 2025 11:31:25 +0100 Subject: [PATCH] - TRA-99 Solved. Unable to create a new Tenant Make - Generic improvement of initialisation of Dynamic Forms, ensuring correct form processing --- eveai_app/templates/user/tenant_make.html | 11 +------ eveai_app/views/dynamic_form_base.py | 40 +++++++++++++++++++---- eveai_app/views/user_forms.py | 2 +- eveai_app/views/user_views.py | 8 ++--- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/eveai_app/templates/user/tenant_make.html b/eveai_app/templates/user/tenant_make.html index b5c1418..6620f8f 100644 --- a/eveai_app/templates/user/tenant_make.html +++ b/eveai_app/templates/user/tenant_make.html @@ -11,18 +11,9 @@ {{ form.hidden_tag() }} {% set disabled_fields = [] %} {% set exclude_fields = [] %} - {% for field in form.get_static_fields() %} + {% for field in form %} {{ render_field(field, disabled_fields, exclude_fields) }} {% endfor %} - - {% for collection_name, fields in form.get_dynamic_fields().items() %} - {% if fields|length > 0 %} -

{{ collection_name }}

- {% endif %} - {% for field in fields %} - {{ render_field(field, disabled_fields, exclude_fields) }} - {% endfor %} - {% endfor %} {% endblock %} diff --git a/eveai_app/views/dynamic_form_base.py b/eveai_app/views/dynamic_form_base.py index 5d4fbbf..abe8d89 100644 --- a/eveai_app/views/dynamic_form_base.py +++ b/eveai_app/views/dynamic_form_base.py @@ -96,14 +96,42 @@ class OrderedListField(TextAreaField): class DynamicFormBase(FlaskForm): - def __init__(self, formdata=None, *args, **kwargs): - # Belangrijk: formdata doorgeven aan FlaskForm zodat WTForms POST-data kan binden - super(DynamicFormBase, self).__init__(formdata=formdata, *args, **kwargs) + def __init__(self, *args, **kwargs): + """Base class voor dynamische formulieren. + + Belangrijk ontwerpprincipe: + - We laten "normaal" FlaskForm-gedrag intact. Dat betekent dat als een view + geen expliciete ``formdata=`` meegeeft, FlaskForm zelf beslist of en hoe + ``request.form`` wordt gebruikt (inclusief CSRF-handling). + - Als een view wel expliciet ``formdata=`` meegeeft, wordt dat gewoon door de + superklasse afgehandeld. + + Hierdoor hoeven views DynamicFormBase niet anders te behandelen dan een + standaard FlaskForm; dynamische velden zijn een extra laag bovenop het + standaard gedrag. + """ + + # Laat FlaskForm alle standaard initialisatielogica uitvoeren + 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 - self.raw_formdata = request.form.to_dict() + + # Bepaal effectieve formdata voor intern gebruik. + # In de meeste gevallen is dat bij POST gewoon request.form; bij GET is er + # doorgaans geen formdata en vertrouwen we op object-binding en defaults. + if request.method == 'POST': + self.formdata = request.form + # Bewaar een eenvoudige dict-weergave voor hulplogica zoals + # get_dynamic_data (bijvoorbeeld voor BooleanFields) + try: + self.raw_formdata = request.form.to_dict(flat=False) + except TypeError: + # Fallback voor oudere/afwijkende MultiDict-implementaties + self.raw_formdata = request.form.to_dict() + else: + self.formdata = None + self.raw_formdata = {} def _create_field_validators(self, field_def): """Create validators based on field definition""" diff --git a/eveai_app/views/user_forms.py b/eveai_app/views/user_forms.py index f99916d..22b33f8 100644 --- a/eveai_app/views/user_forms.py +++ b/eveai_app/views/user_forms.py @@ -177,7 +177,7 @@ def validate_make_name(form, field): raise ValidationError(f'A Make with name "{field.data}" already exists. Choose another name.') -class TenantMakeForm(DynamicFormBase): +class TenantMakeForm(FlaskForm): name = StringField('Name', validators=[DataRequired(), Length(max=50), validate_make_name]) description = TextAreaField('Description', validators=[Optional()]) active = BooleanField('Active', validators=[Optional()], default=True) diff --git a/eveai_app/views/user_views.py b/eveai_app/views/user_views.py index 3e25fdd..458ee14 100644 --- a/eveai_app/views/user_views.py +++ b/eveai_app/views/user_views.py @@ -594,8 +594,6 @@ def delete_tenant_project(tenant_project_id): @roles_accepted('Super User', 'Partner Admin', 'Tenant Admin') def tenant_make(): form = TenantMakeForm() - customisation_config = cache_manager.customisations_config_cache.get_config("CHAT_CLIENT_CUSTOMISATION") - default_customisation_options = create_default_config_from_type_config(customisation_config["configuration"]) if form.validate_on_submit(): tenant_id = session['tenant']['id'] @@ -612,7 +610,7 @@ def tenant_make(): flash('Tenant Make successfully added!', 'success') current_app.logger.info(f'Tenant Make {new_tenant_make.name}, id {new_tenant_make.id} successfully added ' f'for tenant {tenant_id}!') - # Enable step 2 of creation of retriever - add configuration of the retriever (dependent on type) + # Enable step 2 of creation of make - add configuration of the retriever (dependent on type) return redirect(prefixed_url_for('user_bp.edit_tenant_make', tenant_make_id=new_tenant_make.id, for_redirect=True)) except SQLAlchemyError as e: db.session.rollback() @@ -638,7 +636,9 @@ def edit_tenant_make(tenant_make_id): # Get the tenant make or return 404 tenant_make = TenantMake.query.get_or_404(tenant_make_id) - # Create form instance with the tenant make + # Create form instance with the tenant make. + # Dankzij DynamicFormBase wordt formdata nu op standaard FlaskForm-manier + # afgehandeld en is geen expliciete formdata=request.form meer nodig. form = EditTenantMakeForm(obj=tenant_make) # Initialiseer de allowed_languages selectie met huidige waarden