`request.FILES` holds uploaded files from a multipart form submission. It is separate from `request.POST`, which carries ordinary form fields. When a Django `ModelForm` includes a file field, pass both collections to the form so it can process the upload alongside the rest of the submitted data. section 7.4.3 section 7.6
A file-upload request needs three cooperating pieces:
- Give the model a `FileField` or `ImageField`; a `ModelForm` then renders an upload control for it. section 7.6
- Set the HTML form’s `enctype` to `multipart/form-data`; without it, the file upload will not work properly. section 7.4.3 section 7.6
- On POST, construct the form with `request.POST` and `request.FILES`, plus an `instance` when editing an existing object. section 7.4.3
- Save the valid form; uploaded-file references are stored through the model’s file fields, with uploaded files managed under `MEDIA_ROOT`. section 7.6
Listing 7.18 The self-service view for adding and editing venues
# RiffMates/bands/views.py
...
from django.shortcuts import render, get_object_or_404, redirect
from bands.models import Musician, Band, Venue, Room
from bands.forms import VenueForm
...
@login_required
def edit_venue(request, venue_id=0):
if venue_id != 0: #1
venue = get_object_or_404(Venue,
id=venue_id) #2
if not request.user.userprofile.venues_controlled.filter(
id=venue_id).exists(): #3
raise Http404("Can only edit controlled venues")
if request.method == 'GET': #4
if venue_id == 0:
form = VenueForm()
else:
form = VenueForm(instance=venue)
else: # POST
if venue_id == 0: #5
venue = Venue.objects.create()
form = VenueForm(request.POST, request.FILES, #6
instance=venue)
if form.is_valid():
venue = form.save()
# Add the venue to the user's profile #7
request.user.userprofile.venues_controlled.add(venue)
return redirect("venues")
# Was a GET, or Form was not valid
data = {
"form": form,
}
return render(request, "edit_venue.html", data)
The venue edit view shows the key handoff: regular fields arrive in `request.POST`, while the uploaded picture arrives in `request.FILES`. Both are passed to `VenueForm` for a new or existing venue. section 7.4.3
Listing 7.19 Template for adding or editing a Venue object
<!-- RiffMates/templates/edit_venue.html -->
{% extends "base.html" %}
{% block content %}
<h1>Venue Details</h1>
<form enctype="multipart/form-data" method="post"> #1
{% csrf_token %}
{{form.as_p}}
<button class="btn btn-dark" type="submit">Save</button>
</form>
{% endblock content %}
The template supplies the other half of the contract: `enctype="multipart/form-data"` tells the browser to submit the selected file as an upload rather than leaving Django with an empty `request.FILES`. section 7.4.3
Uploading a venue picture
A venue form generated from fields including `picture` can create or edit a venue. The browser submits the form as multipart data; the view builds `VenueForm(request.POST, request.FILES, instance=venue)`, then saves the form when appropriate. Later, a template can display the uploaded image through `venue.picture.url` when a picture exists. section 7.4.3 section 7.6
