Package: django-pictures
Django PicturesResponsive cross-browser image library using modern codes like AVIF & WebP.responsive web images using thepicturetagnative grid system supportserve files with or without a CDNplaceholders for local developmentmigration supportasync image processing forCelery,DramatiqorDjango RQDRFsupportUsageBefore you start, it can be a good idea to understand the fundamentals ofresponsive 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.pyfromdjango.dbimportmodelsfrompictures.modelsimportPictureFieldclassProfile(models.Model):title=models.CharField(max_length=255)picture=PictureField(upload_to="avatars")<!-- template.html -->{% load pictures %}
{% picture profile.picture img_alt="Spiderman" img_loading="lazy" picture_class="my-picture" m=6 l=4 %}The keyword argumentsm=6 l=4define the columns the image should take up in
a grid  at a given breakpoint. So in this example, the image will take up
6 columns on medium screens and 4 columns on large screens. You can define your
grid and breakpoints as you want, refer to thegrid columnsandbreakpointssections.The template above will render into:<pictureclass="my-picture"><sourcetype="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"><imgsrc="/media/testapp/profile/image.jpg"alt="Spiderman"width="800"height="800"loading="lazy"></picture>Note that arbitrary attributes can be passed
to either the<picture>or<img>element
by prefixing parameters to the{% picture %}tag
withpicture_orimg_respectively.SetupInstallationpython3-mpipinstalldjango-picturesSettings# settings.pyINSTALLED_APPS=[# ...'pictures',]# the following are defaults, but you can override themPICTURES={"BREAKPOINTS":{"xs":576,"s":768,"m":992,"l":1200,"xl":1400,},"GRID_COLUMNS":12,"CONTAINER_WIDTH":1200,"FILE_TYPES":["WEBP"],"PIXEL_DENSITIES":[1,2],"USE_PLACEHOLDERS":True,"QUEUE_NAME":"pictures","PROCESSOR":"pictures.tasks.process_picture",}If you have either Dramatiq or Celery installed, we will default to async
image processing. You will need workers to listen to thepicturesqueue.PlaceholdersThis library comes with dynamically created placeholders to simplify local
development. To enable them, add the following to enable thePICTURES["USE_PLACEHOLDERS"]setting and add the following URL configuration:# urls.pyfromdjango.urlsimportinclude,pathfrompictures.confimportget_settingsurlpatterns=[# ...]ifget_settings().USE_PLACEHOLDERS:urlpatterns+=[path("_pictures/",include("pictures.urls")),]Legacy use-cases (email)Although thepicture-tag isadequate for most use-cases,
some remain, where a singleimgtag is necessary. Notably in email, wheremost clients do support WebPbut notsrcset.
The template tagimg_urlreturns a single size image URL.
In addition to the ratio you will need to define thefile_typeas well as thewidth(absolute width in pixels).{% load pictures %}<imgsrc="{% img_url profile.picture ratio="3/2"file_type="webp"width=800%}"alt="profile picture">ConfigAspect ratiosYou can specify the aspect ratios of your images. Images will be cropped to the
specified aspect ratio. Aspect ratios are specified as a string with a slash
between the width and height. For example,16/9will crop the image to 16:9.# models.pyfromdjango.dbimportmodelsfrompictures.modelsimportPictureFieldclassProfile(models.Model):title=models.CharField(max_length=255)picture=PictureField(upload_to="avatars",aspect_ratios=[None,"1/1","3/2","16/9"],)# template.html
{% load pictures %}
{% picture profile.picture img_alt="Spiderman" ratio="16/9" m=6 l=4 %}If you don't specify an aspect ratio or None in your template, the image will be
served with the original aspect ratio of the file.You may only use aspect ratios in templates, that have been defined on the model.
The modelaspect_ratioswill default to[None], if other value is provided.BreakpointsYou may define your own breakpoints, they should be identical to the ones used
in your css library. Simply override thePICTURES["BREAKPOINTS"]setting.Grid columnsGrids 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 thePICTURES["GRID_COLUMNS"]setting.Container widthContainers are commonly used to limit the maximum width of layouts,
to promote better readability on larger screens. We default to1200px,
but you can override this setting, via thePICTURES["CONTAINER_WIDTH"]setting.You may also set it toNone, should you not use a container.File typesUnless you still services IE11 clients, you should be fine serving justWebP. Sadly,AVIF(WebP's successor) isnot yet supported by Pillow.If you are serving IE11 use addJPEGto the list. Beware though, that this may
drastically increase you storage needs.Pixel densitiesUnless 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 default1xand2xdensities.Async image processingIf you have either Dramatiq or Celery installed, we will default to async
image processing. You will need workers to listen to thepicturesqueue.
You can override the queue name, via thePICTURES["QUEUE_NAME"]setting.You can also override the processor, via thePICTURES["PROCESSOR"]setting.
The default processor ispictures.tasks.process_picture. It takes a single
argument, thePictureFileFileinstance. You can use this to override the
processor, should you need to do some custom processing.MigrationsDjango doesn't support file field migrations, but we do.
You can simply auto create the migration and replace Django'sAlterFieldoperation withAlterPictureField. That's it.You can followthe examplein our test app, to see how it works.ContribDjango Rest Framework (DRF)We do ship with a read-onlyPictureFieldthat can be used to include all
available picture sizes in a DRF serializer.fromrest_frameworkimportserializersfrompictures.contrib.rest_frameworkimportPictureFieldclassPictureSerializer(serializers.Serializer):picture=PictureField()The response can be restricted to a single aspect ratio and image source, by
providing theaspect_ratioandimage_sourcearguments to the field.fromrest_frameworkimportserializersfrompictures.contrib.rest_frameworkimportPictureFieldclassPictureSerializer(serializers.Serializer):picture=PictureField(aspect_ratio="16/9",image_source="WEBP")You also may provide optional GET parameters to the serializer,
to specify the aspect ratio and breakpoints you want to include in the response.
The parameters are prefixed with thefieldname_to avoid conflicts with other fields.curlhttp://localhost:8000/api/path/?picture_ratio=16%2F9&picture_m=6&picture_l=4# %2F is the url encoded slash{"other_fields":"…","picture":{"url":"/path/to/image.jpg","width":800,"height":800,"ratios":{"1/1":{"sources":{"image/webp":{"100":"/path/to/image/1/100w.webp","200":"…"}},"media":"(min-width: 0px) and (max-width: 991px) 100vw, (min-width: 992px) and (max-width: 1199px) 33vw, 25vw"}}}}Note that themediakeys are only included, if you have specified breakpoints.Django CleanupPictureFieldis compatible withDjango Cleanup,
which automatically deletes its file and correspondingSimplePicturefiles.