Search code examples
pythondjangodjango-csrfdjango-file-upload

File upload error & csrf error when Method is post even if {% csrf_token %}


Ok, I know there is many question same to mine, but I didn't find any answer to solve my problem.I am newbie to Django, so please keep in mind.

I need to do a from which will upload a file:

Here is my upload.py(which is a views.py)

from django.http import HttpResponse
def upload(request)
  viewfile = HttpResponse()
  viewfile.write('''
             <html>
             <body>
             <form action="/upload_done/" method="POST" enctype="multipart/form-data" {% csrf_token %}>
                 <label for="file">Filename:</label>
                 <input type="file" name="up_file" >
                  <br />
                  <input type="submit" name="submit" value="Submit" >
             </form>
    return HttpResponse(viewfile)

Now My upload_done.py:

from django.http import HttpResponseRedirect
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.http import HttpResponse
import tempfile
import shutil
def upload_done(request):
  viewfile = HttpResponse()
  #####First I Tried this
  Up_file = request.FILES['up_file']
   """ It gives multivalue error('' 'up_file' '')
  # then I change my upload.py input type file to text & try to collect information
  # and change here Up_file = request.FILES['up_file'] to this
   Up_file = request.POST['up_file']

Now I am getting 403 csrf error From Django doc, Iam not able to understand how templates(only able to understand file.html should be same name as views.py's funcution name) works.

Please assist me how to use post method & how to upload a file.Thanks In advance...

I have tried like this also(write in /home/user/myproject/template/upload_form.html)(Note: template dirctory works properly)

<html>
             <body>
             <form action="/upload_done/" method="POST" enctype="multipart/form-data" {% csrf_token %}>
                 <label for="file">Filename:</label>
                 <input type="file" name="up_file" >
                  <br />
                  <input type="submit" name="submit" value="Submit" >
             </form>

& In above 2nd Views.py(i.e. upload_form.py) replace 'Up_file = request.FILES['up_file']' to this

if request.method == 'POST':
    return render(request, 'upload_form.html',{})

But getting error (must return HttpResponse)


Solution

  • This is how it's supposed to look like:

    upload_form.html:

    <form method="POST" enctype="multipart/form-data" >
    {% csrf_token %}
        {{ form.as_p }}
        <input type="submit" name="submit" value="Submit" >
    </form>
    

    view (based on the example from the docs):

    from django import forms
    class UploadFileForm(forms.Form):
        up_file = forms.FileField()
    
    def handle_uploaded_file(f):
        with open('some/file/name.xls', 'wb+') as destination:
            for chunk in f.chunks():
                destination.write(chunk)
    
    from django.http import HttpResponseRedirect
    from django.shortcuts import render
    def upload(request):
        if request.method == "POST":
            form = UploadFileForm(request.POST, request.FILES)
            if form.is_valid():
                handle_uploaded_file(request.FILES['up_file'])
                return HttpResponseRedirect('/upload_done/')
    
        form = UploadFileForm()
        return render(request, 'upload_form.html', {'form': form})
    

    This is merely a skeleton. There's no data handling, no error handling, nothing regarding the view after redirection. Even if you are under deadline pressure, you wouldn't be able to manipulate this example without some minimal understanding of the framework. So take the time to go over the tutorial. I can't stretch this enough. It's not long, and very detailed.

    edit

    I updated the example to a full file-handling example using the django forms. I find it weird to use a form for handling but then saving the file using a function, but seeing as this is how the documentation does it, I'm not gonna go another way