Reputation: 11173
I have a platform with completely different json configs. Any user can create a new json config that is completely different. Hence I cannot model this staticly.
I am trying to make a dynamic form for these json configs.
Some of the json configs have array of values or objects. Visually, I will need these to be a list of inputs with an 'add more' button.
I see that formsets
are the generally accepted way to add arrays of values in django forms. (I'm already using mysql so I can't switch to postgres ArrayField). However from django examples, multiple formsets are initialized separately and passed into the view.
Since my configs are dynamic, I don't know what formsets to initialize and further, the order of fields intermingle between formsets and the form.
For example I am following this link and creating my form classes dynamically like so:
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'])
and in the view:
# 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)
as you can see, the dynamic form is initialized with a config of position
, an array of calendar
elements and a maxSize
field.
My problem is that my dynamic formset is not being shown in the view at all. If I were to separate the formsets, I would somehow have to insert it somewhere inside the original form, so I can't just iterate over the fields, and dynamically create the form
first, then dynamically create formsets
from the array fields.
Hence I am hoping for a way to dynamically create this type of form, where some fields in the form are formsets
.
How do I do this? Or how should I approach this?
Upvotes: 7
Views: 787
Reputation: 134
If you want to save arrays in MySQL you have to do it as JSON, it's the best way to achieve it. Since you want to save a form that the client generates, and probably recover it afterwards, I would do somenthing like:
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)
This way when you call it outside it comes as json already and when u want to save it you pass a json to it.
Upvotes: 1