alacy
alacy

Reputation: 5074

Passing a file from one view to another in Django using sessions

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.


EDIT

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:

Models.py

class FileUpload(models.Model):
    docFile = models.FileField(upload_to='Data_Files', blank=True)

    @property
    def filename(self):
        return os.path.basename(self.docFile.name)

File upload view

# 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 View

# 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

Answers (2)

Riccardo
Riccardo

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

sax
sax

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

Related Questions