I've been stuck on this for over a day now and was hoping I could get some help. I've read a bunch of different SO posts and Django
docs on forms, formsets, bound and unbound forms, but still cant figure this out.
I'm pulling in some data from a model which is a JSONField
. It's a nested mess of dictionary (dict) like so:
dict= {
'A':'data1',
'B': [ {
'one': [
{'x': 'data2', 'y': 'data3', 'z': 'data4'},
{'x': 'data5', 'y': 'data6', 'z': 'data7'},
{'x': 'data8', 'y': 'data9', 'z': 'data10'}
],
'two':'val',
'three': {
'color':'red',
'size':'big',
'order':'new'
},
'four':'someVal',
}],
'C':'moreData'
}
The inner list, one, will have a dynamic amount of dictionaries in it, in this example, there are just 3. The key's for one will always be the same (x, y, and z), but the values will change.
I need to create an editable form, that has each key in it's own charfield with the initial data set as the value.
I've looked into and tried some packages (django-entangled
, django-json-widget
, django-SplitJSONWidget-form
..), but haven't had any luck.
I've tried both bound and unbound forms. The closet I got was taking this approach:
# MODEL:
class myModel(models.Model):
foo = JSONField(blank=True)
# ===========================================================
# FORM:
class oneForm(forms.Form):
A = CharField()
B = CharField()
C = CharField()
class twoForm(forms.Form)
two = CharField()
four = CharField()
# for one(list):
class triForm(forms.Form):
x = charField()
y = charField()
z = charField()
# for three(nested-dict):
class fourForm(forms.Form):
color = CharField()
size = CharField()
order = CharField()
# ===========================================================
# VIEW:
def myView(request,pk):
# getting value of model.Field(JSONField)
obj = myModel.objects.get(pk=pk)
myJson = getattr(obj,'foo')
# Get count of list(one) because it'll dynamically change (this example = 3)
list_count = len(myJson['B'][0]['one'])
# Dynamically populate lines:
one_list = [myJson['B'][0]['one'][i] for i in range(list_count)]
if request.method == "POST":
form = oneForm(initial=myJson) # for first level of dict.
form2 = twoForm(initial=myJson['B'][0]) # for second level of list.
form3 = triForm(initial=one_list) # for one list
form4 = fourForm(initial=myJson['B'][0]['three']) # for three dict.
if form.is_valid():
data = form.save(commit=False)
# Haven't even got around to try and reformat all the data and save it...
data.save()
return HttpResponseRedirect(reverse('blah:home', args=(pk,)))
else:
form = oneForm(initial=myJson) # for first level of dict.
form2 = twoForm(initial=myJson['B'][0]) # for second level of list.
form3 = triForm(initial=one_list) # for one list
form4 = fourForm(initial=myJson['B'][0]['three']) # for three dict.
return render(request, T, {
'form': form,
'form2': form2,
'form3': form3,
'form4': form4,
'range': range(list_count),
})
# ===========================================================
# TEMPLATE:
... some html / form tags
{{ form.as_p }}
{{ form2.as_p }}
{{ form3.as_p }}
{{ form4.as_p }}
... closing tags
This route get's me the correct data fields and initial inputs, although it will not dynamically populate the inner-list (one). It will only display the first dictionary.
x [ data2 ]
y [ data3 ]
z [ data4 ]
... and I tried running it through a {% for x in range %}, but it would just reprint the above 3 times without getting the different values (data 5,6,7,8,9,10).
Any info or tips would help!