From eedb90b2d3dc4b5a04344d7d04bce390d85f2d89 Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Mon, 31 Mar 2025 11:40:13 +0200 Subject: [PATCH] Mark fields as required only if parent also required --- src/servala/core/crd.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/servala/core/crd.py b/src/servala/core/crd.py index 8fd20cd..e1ca8d2 100644 --- a/src/servala/core/crd.py +++ b/src/servala/core/crd.py @@ -37,7 +37,7 @@ def generate_django_model(schema, group, version, kind): # resourceRef object spec = schema["properties"].get("spec") or {} spec["properties"].pop("resourceRef", None) - model_fields.update(build_object_fields(spec, "spec")) + model_fields.update(build_object_fields(spec, "spec", parent_required=True)) meta_class = type("Meta", (), {"app_label": "crd_models"}) model_fields["Meta"] = meta_class @@ -48,13 +48,13 @@ def generate_django_model(schema, group, version, kind): return model_class -def build_object_fields(schema, name, verbose_name_prefix=None): +def build_object_fields(schema, name, verbose_name_prefix=None, parent_required=False): required_fields = schema.get("required") or [] properties = schema.get("properties") or {} fields = {} for field_name, field_schema in properties.items(): - is_required = field_name in required_fields + is_required = field_name in required_fields and parent_required full_name = f"{name}.{field_name}" result = get_django_field( field_schema, @@ -85,8 +85,9 @@ def get_django_field( verbose_name_prefix = verbose_name_prefix or "" verbose_name = f"{verbose_name_prefix} {deslugify(field_name)}".strip() + # Pass down the requirement status from parent to child fields kwargs = { - "blank": not is_required, + "blank": not is_required, # All fields are optional by default "null": not is_required, "help_text": field_schema.get("description"), "validators": [], @@ -118,8 +119,12 @@ def get_django_field( elif field_type == "boolean": return models.BooleanField(**kwargs) elif field_type == "object": + # Here we pass down the requirement status to nested objects return build_object_fields( - field_schema, full_name, verbose_name_prefix=f"{verbose_name}:" + field_schema, + full_name, + verbose_name_prefix=f"{verbose_name}:", + parent_required=is_required, ) elif field_type == "array": # TODO: handle items / validate items, build multi-select input @@ -163,6 +168,12 @@ class CrdModelFormMixin: current = current[part] return result + def clean(self): + cleaned_data = super().clean() + # TODO implement custom validation logic + # nested_data = self.get_nested_data() + return cleaned_data + def generate_model_form_class(model): meta_attrs = {