Reputation: 5074
My current work project requires me to allow for a user to upload files in various formats (currently only dealing with CSV format) and then use the contained data to plot a graph using the Pandas library.
I have decided that the easiest way to render a graph to a template is to make a specific view for the graph and then just link an image to that view from the desired template (e.g. the form page that containing the file upload). I have that working for files with a local path that I hard-coded, but I can't seem to pass the uploaded file to the graph view. I've read that using sessions is the simplest way, but I haven't been successful in my attempts.
The following code is of my file upload form view which gives the following error:
Error #1
InMemoryUploadedFile: sampleCSV.csv (application/vnd.ms-excel) is not JSON serializable
# upload files
@login_required
def list(request):
# handle file upload
if request.method == 'POST':
form = FileUploadForm(request.POST, request.FILES)
if form.is_valid():
newdoc = FileUpload(docFile = request.FILES['docFile'])
newdoc.save();
request.session['docFile'] = request.FILES['docFile']
return HttpResponseRedirect(reverse('list'))
else:
form = FileUploadForm()
# render list page
return render_to_response(
'graphite/list.html',
{ 'form': form },
context_instance=RequestContext(request)
)
And my graph view shown below throws the following error:
Error #2
Expected file path name or file-like object, got class 'NoneType' type
# graph input file
def graph(request):
new_file = request.session.get('docFile')
fig = Figure()
ax = fig.add_subplot(111)
data_df = pd.read_csv(new_file)
data_df = pd.DataFrame(data_df)
data_df.plot(ax=ax)
canvas = FigureCanvas(fig)
response = HttpResponse( content_type = 'image/png')
canvas.print_png(response)
return response
Any ideas on what I am obviously doing wrong or what I can do differently would be greatly appreciated. Thanks.
Per suggestion I tried to store the name of the file and then pass that via the session, but also to no avail. Current error is the same as error listed second above. My implementations are as follows:
class FileUpload(models.Model):
docFile = models.FileField(upload_to='Data_Files', blank=True)
@property
def filename(self):
return os.path.basename(self.docFile.name)
# upload files
@login_required
def list(request):
# handle file upload
if request.method == 'POST':
form = FileUploadForm(request.POST, request.FILES)
if form.is_valid():
newdoc = FileUpload(docFile = request.FILES['docFile'])
newdoc.save();
request.session['docFile'] = newdoc.filename
return HttpResponseRedirect(reverse('list'))
else:
form = FileUploadForm()
# render list page
return render_to_response(
'graphite/list.html',
{ 'form': form },
context_instance=RequestContext(request)
)
# graph input file
def graph(request):
new_file = request.session.get('docFile')
fig = Figure()
ax = fig.add_subplot(111)
data_df = pd.DataFrame.from_csv(new_file)
data_df.plot(ax=ax)
canvas = FigureCanvas(fig)
response = HttpResponse( content_type = 'image/png')
canvas.print_png(response)
return response
Traceback for above error:
Traceback:
File "C:\Python34\lib\site-packages\django-1.7.1-py3.4.egg\django\core\handlers\base.py" in get_response
111. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\vut46744\Desktop\graphite_project\graphite\views.py" in graph
127. data_df = pd.DataFrame.from_csv(new_file)
File "C:\Python34\lib\site-packages\pandas\core\frame.py" in from_csv
1027. infer_datetime_format=infer_datetime_format)
File "C:\Python34\lib\site-packages\pandas\io\parsers.py" in parser_f
465. return _read(filepath_or_buffer, kwds)
File "C:\Python34\lib\site-packages\pandas\io\parsers.py" in _read
241. parser = TextFileReader(filepath_or_buffer, **kwds)
File "C:\Python34\lib\site-packages\pandas\io\parsers.py" in __init__
557. self._make_engine(self.engine)
File "C:\Python34\lib\site-packages\pandas\io\parsers.py" in _make_engine
694. self._engine = CParserWrapper(self.f, **self.options)
File "C:\Python34\lib\site-packages\pandas\io\parsers.py" in __init__
1056. self._reader = _parser.TextReader(src, **kwds)
Upvotes: 4
Views: 3044
Reputation: 1520
Django uses pickle for serialization/ deserialization of session objects.
if you can't refactor your code and adding the response in your list view you might store your files and retrieve them later using python io API.
From the documentation the accepted types for serialization from pickle are:
None, True, and False integers, long integers, floating point numbers, complex numbers normal and Unicode strings tuples, lists, sets, and dictionaries containing only picklable objects functions defined at the top level of a module built-in functions defined at the top level of a module classes that are defined at the top level of a module instances of such classes whose dict or the result of calling getstate() is picklable
Upvotes: 0
Reputation: 3806
I don't think you can put a file
object in session as is not serializable, store its filename and reopen the file in the graph
view
Upvotes: 3