schon/core/widgets.py

51 lines
1.7 KiB
Python

import json
from typing import Any, Mapping
from django import forms
from django.core.files.uploadedfile import UploadedFile
from django.forms.renderers import BaseRenderer
from django.utils.datastructures import MultiValueDict
from django.utils.safestring import SafeString
class JSONTableWidget(forms.Widget):
template_name = "json_table_widget.html"
def format_value(self, value: str | dict[str, Any]) -> str | dict[str, Any]: # type: ignore [override]
if isinstance(value, dict):
return value
try:
if isinstance(value, str):
value = json.loads(value)
except json.JSONDecodeError:
value = {}
return value
def render(
self,
name: str,
value: str | dict[str, Any],
attrs: dict[str, Any] | None = None,
renderer: BaseRenderer | None = None,
) -> SafeString:
value = self.format_value(value)
return super().render(name, value, attrs, renderer)
def value_from_datadict(
self, data: Mapping[str, Any], files: MultiValueDict[str, UploadedFile], name: str
) -> str | None:
json_data = {}
try:
keys = data.getlist(f"{name}_key") # type: ignore [attr-defined]
values = data.getlist(f"{name}_value") # type: ignore [attr-defined]
for key, value in zip(keys, values, strict=True):
if key.strip():
try:
json_data[key] = json.loads(value)
except (json.JSONDecodeError, ValueError):
json_data[key] = value
except TypeError:
pass
return None if not json_data else json.dumps(json_data)