2
votes

Python: 2.7.11

Django: 1.9

I want to upload a csv file to Django and analyze it with a Python class. No saving is allowed and the file is only needed to reach the class to be analyzed. I'm using Dropzone.js for the form but I don't understand how I should configure/program the views to achieve this.

<form action="/upload/" method="post" enctype="multipart/form-data" class="dropzone" id="dropzone">
    {% csrf_token %}
    <div class="fallback">
        <input name="file" type="file" multiple />
    </div>
</form>

I have found an article about this but it describes saving and is based on Django 1.5.

view.py

def upload(request):
    if request.method == 'POST':
        file = FileUploadForm(request.POST)
        if file.is_valid():
            return HttpResponseRedirect('/upload/')
    else:
        file = FileUploadForm()

    return render(request, 'app/upload.html', {'file': file})

forms.py

from django import forms
class FileUploadForm(forms.Form):
    file = forms.FileField()

Closing Update: The most important difference between the helping answer and my situation is that I had to decode my input. See the following line as mine csv_file in handle_csv_data:

StringIO(content.read().decode('utf-8-sig'))
1
The url in your link is invalid. Is this the article? amatellanes.wordpress.com/2013/11/05/…Håken Lid
@HåkenLid Yeah sorry that's the one. I fixed it in the question.Adrian Z.
What have you tried so far? Can you post your form and view code? And what exactly do you mean by "no saving is allowed".Håken Lid
@HåkenLid I have added the view.py. What I mean by no saving is that the csv file can't be saved to the server, database or anywhere else. The files just needs to be scanned/analyzed by a python class/function. This function extracts all values from the csv and analyzes it. Which means that the file is not needed for anything else than that.Adrian Z.

1 Answers

2
votes

Access the csv file in the view function. If you are using python 3, you must wrap the InMemoryUploadedFile in a TextIOWrapper to parse it with the csv module.

In this example the csv is parsed and passed back as a list named 'content' that will be displayed as a table.

views.py

import csv
import io  # python 3 only

def handle_csv_data(csv_file):
    csv_file = io.TextIOWrapper(csv_file)  # python 3 only
    dialect = csv.Sniffer().sniff(csv_file.read(1024), delimiters=";,")
    csv_file.seek(0)
    reader = csv.reader(csv_file, dialect)
    return list(reader)


def upload_csv(request):
    csv_content=[]
    if request.method == 'POST':
        csv_file = request.FILES['file'].file
        csv_content = handle_csv_data(csv_file)  
    return render(request, 'upload.html', {'content':content})

Your original code did not use django's form framework correctly, so I just dropped that from this example. So you should implement error handling when the uploaded file is invalid or missing.

upload.html

  <form action="/upload/" 
        method="post" 
        enctype="multipart/form-data" 
        class="dropzone" 
        id="dropzone">
    {% csrf_token %}
    <div class="fallback">
      <input name="file" type="file"/>
      <input type="submit"/>
    </div>
  </form>
  {% if content %}
  <table>
  {% for row in content %}
    <tr>
    {% for col in row %}
      <td>{{ col }}</td>
    {% endfor %}
    </tr>
  {% endfor %}
  </table>
  {% endif %}

I've added a 'submit' button so this works without the dropzone thing. I also removed 'multiple' from the file input, to keep the example simple. Finally there's a table if the template receives content from a parsed csv. But when using dropzone.js, you have to use a javascript callback function to display the table.