MultipleFileField returns no data

My goal is to allow registered users to upload files (numbering the hundreds) to a staging area, after passing through Django authentication and selecting the target directory using a identifier registered to them that is used to look up the target in a db table. While I’m not convinced that the multiple file uploader is the best way to go, as I’d prefer the clients to be non-interactive (i.e., run from cron), I thought I’d start this way…

From the Django documentation, I created the form & view verbatim, filling in the values for the template_name and success_url. When I try to use it, the form displays, and gives me a choose file button. Clicking the button brings up the file dialog and I can select multiple files. When I close the dialog it shows 5 files next to the button. When I submit, it goes to the page I provided in success_url.

The problem is that when the clean method of the MultipleFileField class is called, the data parameter points to an empty list, verified with print statements - so there is nothing to clean. The empty list is assigned by the FileFieldForm class to the file_field variable which appears in the view.

There is no example template in the documentation, so here is the one I used, which borrows its formatting from the django admin model.

{% extends "admin/base.html" %}
{% load i18n %}
{% spaceless %}
    {% load static %}
    {% block title %}
        Upload Recordings
    {% endblock %}
    {% block extrahead %}
      <link rel="icon" type="image/png" href="{% static 'images/favicon_64x64.png' %}" >
    {% endblock %}
    {% block branding %}
      <h1 id="site-name">{% trans 'Upload Recordings' %}</h1>
    {% endblock %}
    {% block content %}
      <form method="post">
        {% csrf_token %}
        {{ form }}
        <button name="submit">Submit</button>
    {% endblock %}
{% endspaceless %}

Django 5.0.6, Python 3.12.3, Windows 11. Running in Django runserver with debug enabled.

Welcome @SullivanChrisJ !

From the docs at Basic file uploads:

Note that request.FILES will only contain data if the request method was POST , at least one file field was actually posted, and the <form> that posted the request has the attribute enctype="multipart/form-data" . Otherwise, request.FILES will be empty.

There may be other things wrong, but this is the first one I see.

Also, be aware that Django does not intrinsically or automatically handle multiple file uploads. You don’t post the view that is handling this form, so I don’t know if you’re doing this, but you at least need to be aware that that work is up to you. See all the docs at Uploading multiple files.

Thank you Ken.

I mentioned the form & view were verbatim from the documentation, except for the blanks I filled in.

from django import forms

class MultipleFileInput(forms.ClearableFileInput):
    allow_multiple_selected = True

class MultipleFileField(forms.FileField):
    def __init__(self, *args, **kwargs):
        kwargs.setdefault("widget", MultipleFileInput())
        super().__init__(*args, **kwargs)

    def clean(self, data, initial=None):
        print('>>>', data, initial)
        single_file_clean = super().clean
        if isinstance(data, (list, tuple)):
            result = [single_file_clean(d, initial) for d in data]
            result = [single_file_clean(data, initial)]
        return result

class FileFieldForm(forms.Form):
    file_field = MultipleFileField()

and here is the view

from django.views.generic.edit import FormView
from .forms import FileFieldForm

class FileFieldFormView(FormView):
    form_class = FileFieldForm
    template_name = "ingest/upload.html"
    success_url = '/ingest/receiver/'

    def form_valid(self, form):
        print(form.cleaned_data)   # test
        files = form.cleaned_data["file_field"]

        for f in files:
            print(f)    # Test
        return super().form_valid(form)

I haven’t been able to find a way to add that enctype attribute to the form defined as a class with {form} in the html.

It’s not in the form. It belongs as an attribute on the HTML <form> element.

It’s not in the form. It belongs as an attribute on the HTML <form> element.

I was misreading my own template. It would have saved some time if the example included the template code (or, admittedly, I’d read the single file upload documentation more carefully).

Thanks for your patience :grinning: