You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

86 lines
2.4 KiB

import json
from typing import Any, Optional
from django import forms
from django.db import models
from django.utils.safestring import mark_safe
from django.forms import MultiWidget, Widget
JSON_EDITOR_CLASSES = [
"border",
"border-base-200",
"rounded",
"group-[.errors]:border-red-600",
"w-full",
"dark:border-base-700",
"dark:group-[.errors]:border-red-500",
]
class JsonEditorWidget(Widget):
template_name = 'account/json_editor_field.html'
class Media:
css = {
'all': ('https://cdn.jsdelivr.net/npm/@json-editor/json-editor@latest/dist/css/jsoneditor.min.css',)
}
js = ('https://cdn.jsdelivr.net/npm/@json-editor/json-editor@latest/dist/jsoneditor.min.js',)
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
if attrs is None:
attrs = {}
# Set default title if not provided
if 'title' not in attrs and 'label' in attrs:
attrs['title'] = attrs['label']
elif 'title' not in attrs:
attrs['title'] = 'JSON Editor'
super().__init__(attrs)
self.attrs.update({
'class': ' '.join(JSON_EDITOR_CLASSES),
})
def render(self, name, value, attrs=None, renderer=None):
if value is None:
value = '{}'
elif isinstance(value, dict):
value = json.dumps(value)
attrs = self.build_attrs(self.attrs, attrs)
attrs['name'] = name
# Ensure the schema is properly passed to the template
if 'schema' in self.attrs:
attrs['schema'] = self.attrs['schema']
# Pass field name as title if not set
if 'title' not in attrs:
attrs['title'] = name.replace('_', ' ').title()
return super().render(name, value, attrs, renderer)
class JsonEditorField(models.JSONField):
schema = {}
def __init__(self, *args, schema: dict, **kwargs):
self.schema = schema
super().__init__(*args, **kwargs)
def formfield(self, **kwargs):
schema = self.schema() if callable(self.schema) else self.schema
kwargs.update({
'widget': JsonEditorWidget(attrs={'schema': json.dumps(schema)}),
})
return super(JsonEditorField, self).formfield(**kwargs)
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
kwargs['schema'] = self.schema
return name, path, args, kwargs