I have an application where I allow importing from CSV files. A list of Libraries are contained in the CSV file. I need to first parse them into a list of Library instances, display them on another page, after user clicks “confirm”, these libraries are saved.
Here is my Form:
class LibCsvForm(forms.Form):
lib_csv = forms.FileField(label='CSV file')
class LibListForm(forms.Form):
def __init__(self, *args, **kwargs):
new_libs = kwargs.pop('new_libs')
super(LibListForm, self).__init__(*args, **kwargs)
self.fields['new_libs'] = new_libs
And my views:
def import_lib_csv(request):
if request.method == 'POST':
form = LibCsvForm(request.POST, request.FILES)
if form.is_valid():
raw = request.FILES['lib_csv'].read()
new_libs = []
# Process string 'raw' and add instances of Library to new_libs
context = RequestContext(request, {'form': LibListForm(new_libs=new_libs)})
context.update(csrf(request))
return render_to_response('master/library.csv.confirm.html', context)
else:
form = LibCsvForm()
variables = RequestContext(request, { 'form': form })
return render_to_response('master/library.csv.html', variables)
A LibCsvForm is just for user to upload a file. Method “import_lib_csv” is to read the file, create instances, and pass them to another form LibListForm, which contains only ‘new_libs’. After the user clicks ‘confirm’, I would like to get this list and save the objects.
The problem is that, in the template:
{{ form.new_libs }}
{% for lib in new_libs %}
{{ lib.id }}
{% endfor %}
It does not show anything. I think I did not pass the ‘new_libs’ into the form properly. Could anybody help? Thanks.
Edit:
Thanks, Rohan. I modified it as you mention. Now the library list can be displayed on in the template. ‘new_libs’ is a list of Library instances.
But when I click “confirm”, it reports error. Here is my method to save:
def save_lib_list(request):
if request.POST:
form = LibListForm(request.POST)
print form.cleaned_data['new_libs']
variables = RequestContext(request, {
'lib_list': Library.objects.all()
})
return render_to_response('master/library.list.html', variables)
Django says
"Exception Type: KeyError
Exception Value: 'new_libs' "
My template is:
<form method="post" action="/library/savelist/" class="well">
{% csrf_token %}
<legend>Libraries to import</legend>
{% for lib in new_libs %}
{{ lib.id }}
{% endfor %}
</form>
I think i miss something here, but not know how to solve…
Solved:
Save the content of uploaded CSV file on the server first. Set the path of this file as a hidden field in the LibListForm:
tmp_lib_file = forms.CharField(widget=forms.HiddenInput(), initial='tmp.lib')
Then when user clicks ‘confirm’, parse the file again and get instances of Library, save them.
You should add the
new_libsin the template context if you want to use it in template.Also, what is the type of
new_libsthat you pass toLibListForm? If its not a proper field type if would not be displayed/processed properly.Update after question edit:
new_fieldskey in theform.cleaned_data. The form should have a field with that name.new_fielddoesn’t seem to be a form field.