Reputation: 1538
Motivation
I'm currently creating a to-do-list app in django for practice. What I'm trying to do now is to give the "user" the option to submit multiple to-do items at once. To do so, I display the form multiple times and then retrieve the items from each form individually.
Attempt & Error
Here's the form in question:
class AddItemForm(forms.Form):
name = forms.CharField(max_length=60, label='Item Name')
priority = forms.IntegerField(required=False,
widget=forms.Select(choices=Item.PRIORITY))
due_date = forms.DateTimeField(required=False, label='Due Date')
However, when I try to create a form using keyword arguments (the lines of interest are in the for loop):
def add_item(request):
if request.method == 'POST':
r = request.POST
names = r.getlist('name')
priorities = r.getlist('priority')
due_dates = r.getlist('due_date')
for i in xrange(len(names)):
form = AddItemForm(
name=names[i],
priority=priorities[i],
due_date=due_dates[i],
)
if form.is_valid():
item = form.cleaned_data
Item.objects.create(**item)
return HttpResponseRedirect('/todo')
form = AddItemForm()
try:
num_items = xrange(int(request.GET.get('n', 1)))
except ValueError:
num_items = xrange(1)
return render(request, 'add_item.html',
{'form': form, 'num_items': num_items})
I get the following error message:
Exception Type: TypeError
Exception Value:
__init__() got an unexpected keyword argument 'priority'
I don't understand what's going on since I do have priority as a field in AddItemForm.
HTML
Here's the template html if it helps:
<!DOCTYPE html>
<html>
<head> <title>Add item</title> </head>
<body>
<form method="post">{% csrf_token %}
{% for i in num_items %}
<div>{{ form }}</div>
{% endfor %}
<input type="submit">
</form>
<br><br>
<form action="/todo" method="get">
<input type="submit" value="Go back to To-Do List">
</form>
</body>
</html>
Upvotes: 0
Views: 4251
Reputation: 1
Django the form.init() accepts an 'initial' keyword argument, you could have set the initial values of the form in the following way:
form = AddItemForm(initial = {
'name':names[i],
'priority':priorities[i],
'due_date':due_dates[i],
}
)
Upvotes: 0
Reputation: 599956
Well, that's not how forms work. You're not supposed to process the POST arguments first, and you can't pass data for individual fields as arguments like that. You're simply supposed to pass request.POST
into the form instantiation as-is.
The way to do a set of multiple identical forms is to use a formset. You can then pass the POST data straight into the formset instantiation, and get validated forms out.
Note that since your form is being used to create model instances, you may want to consider using a modelform (and a model formset, on the same page).
Upvotes: 1