Добавление динамических полей через админку django

Я просмотрел весь стек, но не нашел ответов. Итак, у меня есть такая модель:


class DynamicModel(models.Model):
    config = models.JSONField()

    def __str__(self):
        return self.config

Теперь я хочу отобразить пары ключ-значение json-поля как отдельные поля и иметь возможность редактировать их таким же образом, как если бы каждое из них было отдельным полем. Это был лучший способ, который я смог придумать для создания dynamic fields. Итак, если у меня есть json-поле следующего вида:

{
    "age": 23, 
    "name": "John Doe",
    "gender": "Male"
}
I would have an `Age` field where I can edit the value or even remove the field alotgether. The changes would then reflect to the `JSONField`.

Мой подход таков:

# forms.py
from django import forms
from .models import DynamicModel

class DynamicModelForm(forms.ModelForm):
    class Meta:
        model = DynamicModel
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Check if 'config' is in the fields
        if 'config' in self.fields:
            # Extract JSON data from the instance or initialize an empty dictionary
            json_data = self.instance.config if self.instance and 'config' in self.instance else {}

            # Loop through the JSON data and add individual fields
            for key, value in json_data.items():
                # Add a CharField for each key
                self.fields[key] = forms.CharField(initial=value, required=False)
                self.fields[key].label = key
                self.fields[key].widget.attrs.update({'style': 'display:block;'})

            # Remove the original JSON field
            self.fields.pop('config', None)

    def clean(self):
        cleaned_data = super().clean()
        json_data = cleaned_data.get('config', {})
        
        # Loop through the JSON data and add individual fields
        for key, value in json_data.items():
            cleaned_data[key] = value

        return cleaned_data

# admin.py
from django.contrib import admin
from .models import DynamicModel

class DynamicModelAdmin(admin.ModelAdmin):
    form = DynamicModelForm
    list_display = ['config']

admin.site.register(DynamicModel, DynamicModelAdmin)

но это, похоже, не решает проблему. Любая помощь приветствуется.

Идея заключается в том, чтобы работать с эмти ModelForm, которые затем динамически размещаются:

class DynamicModelForm(forms.ModelForm):
    class Meta:
        model = DynamicModel
        fields = []

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields.pop('config', None)
        json_data = self.instance.config or {}
        for key, value in json_data.items():
            # Add a CharField for each key
            self.fields[key] = forms.CharField(initial=value, required=False)
            self.fields[key].label = key
            self.fields[key].widget.attrs.update({'style': 'display:block;'})

    def save(self, *args, **kwargs):
        json_data = self.instance.config or {}
        cleaned_data = self.cleaned_data
        data = self.cleaned_data
        for key, value in json_data.items():
            config[key] = cleaned_data.get(key, value)
        self.instance.config = config
        return super().save(*args, **kwargs)

Таким образом, мы добавляем поля, более или менее похоже на то, как вы сами это определили. Когда мы захотим сохранить элемент, мы перегруппируем поля в словарь и сохраним его в экземпляре.

Вернуться на верх