Django在文件上传中引发MultiValueDictKeyError

Dav*_*uez 11 django file-upload

我已经咨询了很多论坛,我无法得到答案.我已经在我的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)
    )
Run Code Online (Sandbox Code Playgroud)

forms.py中的文档格式:

class DocumentForm(forms.ModelForm):
    docfile = forms.FileField(label='Select a file', help_text='max. 42 megabytes')
    class Meta:
    model = Document
Run Code Online (Sandbox Code Playgroud)

models.py中的类文档:

class Document(models.Model):
    docfile = models.FileField(upload_to='documents')
    phase = models.ForeignKey(Phase)
Run Code Online (Sandbox Code Playgroud)

最后,我的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 %}
Run Code Online (Sandbox Code Playgroud)

我的追溯说:

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) 
Run Code Online (Sandbox Code Playgroud)

我的QueryDict是空的:

POST:<QueryDict: {u'csrfmiddlewaretoken': [u'UZSwiLaJ78PqSjwSlh3srGReICzTEWY1']}>
Run Code Online (Sandbox Code Playgroud)

为什么?我究竟做错了什么?

提前致谢.

Ste*_*lim 16

您需要更改multipart/form_datamultipart/form-data-这就是为什么request.FILES是空的:形式是不是在路上送东西的Django预计,由于错字.[编辑:这已经完成]

更新1:此外,不是直接访问request.FILES,而是尝试依赖于modelform的默认行为,因为它将被适当地作为上传处理.也就是说,newdoc = form.save()应该做所有你需要的,从快速查看它 - 是否有一个特殊的原因你手动保存文件时,模型可以为你做到这一点?

更新2:啊,看:您没有为文件上传元素指定名称

来自文档:

HttpRequest.FILES包含所有上传文件的类字典对象.FILES中的每个键都是来自的名称<input type="file" name="" />.FILES中的每个值都是UploadedFile

所以,你需要改变

<input id="file" type="file" />
Run Code Online (Sandbox Code Playgroud)

或者,对于默认的Django约定

<input id="id_docfile" type="file" name="docfile"/>
Run Code Online (Sandbox Code Playgroud)

实际上,使用Django表单渲染实际字段通常会更好,即使您已经超越了整个{{form.as_p}}方法:

{{form.docfile}}
Run Code Online (Sandbox Code Playgroud)

PS.如果你没有完全阅读它,我衷心建议花时间浏览所有表格文档


小智 7

将Post方法修改为

<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
Run Code Online (Sandbox Code Playgroud)