Django поднимает MultiValueDictKeyError в загрузке файлов

Я уже консультировался со многими форумами, и я не могу получить ответ. Я установил загрузку файла в приложение Django для сохранения данных на моем сервере. Но это не работает. Вместо этого он поднимает MultiValueDictKeyError. Я думаю, проблема в том, что нет запроса.Файлы (потому что это вызывает ошибку в запросе.Файлы упоминаются), поэтому загрузка файла не работает. Это мой 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']}>

почему? Что я делаю не так?

спасибо заранее.

2 ответов


вам нужно изменить multipart/form_data to multipart/form-data - это почему request.FILES пусто: форма не отправляет вещи так, как ожидает Django из-за опечатки. [EDIT: это уже сделано]

Update 1: Кроме того, вместо прямого запроса доступа.Файлы, попробуйте полагаться на поведение modelform по умолчанию, так как тогда он будет обработан как загрузка соответствующим образом. ie,newdoc = form.save() должен делать все, что вам нужно, от быстрого взгляда на него - есть ли особая причина, по которой вы вручную сохраняете файл, когда modelform может сделать это для вас?

Update 2: Ах, посмотрите: вы не назначаете имя для элемента загрузки файла

документы:

HttpRequest.Файлы словарный объект, содержащий все загруженные файлы. Каждый ключ в файлах-это имя из <input type="file" name="" />. Каждое значение в файлах-это UploadedFile

Итак, вам нужно изменить

<input id="file" type="file" />

в

или по умолчанию Конвенция Джанго

<input id="id_docfile" type="file" name="docfile"/>

действительно, обычно лучше использовать форму Django для рендеринга фактического поля, даже если вы перешли за пределы целого {{form.as_p}} подход:

{{form.docfile}}

PS. если вы не прочитали их полностью, я сердечно рекомендую потратить время, чтобы пройти через все формы документации


изменить метод Post на

<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}