From 9b5f52035d5aa3877b75f6cb1a07e0869d82a9ea Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 15 Dec 2025 20:41:26 +0000 Subject: [PATCH] Enhance JSON parsing and normalization in WorkerForm to handle various input types --- djangorota/rota/forms.py | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/djangorota/rota/forms.py b/djangorota/rota/forms.py index 72eb453..129aa92 100644 --- a/djangorota/rota/forms.py +++ b/djangorota/rota/forms.py @@ -168,11 +168,40 @@ class WorkerForm(forms.ModelForm): if val is None or val == "": opts[k] = [] else: - try: - parsed = json.loads(val) - except Exception: + # If the cleaned value is a JSON string, parse it. If + # it's already a Python structure (possibly containing + # pydantic models from `clean()`), keep it but normalize + # any model instances into serializable dicts. + if isinstance(val, str): + try: + parsed = json.loads(val) + except Exception: + parsed = val + else: parsed = val - opts[k] = parsed + + def _normalize(obj): + # Normalize pydantic BaseModel instances (v2:v1) + if hasattr(obj, "model_dump"): + try: + return obj.model_dump() + except Exception: + pass + if hasattr(obj, "dict") and not isinstance(obj, dict): + try: + return obj.dict() + except Exception: + pass + # Recurse lists/tuples + if isinstance(obj, list): + return [_normalize(i) for i in obj] + if isinstance(obj, tuple): + return [_normalize(i) for i in obj] + if isinstance(obj, dict): + return {k: _normalize(v) for k, v in obj.items()} + return obj + + opts[k] = _normalize(parsed) instance.options = opts if commit: