request.FILES 在文件上传时始终为空
Posted
技术标签:
【中文标题】request.FILES 在文件上传时始终为空【英文标题】:request.FILES always empty on file upload 【发布时间】:2013-07-16 12:40:16 【问题描述】:我对此完全感到困惑,并且一定在做一些非常愚蠢的事情。我正在尝试简单地在 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
我的意见.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 form 和 I am binding the form data to my model(没关系,因为 request.FILES 为空)。我还尝试在每个this Django newbie page 的表单操作(action='/report/showreport/')中使用直接 url,但这并没有什么不同。据我所知,没有其他脚本绑定到表单提交操作并覆盖默认操作。
我也意识到上面的代码最可能是 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 在我的项目目录中手动创建和写入文件,所以我认为权限不是问题...问题出在表单中?
【问题讨论】:
看起来您的 html 表单缺少输入字段中的名称属性,请尝试像 一些对我来说很可疑的事情。您的表单输入缺少name
属性。您正在对forms.Form
进行子类化,但有一个Meta
类表明您想要forms.ModelForm
。如果您打算使用模型表单,则不需要实例化 Document 对象,因为该表单会为您执行此操作。
天才——谢谢!如果您将其作为一个提交,我很乐意接受作为答案...
几乎可以肯定是缺少name
属性。这就是 POST 数据的密钥的来源,而不是 ID。
name 属性修复了它...不确定我是否完全理解 Scott 关于模型表单的评论(我试图遵循 Django example on forms)。这是否意味着我不需要 class Meta: 标签?
【参考方案1】:
检查您是否已将enctype
属性添加到form
标记中。
来自official docs 的示例:
<form enctype="multipart/form-data" method="post" action="/foo/">
【讨论】:
完美解决方案。 enctype="multipart/form-data" 对我有用。真的很有帮助。谢谢@Kuznetsov【参考方案2】:我希望你已经解决了这个问题。 我遇到了完全相同的问题,我发现输入标签中没有名称道具
<input type="file" id="grade_csv" />
这是您的输入。
如果它没有名字,django 不会接受它。 所以添加 name 属性就可以了。
【讨论】:
【参考方案3】:我也有这个问题,困惑了一段时间。我的错误是一样的——我在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.中进行了概述
【讨论】:
你能举个例子吗?【参考方案4】:我刚刚遇到一个奇怪的错误,当我打印出来时它显示为空:
print(request.FILES)
# Prints <MultiValueDict: >
如果我加载调试器并实际检查对象,它不是空的并且包含我期望的数据。这在两种情况下都是同一个对象。调试器将FILES
显示为已填充,然后当我继续时,print
将其显示为空。
所以,如果你像我一样想先戳对象以了解它,也许不要依赖MultiValueDict
的字符串表示。我无法解释错误的来源,因为MultiValueDict
只是dict
的子类并使用dict
的__str__
。
【讨论】:
以上是关于request.FILES 在文件上传时始终为空的主要内容,如果未能解决你的问题,请参考以下文章