首页 > 编程问答 >通过django admin添加动态字段

通过django admin添加动态字段

时间:2024-07-22 11:14:00浏览次数:6  
标签:python django django-forms django-admin

我环顾了堆栈,但找不到任何答案。 所以我有一个像这样的模型:


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

    def __str__(self):
        return self.config

我现在想要做的是将 json 字段键值对显示为独立字段,并且还能够以相同的方式编辑它们,就像它们每个都是一个不同的领域。这是我能想到的最好的创作方式 dynamic fields 因此,如果我有一个像这样的 jsonfield:

{
    "age": 23, 
    "name": "John Doe",
    "gender": "Male"
}

我将有一个 Age 字段,我可以在其中编辑值,甚至删除该字段。然后更改将反映到 JSONField

我的方法是这样的:


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

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)


# admin.py

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

admin.site.register(DynamicModel, DynamicModelAdmin)

但这似乎并不能解决问题。我得到的结果是,当尝试添加新实例时: enter image description here ,如果我尝试编辑旧实例,它是一样的,但唯一的区别是它显示 def __str__(self) 任何帮助。


你几乎就要成功了!问题出在你的 save 方法中。你正在创建名为 config 的局部变量,而不是更新 self.instance.config

以下是已更正的 save 方法:

    def save(self, *args, **kwargs):
        json_data = self.instance.config or {}
        for key, value in json_data.items():
            # 更新 self.instance.config 而不是创建一个新的局部变量
            self.instance.config[key] = self.cleaned_data.get(key, value)
        return super().save(*args, **kwargs)

通过此更改,你的动态表单字段现在应该可以正确保存到 JSONField

以下是一些额外的技巧:

  • 为了更好地控制每个动态字段的呈现,你可以考虑使用 Fieldset formfield_overrides 在 Django 管理器中对其进行分组。
  • 对于更复杂的情况,你可能希望探索使用 JavaScript 来动态添加和删除表单字段。

祝你好运,编程愉快!

标签:python,django,django-forms,django-admin
From: 78002789

相关文章

  • python中datetime模块
    datetime模块可以更方便的显示日期,并对日期进行计算。datetime模块中常用的类及其功能描述如下:datetime.datetime------>表示日期时间的类(常用)datetime.timedelta------>表示时间间隔的类(常用)datetime.date------>表示日期的类datetime.time------>表示时间的类datetime.......
  • Python - requests
    前言:介绍:安装及验证:使用:连续接口请求:传参方式: 前言:当你上班无聊的时候,你做什么,说实话有人让我写个requests的教程,教程我觉得网上已经有很多教程了,也很全面,我还是不要献丑了介绍:哎,我认为就是一个接口请求的仓库,不过requests属于第三方库,......
  • Python学习计划——2.4列表推导式(List Comprehensions)
    列表推导式是Python的一种简洁且强大的语法,用于生成新的列表。它可以用更少的代码、更清晰的方式来创建列表,特别是在处理简单的循环和条件操作时。1.基本语法列表推导式的基本语法如下:[expressionforiteminiterable]expression:表达式,计算结果用于生成列表的元素。ite......
  • Python学习计划——2.3常用内置函数(len, max, min, sum, etc.)
    Python提供了许多内置函数,用于简化对数据结构的操作。以下是一些常用的内置函数及其详细说明。1.len()len()函数用于返回对象(如列表、元组、字符串、字典等)的长度(元素个数)。示例:#列表fruits=["apple","banana","cherry"]print(len(fruits))#输出:3#元组c......
  • 哪个 Python 框架可以在 Google Collab 中显示和更改图像?
    我希望能够在使用GoogleCollab时为RL绘制高fps的位图。我现在可以使用OpenCV绘制图像cv2_imshowgoogle替换cv2.imshow但是,它无法替换现有图像,它下面绘制了新的我能够在替换imshow函数中使用一些JavaScript来修复它。但刷新率约为......
  • VSCode 自动建议 python 导入而不依赖 Intellisense
    我正在使用Transformer中的AutoModel之类的对象,并且经常遇到自动导入建议无法找到的对象。我总是希望VSCode建议“从Transformer中执行”,而不是费心寻找它找不到的原因每当看到未定义的“AutoModel”时,都会导入AutoModel”,因此无需扫描任何python导入目录。这......
  • 如何使用Python计算位移自相关函数?
    我正在使用python来分析粒子的异常扩散。我已经得到了粒子轨迹的位移,我想计算并绘制位移自相关与滞后时间t的关系。我认为可能存在使用t和位移(如deltar)的自相关函数的一般函数,但我不能没找到。我可以得到函数或代码吗?可以使用numpy和matplotlib库在Python......
  • 一天一点点,第四天Python基础
    第一天:一天一点点。Python基础-CSDN博客第二天:一天一点点,接上章Python基础-CSDN博客第三天:一天一点点,第三天Python基础(循环语句)-CSDN博客推导式推导式是一种独特的数据处理方式,可以从一个数据序列构建另一个新的数据序列的结构体。推导式是一种强大且简洁的语法,适用于生......
  • Python - for循环不使用正则表达式附加数组
    以下代码从URL获取版本号,然后对于每个版本号,转到该版本号的页面并使用文件名的特定模式填充数组。生成的数组应包含每个版本号的文件名列表,但它似乎只包含早期版本(2.6)。使用print语句,我可以看到代码的工作原理是它获取sha256sums.asc文件-所有这些文件,所有版本。我猜......
  • 使用 callable_iterator (re.finditer) 导致 Python 冻结
    我有一个为文本的每一行调用的函数。deftokenize_line(line:str,cmd=''):matches=re.finditer(Patterns.SUPPORTED_TOKENS,line)tokens_found,not_found,start_idx=[],[],0print(matches)formatchinmatches:pass#Rest......