Responsive cross-browser image library using modern codes like AVIF & WebP.
- responsive web images using the picture tag
- native grid system support
- serve files with or without a CDN
- placeholders for local development
- migration support
- async image processing for Celery or Dramatiq
Before you start, it can be a good idea to understand the fundamentals of responsive images.
Once you get a feeling how complicated things can get with all device types, you'll probably find a new appreciation for this package and are ready to adopt in you project :)
# models.py
from django.db import models
from pictures.models import PictureField
class Profile(models.Model):
title = models.CharField(max_length=255)
picture = PictureField(upload_to="avatars")
<!-- template.html -->
{% load pictures %}
{% picture profile.picture alt="Spiderman" loading="lazy" m=6 l=4 %}
The template above will render into:
<picture>
<source type="image/webp"
srcset="/media/testapp/profile/image/800w.webp 800w, /media/testapp/profile/image/100w.webp 100w, /media/testapp/profile/image/200w.webp 200w, /media/testapp/profile/image/300w.webp 300w, /media/testapp/profile/image/400w.webp 400w, /media/testapp/profile/image/500w.webp 500w, /media/testapp/profile/image/600w.webp 600w, /media/testapp/profile/image/700w.webp 700w"
sizes="(min-width: 0px) and (max-width: 991px) 100vw, (min-width: 992px) and (max-width: 1199px) 33vw, 600px">
<img src="/media/testapp/profile/image.jpg" alt="Spiderman" width="800" height="800" loading="lazy">
</picture>
python3 -m pip install django-pictures
# settings.py
INSTALLED_APPS = [
# ...
'pictures',
]
# the following are defaults, but you can override them
PICTURES = {
"BREAKPOINTS": {
"xs": 576,
"s": 768,
"m": 992,
"l": 1200,
"xl": 1400,
},
"GRID_COLUMNS": 12,
"CONTAINER_WIDTH": 1200,
"FILE_TYPES": ["WEBP"],
"PIXEL_DENSITIES": [1, 2],
}
If you have either Dramatiq or Celery installed, we will default to async
image processing. You will need workers to listen to the pictures
queue.
This library comes with dynamically created placeholders to simplify local
development. To enable them, add the following to enable the
PICTURES["USE_PLACEHOLDERS"]
setting and add the following URL configuration:
# urls.py
from django.conf.urls import include, path
from pictures.conf import get_settings
urlpatterns = [
# ...
]
if get_settings().USE_PLACEHOLDERS:
urlpatterns += [
path("_pictures/", include("pictures.urls")),
]
You may define your own breakpoints, they should be identical to the ones used
in your css library. Simply override the PICTURES["BREAKPOINTS"]
setting.
Grids are so common in web design, that they even made it into CSS.
We default to 12 columns, but you can override this setting, via the
PICTURES["GRID_COLUMNS"]
setting.
Containers are commonly used to limit the maximum width of layouts,
to promote better readability on larger screens. We default to 1200px
,
but you can override this setting, via the PICTURES["CONTAINER_WIDTH"]
setting.
You may also set it to None
, should you not use a container.
Unless you still services IE11 clients, you should be fine serving just WebP. Sadly, AVIF (WebP's successor) is not yet supported by Pillow.
Unless you really care that your images hold of if you hold your UHD phone very
close to your eyeballs, you should be fine, serving at the default 1x
and 2x
densities.
If you have either Dramatiq or Celery installed, we will default to async
image processing. You will need workers to listen to the pictures
queue.
You can override the queue name, via the PICTURES["QUEUE_NAME"]
setting.
Django doesn't support file field migrations, but we do.
You can simply auto create the migration and replace Django's
AlterField
operation with AlterPictureField
. That's it.
You can follow the example in our test app, to see how it works.
We do ship with a read-only PictureField
that can be used to include all
available picture sizes in a DRF serializer.
from rest_framework import serializers
from pictures.contrib.rest_framework import PictureField
class PictureSerializer(serializers.Serializer):
picture = PictureField()
PictureField
is compatible with Djang Cleanup,
which automatically deletes its file and corresponding SimplePicture
files.