request.FILES在文件上传时始终为空

时间:2013-07-17 19:30:14

标签: html django forms file django-forms

我对此完全感到困惑,并且必须做一些非常愚蠢的事情。我想在Django项目上上传一个文件。问题似乎是没有表单数据传递到服务器 - 只有csrf令牌。我在Mac上运行Django 1.5.1,python 2.7,virtualenv,并使用内置的Django开发服务器。

我的HTML表单是:

{% load url from future %}

<form enctype="multipart/form-data" method="POST" action="{% url 'showreport' %}">
    {% csrf_token %}
    <label>Upload grade csv file: </label>
    <input type="hidden" id="testing" value="maybe" />
    <input type="file" id="grade_csv" />
    <input type="submit" value="Generate Report" />
</form>

我的模特:

from django.db import models

class Document(models.Model):
file = models.FileField(upload_to='/media/', blank=True, null=True)

我的forms.py:

from django import forms
from .models import Document

class DocumentForm(forms.Form):
"""
to handle uploading grades csv file
"""
class Meta:
    models = Document

我的views.py:

def report(request):
"""
Process the CSV file to remove inactive students
Manipulate to get right JSON format
Chart the results
"""
if request.method == 'POST':
    form = DocumentForm( request.POST, request.FILES )
    if form.is_valid():
        newfile = Document( file = request.FILES['file'] )
        newfile.save()

        classdata = {}
        studentdata = {}

        return render( request, 'report/showreport.html', { 'classdata': classdata, 'studentdata': studentdata } )
else:
    form = UploadFileForm()

return render( request, 'report/index.html', { 'form': form })

我花了几个小时寻找解决方案,但似乎没有任何效果。 I have the enctype set correctly(我认为),I am using input type 'submit' for the formI am binding the form data to my model(无关紧要,因为request.FILES为空)。我还尝试在每个this Django newbie page的表单操作(action ='/ report / showreport /')中使用直接网址,但这并没有什么区别。据我所知,没有其他脚本绑定到表单提交操作并覆盖默认操作。

我也意识到上面的代码最应该是request.FILES ['grades_csv']来匹配表单的输入id ......但是这也没关系,因为request.FILES是空的。

在尝试调试时,我在我的视图中的if request.method ==“POST”之前设置了一个pdb跟踪。使用控制台,我可以看到我的request.POST不包含我隐藏的“测试”输入,并且该request.FILES为空。当我在浏览器中运行它时,它只是将我返回到我的表单页面,基本上说我的表单无效。我的pdb结果在这里:

(Pdb) request.FILES
(Pdb) <MultiValueDict: {}>
(Pdb) request.POST['testing']
(Pdb) *** MultiValueDictKeyError: "Key 'testing' not found in <QueryDict: {u'csrfmiddlewaretoken': [u'0tGCChxa3Po619dCi114Sb9jmWRt82aj']}>"
(Pdb) request.POST
<QueryDict: {u'csrfmiddlewaretoken': [u'0tGCChxa3Po619dCi114Sb9jmWRt82aj']}>

如果我尝试访问views.py中的request.FILES而不检查表单是否有效,我会收到此错误:

"Key 'file' not found in <MultiValueDict: {}>"

我很难过,并且感谢任何帮助,为什么我不能让它工作 - 看起来应该很简单。我可以使用pdb手动创建和写入项目目录中的文件,所以我不认为权限是问题...问题出在表单中?

3 个答案:

答案 0 :(得分:8)

检查您是否已将enctype属性添加到form代码中。

来自official docs的示例: <form enctype="multipart/form-data" method="post" action="/foo/">

答案 1 :(得分:1)

我也遇到了这个问题,并且对它持续了一段时间的困惑。我的错误是一样的 - 我在input字段上缺少必要的字段。

为了看看实际需要的字段是什么,一个非常好的事情是,在这种情况下:

from base.forms import DocumentForm ## or put whatever the name is of the app, which is unspecified in the question
print DocumentForm()

这将打印您需要的html,包括此对象所需的所有标记。非常简洁的功能,我第一次错过了,但在the docs.

中概述了

答案 2 :(得分:1)

我希望您已经解决了这个问题。 我遇到了完全相同的问题,发现输入标签中没有命名道具

<input type="file" id="grade_csv" />是您的输入。

如果没有名称,django将不会使用它。 因此,添加名称prop即可正常工作。