我已经咨询了很多论坛,我无法得到答案。我已经在我的Django应用程序中安装了文件上传,以便将数据保存到我的服务器中。但它不起作用。相反,它会引发MultiValueDictKeyError。我想问题是没有request.FILES(因为它在request.FILES中提到了一个错误),所以文件上传不起作用。这是我的views.py:
def list_files(request, phase_id):
phase = get_object_or_404(Phase, pk=int(phase_id))
if request.method == 'POST':
#form = DocumentForm(request.POST, request.FILES)
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile = request.FILES['docfile'], phase = phase_id)
newdoc.save()
doc_to_save = request.FILES['docfile']
filename = doc_to_save._get_name()
fd = open(settings.MEDIA_URL+'documents/'+str(filename),'wb')
for chunk in doc_to_save.chunks():
fd.write(chunk)
fd.close()
return HttpResponseRedirect(reverse('list_files'))
else:
form = DocumentForm()
documents = Document.objects.filter(phase=phase_id)
return render_to_response('teams_test/list_files.html',{'documents': documents, 'form':form, 'phase':phase}, context_instance = RequestContext(request)
)
forms.py中的文档表单:
class DocumentForm(forms.ModelForm):
docfile = forms.FileField(label='Select a file', help_text='max. 42 megabytes')
class Meta:
model = Document
models.py中的类文档:
class Document(models.Model):
docfile = models.FileField(upload_to='documents')
phase = models.ForeignKey(Phase)
最后,我的HTML代码:
{% extends "layouts/app.html" %}
{% load i18n user %}
{% block title %}{% trans "Files list" %}{% endblock %}
{% block robots %}noindex,nofollow{% endblock %}
{% block page%}
<div id="page" class="container">
<div class="header prepend-2 span-20 append-2 last whiteboard">
<h2 style="margin-left:-40px">{{ phase.name }} files</h2>
{% if documents %}
<ul>
{% for document in documents %}
<li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}
<form action="{% url list_files phase.id %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input id="file" type="file" />
<input id="submit" type="submit" value="Upload file" />
</form>
</div>
</div>
{% endblock %}
我的追溯说:
Exception Type: MultiValueDictKeyError
Exception Value: "Key 'docfile' not found in <MultiValueDict: {}>"
my_dir/views.py in list_files
newdoc = Document(docfile = request.FILES['docfile'], phase = phase_id)
我的QueryDict是空的:
POST:<QueryDict: {u'csrfmiddlewaretoken': [u'UZSwiLaJ78PqSjwSlh3srGReICzTEWY1']}>
为什么呢?我究竟做错了什么?
提前致谢。
答案 0 :(得分:14)
您需要将multipart/form_data
更改为multipart/form-data
- 这就是request.FILES
为空的原因:表单不会像Django所期望的那样发送内容错字。 [编辑:现在已经完成了]
更新1:此外,不是直接访问request.FILES,而是尝试依赖于模型形式的默认行为,因为它已被适当地作为上传处理。也就是说,newdoc = form.save()
应该做你需要的所有东西,快速查看一下 - 当模型可以为你做这件事时,你手动保存文件有什么特别的原因吗?
更新2:啊,看:您没有为文件上传元素指定名称
来自文档:
HttpRequest.FILES包含所有上传文件的类字典对象。 FILES中的每个键都是
<input type="file" name="" />
中的名称。 FILES中的每个值都是UploadedFile
所以,你需要改变
<input id="file" type="file" />
要
或者,对于默认的Django约定
<input id="id_docfile" type="file" name="docfile"/>
实际上,即使您已超越整个{{form.as_p}}
方法,使用Django表单渲染实际字段通常会更好:
{{form.docfile}}
PS。如果您还没有完整阅读,我衷心建议您花时间浏览所有forms documentation
答案 1 :(得分:5)
将Post方法修改为
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
答案 2 :(得分:0)
对于已经尝试了上述方法但仍然找不到解决方案的人来说。这是我所做的:
views.py
if request.method == 'POST':
doc = request.FILES #returns a dict-like object
doc_name = doc['filename']
...
答案 3 :(得分:0)
对于尝试过上述方法但仍然无法找到解决方案的任何人。这是我所做的(第二部分):
if request.method == 'POST' and 'filename' in request.FILES:
doc = request.FILES #returns a dict-like object
doc_name = doc['filename']
...