liveBook · Manning

Multipart/form-data

As explained in Django in Action

multipart/form-data is an HTTP media type for encoding form fields and uploaded files as separate parts of one request body.

multipart/form-data is an HTTP media type that lets one form request carry ordinary fields and uploaded files. In a Django form that includes a file field, the HTML form must declare enctype="multipart/form-data"; otherwise the upload does not work properly. section 7.4.3 section 7.6

Think of the setup as a two-sided handshake: the template marks the submitted form as capable of carrying files, and the view reads uploaded data separately from ordinary posted values. Django places normal form values in request.POST and uploaded files in request.FILES. section 7.4.3 section 7.6

For a ModelForm-backed upload, wire together these pieces:

  • Include a FileField or ImageField on the model; Django stores a reference to the uploaded file. section 7.6
  • Render the ModelForm, which supplies an upload control for the file field. section 7.6
  • Set enctype="multipart/form-data" on the form element, along with method="post". section 7.4.3
  • Construct or bind the form with request.POST and request.FILES so submitted fields and files reach the form together. section 7.4.3 section 7.6

Uploading a venue picture

A venue editor can use a ModelForm containing name, description, and picture. Its template adds enctype="multipart/form-data" to the form tag. On POST, the view passes request.POST and request.FILES to VenueForm, then can save the venue with its picture and display that picture from the stored field URL. section 7.4.3 section 7.6

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 form tag shows the small but essential enctype change: it is easy to omit and prevents file uploads from working when absent. section 7.4.3

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 view shows the matching server-side step: bind a ModelForm with request.POST and request.FILES when handling a POST request. section 7.4.3

How Django in Action covers it

How deep it goes
Explains template and view wiring for ModelForm uploads without descending into multipart wire-format internals.
Examples
Uses a venue add/edit form that uploads a picture with name and description fields.
What you can do after
Apply it via Django ModelForm by setting enctype and passing request.FILES alongside request.POST.
How it connects
Connects HTML forms, Django ModelForm, FileField, ImageField, request.POST, request.FILES, and MEDIA_ROOT.

Also explained in

Compare how 3 books explain multipart/form-data →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Django in Action. The section links point to the parts of the book it draws on.