Reputation: 5057
I have a model form in which I need to store an unknown number of helpers alongside a thing. The names can be serialised upon save, and that's not a problem. It's being able to clean and validate them upon submission.
The form looks like;
class ThingForm(forms.ModelForm):
"""
Form for the Thing
"""
owner = forms.CharField()
helpers = forms.CharField()
class Meta:
model = Thing
def save(self, *args, **kwargs):
"""
Serialize helpers to JSON.
"""
...
And the model is using a JSONField to store the serialised helpers.
class Thing(models.Model):
owner = models.CharField()
helpers = JSONField()
I have JavaScript adding as many helpers as required with the same input name:
<input name="helpers" value="Fred" />
<input name="helpers" value="Joe" />
Which is returning a tuple of the helpers. The problem is that the if the form isn't valid - those names will be lost and the cleaning isn't working.
My first thought was to add to the form's constructor:
def __init__(self, *args, **kwargs):
super(ThingForm, self).__init__(*args, **kwargs)
try:
helpers = args[0].pop('helpers')
for name in helpers:
# Add a charfield, or something?
except:
pass
But I'm not really getting anywhere...
Upvotes: 3
Views: 1510
Reputation: 493
We had a similar problem and found no ready solution. So we did ours (https://github.com/vialink/vlk-django-jsonfield).
Upvotes: 0
Reputation: 5057
Thanks to AdamKG for the answer to this. You can just use the list in your view again:
View:
if request.method == 'POST':
helpers = request.POST.getlist('helpers')
form = ThingForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/saved/')
else:
helpers = None
form = ThingForm()
return render_to_response('my_template.html',
{'helpers': helpers, 'form': form},
context_instance=RequestContext(request))
Template:
{% for field in form %}
{% if field.name == 'helpers' %}
{% for name in helpers %}
<input name="helpers" value="{{ name }}" />
{% endfor %}
{% else %}
{{ field }}
{% endif %}
{% endfor %}
Upvotes: 1
Reputation: 14081
I think all you need to do is do something like this in your template:
{% if form.data %}{# eg, was invalid and this is a re-render w/ errors #}
{% for helper in form.data.helpers %}
<input type="hidden" name="helpers" value="{{ helper }}">
{% endfor %}
{% endif %}
Note that this will break if you start passing a prefix
kwarg to your form - but so would your original code, fixing that is a separate issue :)
Upvotes: 0