@@ -126,19 +126,54 @@ model::
126
126
form = UploadFileForm()
127
127
return render(request, 'upload.html', {'form': form})
128
128
129
+ .. _uploading_multiple_files:
130
+
129
131
Uploading multiple files
130
132
------------------------
131
133
132
- If you want to upload multiple files using one form field, set the ``multiple``
133
- HTML attribute of field's widget:
134
+ ..
135
+ Tests in tests.forms_tests.field_tests.test_filefield.MultipleFileFieldTest
136
+ should be updated after any changes in the following snippets.
137
+
138
+ If you want to upload multiple files using one form field, create a subclass
139
+ of the field's widget and set the ``allow_multiple_selected`` attribute on it
140
+ to ``True``.
141
+
142
+ In order for such files to be all validated by your form (and have the value of
143
+ the field include them all), you will also have to subclass ``FileField``. See
144
+ below for an example.
145
+
146
+ .. admonition:: Multiple file field
147
+
148
+ Django is likely to have a proper multiple file field support at some point
149
+ in the future.
134
150
135
151
.. code-block:: python
136
152
:caption: ``forms.py``
137
153
138
154
from django import forms
139
155
156
+
157
+ class MultipleFileInput(forms.ClearableFileInput):
158
+ allow_multiple_selected = True
159
+
160
+
161
+ class MultipleFileField(forms.FileField):
162
+ def __init__(self, *args, **kwargs):
163
+ kwargs.setdefault("widget", MultipleFileInput())
164
+ super().__init__(*args, **kwargs)
165
+
166
+ def clean(self, data, initial=None):
167
+ single_file_clean = super().clean
168
+ if isinstance(data, (list, tuple)):
169
+ result = [single_file_clean(d, initial) for d in data]
170
+ else:
171
+ result = single_file_clean(data, initial)
172
+ return result
173
+
174
+
140
175
class FileFieldForm(forms.Form):
141
- file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}) )
176
+ file_field = MultipleFileField( )
142
177
143
178
Then override the ``post`` method of your
144
179
:class:`~django.views.generic.edit.FormView` subclass to handle multiple file
@@ -158,14 +193,32 @@ uploads:
158
193
def post(self, request, *args, **kwargs):
159
194
form_class = self.get_form_class()
160
195
form = self.get_form(form_class)
161
- files = request.FILES.getlist('file_field')
162
196
if form.is_valid():
163
- for f in files:
164
- ... # Do something with each file.
165
197
return self.form_valid(form)
166
198
else:
167
199
return self.form_invalid(form)
168
200
201
+ def form_valid(self, form):
202
+ files = form.cleaned_data["file_field"]
203
+ for f in files:
204
+ ... # Do something with each file.
205
+ return super().form_valid()
206
+
207
+ .. warning::
208
+
209
+ This will allow you to handle multiple files at the form level only. Be
210
+ aware that you cannot use it to put multiple files on a single model
211
+ instance (in a single field), for example, even if the custom widget is used
212
+ with a form field related to a model ``FileField``.
213
+
214
+ .. versionchanged:: 3.2.19
215
+
216
+ In previous versions, there was no support for the ``allow_multiple_selected``
217
+ class attribute, and users were advised to create the widget with the HTML
218
+ attribute ``multiple`` set through the ``attrs`` argument. However, this
219
+ caused validation of the form field to be applied only to the last file
220
+ submitted, which could have adverse security implications.
221
+
169
222
Upload Handlers
170
223
===============
171
224
0 commit comments