- TRA-99 Solved. Unable to create a new Tenant Make

- Generic improvement of initialisation of Dynamic Forms, ensuring correct form processing
This commit is contained in:
Josako
2025-11-26 11:31:25 +01:00
parent 0d3c3949de
commit f10bb6f395
4 changed files with 40 additions and 21 deletions

View File

@@ -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 %}
<!-- Render Dynamic Fields -->
{% for collection_name, fields in form.get_dynamic_fields().items() %}
{% if fields|length > 0 %}
<h4 class="mt-4">{{ collection_name }}</h4>
{% endif %}
{% for field in fields %}
{{ render_field(field, disabled_fields, exclude_fields) }}
{% endfor %}
{% endfor %}
<button type="submit" class="btn btn-primary">Register Tenant Make</button>
</form>
{% endblock %}

View File

@@ -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"""

View File

@@ -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)

View File

@@ -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