Adding a Photo Field
People want to browse potential pets by their cute pictures. Let's add a photo to our animals, so our sample data can include a picture of each one.
This chapter's starting branch provides Pillow, the settings for uploaded files, and the sample data. Check it out:
git stash -u
git fetch --all
git checkout -b my-ch04-start --no-track origin/ch04-start
uv sync
If Git prints No local changes to save, there was nothing to set aside.
The Photo Field
Open animals/models.py and add a photo field to Animal:
description = models.TextField(blank=True)
photo = models.ImageField(upload_to="animals/", blank=True)
Django saves the uploaded file to disk, and the ImageField column holds the file's path. upload_to is the folder the files go in, and blank=True means it's an optional field.
An ImageField requires Pillow, an imaging library, which the starting branch added to our dependencies.
Where Uploaded Files Get Stored
Two settings say where on disk uploaded files are saved, and what address they're served from. The starting branch added them at the bottom of config/settings.py:
MEDIA_ROOT = BASE_DIR / "media"
MEDIA_URL = "media/"
MEDIA_ROOT: The folder where Django saves uploaded files.BASE_DIRis the project's root folder, whichstartprojectdefines at the top of the settings.MEDIA_URL: The root of the address those files are served from.
With upload_to="animals/" on our field, a photo is saved in media/animals/, and served from an address that starts with /media/animals/.
Django doesn't serve that folder automatically, so the starting branch also added this line at the bottom of config/urls.py:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
static() returns URL patterns that serve the files in MEDIA_ROOT. It only does that while DEBUG is on. On a production site, a web server or a storage service serves uploaded files.
Migrate the New Field
We changed a model, so let's make a migration, and migrate:
uv run manage.py makemigrations
uv run manage.py migrate