【问题标题】:django formset within a form / dynamic arrays within forms表单内的 django formset / 表单内的动态数组
【发布时间】:2018-12-24 17:19:26
【问题描述】:

我有一个具有完全不同 json 配置的平台。任何用户都可以创建一个完全不同的新 json 配置。因此,我无法对其进行静态建模。

我正在尝试为这些 json 配置制作动态表单。

一些 json 配置具有值或对象数组。从视觉上看,我需要这些是带有“添加更多”按钮的输入列表。

我看到formsets 是在 django 表单中添加值数组的普遍接受的方式。 (我已经在使用 mysql,所以我无法切换到 postgres ArrayField)。但是从 django 示例中,多个表单集分别初始化并传递到视图中。

由于我的配置是动态的,我不知道要初始化哪些表单集,此外,表单集和表单之间的字段顺序混合在一起。

例如,我正在关注this link 并像这样动态创建我的表单类:

class FieldHandler():
    def __init__(self, fields):
        self.formfields = {}
        for field in fields:
            options = self.get_options(field)
            f = getattr(self, "create_field_for_" +
                        field['type'])(field, options)
            self.formfields[field['name']] = f

    def get_options(self, field):
        options = {}
        options['label'] = field['name']
        options['help_text'] = field.get("help_text", None)
        options['required'] = bool(field.get("required", 0))
        return options

    def create_field_for_text(self, field, options):
        options['max_length'] = int(field.get("max_length", "20"))
        return django.forms.CharField(**options)

    def create_field_for_number(self, field, options):
        options['max_value'] = int(field.get("max_value", "999999999"))
        options['min_value'] = int(field.get("min_value", "-999999999"))
        return django.forms.IntegerField(**options)

    # This does not work, formsets are not shown in the template
    def create_field_for_array(self, field, options):
        fh = FieldHandler(field['elements'])
        form_class = type('DynamicForm',  (django.forms.Form,), fh.formfields)
        DynamicFormSet = formset_factory(form_class)
        return DynamicFormSet(prefix=field['name'])

在视图中:

# arg to FieldHandler is an example config, it will be retrieved from db 
fh = FieldHandler([
    {'type': 'text', 'label': 'position'}, 
    {'type': 'array', 'label': 'calendar', 'elements': [
        {'type': 'text', 'label': 'country'},    
        {'type': 'text', 'label': 'url'},
    ]},
    {'type': 'number', 'label': 'maxSize'}
])
form_class = type('DynamicForm', (django.forms.Form,), fh.formfields)
form = form_class(request.POST or None)

如您所见,动态表单使用position 的配置、calendar 元素的数组和maxSize 字段进行初始化。

我的问题是我的动态表单集根本没有显示在视图中。如果我要分离表单集,我将不得不以某种方式将其插入原始表单中的某个位置,所以我不能只遍历字段,并首先动态创建form,然后从数组动态创建formsets字段。

因此,我希望有一种方法可以动态创建这种类型的表单,其中表单中的某些字段是formsets

我该怎么做?或者我应该如何处理?

【问题讨论】:

  • 如果你想在表单中包含表单集,你将不得不提供一个可以呈现它的模板。作为参考,django-admin 使用(内联)表单集 + 表单来允许在另一个对象的更改页面上编辑相关对象。还找到了this(另请阅读article),这可能对您有所帮助。

标签: django django-forms django-templates


【解决方案1】:

如果您想在 MySQL 中保存数组,您必须将其保存为 JSON,这是实现它的最佳方式。 由于您想保存客户端生成的表单,并可能在之后恢复它,我会做类似的事情:

import json
from django.db import models

class Forms(models.Model):
      _forms = models.TextField(null=True)

    def get_forms(self):
        if self._forms:
            return json.loads(self._forms)
        return []

    def set_forms(self, v):
        if not v:
            v = []
        self._forms = json.dumps(v)

这样,当你在外面调用它时,它已经是 json 了,当你想保存它时,你传递一个 json 给它。

【讨论】:

  • 这不是很友好。我不能只要求用户开始在文本字段中输入 json。
  • 您可以将您的实际表单转换为我相信的 json,和/或尝试调整您的实际代码以仅解析数组字段以将其以这种格式保存在数据库中。
猜你喜欢
  • 2019-11-27
  • 1970-01-01
  • 1970-01-01
  • 2018-09-21
  • 2014-04-09
  • 2019-04-15
  • 2015-11-08
  • 2014-12-07
  • 2012-03-25
相关资源
最近更新 更多