Usage

The common way easy-thumbnails is used is via the {% thumbnail %} template tag or thumbnail_url filter, which generates images from a model with an ImageField. The tag can also be used with media images not tied to a specific model by passing in the relative path instead.

Custom database fields are also available for simpler access.

The underlying Python code can be used for lower-level generation of thumbnail images.

Overview

The primary function of easy-thumbnails is to dynamically create thumbnails based on a source image.

So whenever a thumbnail does not exist or if the source was modified more recently than the existing thumbnail, a new thumbnail is generated (and saved).

Every thumbnail is generated by running the source image through the pipeline of image processors defined in the THUMBNAIL_PROCESSORS setting. The processors are called one after the other, in the order listed: each receives the image returned by the previous one and modifies it. All thumbnail options are passed to every processor, and each processor only acts on the options it knows. See Image Processors for the built-in processors and how to write your own.

Thumbnail aliases can be defined in the THUMBNAIL_ALIASES setting, providing predefined thumbnail options. This also allows for generation of thumbnails when the source image is uploaded.

Thumbnail options

To generate a thumbnail of a source image, you specify options which are used by the image processors to generate the required image. The options are grouped below by the processor that uses them; see Image Processors for the complete reference.

Required options

size is a required option, and defines the bounds that the generated image must fit within. It is used by scale_and_crop() and background().

Optional options

Use other options only if the given functionality is required.

colorspace()
  • bw Convert the image to grayscale.

  • replace_alpha=#colorcode Replace any transparency layer with a solid color.

autocrop()
  • autocrop Remove any unnecessary whitespace from the edges of the source image.

scale_and_crop()
  • crop=<smart|scale|W,H> Cut the edges of the image to match the aspect ratio of size before resizing.

    • smart Incrementally crop the image down to the requested size by removing slices from edges with the least entropy.

    • scale Scale the image so that at least one dimension fits within the size dimensions given.

    • W,H Modify the cropping origin behavior:

      • crop="0,0" Crop from the left and top edges.

      • crop="-10,-0" Crop from the right edge (with a 10% offset) and the bottom edge.

      • crop=",0" Keep the default behavior for the x axis (horizontally centering the image) and crop from the top edge.

  • upscale Allow the source image to be enlarged to reach size.

  • zoom=<N> Zoom in on the scaled image by N percent, clipping the edges.

  • target=<X,Y> Set the focal point (in percent from the left and top) that is kept centered when the image has to be cropped. Defaults to 50,50.

filters()
  • sharpen and detail Apply the SHARPEN and DETAIL filters from Pillow’s ImageFilter module.

background()
  • background=#colorcode Pad the image with a border of this color so it fits size exactly (the image is centered). Also replace any transparency with that color.

Output options

These are not used by a processor but when the thumbnail is saved.

  • quality=<N> Specify the output JPEG, WebP or AVIF quality as an integer N between 1 and 100. The default depends on the output format and is set by the quality entries of THUMBNAIL_IMAGE_SAVE_OPTIONS (JPEG 76, WebP 80, AVIF 61 by default). For lossless WebP it only trades encoding speed for file size, see WebP support.

  • format=<jpeg|webp|avif> Set the output format of this thumbnail, overriding THUMBNAIL_EXTENSION, THUMBNAIL_TRANSPARENCY_EXTENSION and THUMBNAIL_PRESERVE_EXTENSIONS. Note that JPEG does not support transparency: with format=jpeg the alpha channel of a transparent source is discarded, so combine it with replace_alpha to choose the background color. WebP and AVIF preserve transparency.

  • subsampling=<N> Set the JPEG color subsampling level where N is:

    • 2 is 4:1:1 (both easy-thumbnails and PIL’s default)

    • 1 is 4:2:2 (slightly crisper color borders, small increase in size)

    • 0 is 4:4:4 (very crisp color borders, ~15% increase in size)

For a complete and detailed list of options, see the Image Processors reference documentation.

To change a default options level, add it to the THUMBNAIL_DEFAULT_OPTIONS setting. Be aware that this will change the filename for thumbnails, so existing thumbnails which don’t explicitly specify the new default option will have a new filename (and therefore be regenerated).

Thumbnail aliases

An alias is a specific set of thumbnail options.

Using aliases gives you a single location to define all of your standard thumbnail sizes/options, and avoids repetition of thumbnail options in your code and templates.

An alias may be available project-wide, or set to target a specific app, model or field.

The setting is defined like this:

THUMBNAIL_ALIASES = {
    <target>: {
        <alias name>: <alias options dictionary>,
        ...
    },
    ...
}

Use the target '' for project-wide aliases. Otherwise, the target should be a string which defines the scope of the contained aliases:

  • 'sprocket.Widget.image' would make the aliases available to only the ‘image’ field of a ‘Widget’ model in an app named ‘sprocket’.

  • 'sprocket.Widget' would apply to any field in the ‘Widget’ model.

  • 'sprocket' would target any field in any model in the app.

Pregeneration

Some provided signal handlers (along with a new saved_file signal) allow for you to have the relevant aliases generated when a file is uploaded.

easy_thumbnails.signal_handlers.generate_aliases(fieldfile, **kwargs)

A saved_file signal handler which generates thumbnails for all field, model, and app specific aliases matching the saved file’s field.

easy_thumbnails.signal_handlers.generate_aliases_global(fieldfile, **kwargs)

A saved_file signal handler which generates thumbnails for all field, model, and app specific aliases matching the saved file’s field, also generating thumbnails for each project-wide alias.

In a module that will be executed when Django loads (such as a models.py file), register one of these signal handlers. For example:

from easy_thumbnails.signals import saved_file
from easy_thumbnails.signal_handlers import generate_aliases_global

saved_file.connect(generate_aliases_global)

Asynchronous Pregeneration

For some use cases, it may not be necessary to have the relevant aliases generated at the exact moment a file is uploaded. As an alternative, the pregeneration task can be queued and executed by a background process.

The following example uses Celery to achieve this.

models.py:

from django.dispatch import receiver
from easy_thumbnails.signals import saved_file
from myapp import tasks

@receiver(saved_file)
def generate_thumbnails_async(sender, fieldfile, **kwargs):
    tasks.generate_thumbnails.delay(
        class_path="{}.{}".format(sender.__module__, sender.__name__),
        pk=fieldfile.instance.pk,
        field=fieldfile.field.name
    )

tasks.py:

import importlib
from celery import shared_task
from easy_thumbnails.files import generate_all_aliases

@task
def generate_thumbnails(class_path, pk, field):
    bits = class_path.split(".")
    generate_all_aliases(
        getattr(
            getattr(
                importlib.import_module(".".join(bits[:-1])), bits[-1]
            ).objects.get(pk=pk),
            field,
        ),
        include_global=True,
    )

This results in a more responsive experience for the user, particularly when dealing with large files and/or remote storage.

Setting aliases for your third-party app

If you have a distributable app that uses easy-thumbnails and want to provide an alias, you can modify the aliases at runtime.

For example, put something like this in a module that will execute when Django initializes (such as models.py):

from easy_thumbnails.alias import aliases
if not aliases.get('badge'):
    aliases.set('badge', {'size': (150, 80), 'crop': True})

Templates

To make the easy-thumbnail template library available for use in your template, use:

{% load thumbnail %}

thumbnail_url filter

easy_thumbnails.templatetags.thumbnail.thumbnail_url(source, alias)

Return the thumbnail url for a source file using an aliased set of thumbnail options.

If no matching alias is found, returns an empty string.

Example usage:

<img src="{{ person.photo|thumbnail_url:'small' }}" alt="">

{% thumbnail %} tag

If you want to create a thumbnail without providing an alias, use this tag to generate the thumbnail by specifying all of the required options (or with an alias name, to override/supplement the default alias options with dynamic content).

easy_thumbnails.templatetags.thumbnail.thumbnail(parser, token)

Creates a thumbnail of an ImageField.

Basic tag Syntax:

{% thumbnail [source] [size] [options] %}

source must be a File object, usually an Image/FileField of a model instance.

size can either be:

  • the name of an alias

  • the size in the format [width]x[height] (for example, {% thumbnail person.photo 100x50 %}) or

  • a variable containing a valid size (i.e. either a string in the [width]x[height] format or a tuple containing two integers): {% thumbnail person.photo size_var %}.

options are a space separated list of options which are used when processing the image to a thumbnail such as sharpen, crop and quality=90.

The output format of a single thumbnail can be set with format="webp", format="avif" or format="jpeg", overriding the extension settings. JPEG does not support transparency, so for transparent sources prefer WebP or add replace_alpha to choose the background color.

If size is specified as an alias name, options are used to override and/or supplement the options defined in that alias.

The thumbnail tag can also place a ThumbnailFile object in the context, providing access to the properties of the thumbnail such as the height and width:

{% thumbnail [source] [size] [options] as [variable] %}

When as [variable] is used, the tag doesn’t output anything. Instead, use the variable like a standard ImageFieldFile object:

{% thumbnail obj.picture 200x200 upscale as thumb %}
<img src="{{ thumb.url }}"
     width="{{ thumb.width }}"
     height="{{ thumb.height }}" />

Debugging

By default, if there is an error creating the thumbnail or resolving the image variable then the thumbnail tag will just return an empty string (and if there was a context variable to be set then it will also be set to an empty string).

For example, you will not see an error if the thumbnail could not be written to directory because of permissions error. To display those errors rather than failing silently, set THUMBNAIL_DEBUG = True in your Django project’s settings module.

For a full list of options, read the Image Processors reference documentation.

Fallback images

If you need to support fallback or default images at template level you can use:

{% thumbnail object.image|default:'img/default_image.png' 50x50 %}

Where the image string is relative to your default storage (usually the MEDIA_ROOT setting).

Other thumbnailer filters

There are two filters that you can use if you want to get direct access to a thumbnailer in your template. This can be useful when dealing with aliased thumbnails.

easy_thumbnails.templatetags.thumbnail.thumbnailer(obj, relative_name=None)

Creates a thumbnailer from an object (usually a FileField).

Example usage:

{% with photo=person.photo|thumbnailer %}
{% if photo %}
    <a href="{{ photo.large.url }}">
        {{ photo.square.tag }}
    </a>
{% else %}
    <img src="{% static 'template/fallback.png' %}" alt="" />
{% endif %}
{% endwith %}

If you know what you’re doing, you can also pass the relative name:

{% with photo=storage|thumbnailer:'some/file.jpg' %}...
easy_thumbnails.templatetags.thumbnail.thumbnailer_passive(obj)

Creates a thumbnailer from an object (usually a FileFile) that won’t generate new thumbnails.

This is useful if you are using another process to generate the thumbnails rather than having them generated on the fly if they are missing.

Example usage:

{% with avatar=person.avatar|thumbnailer_passive %}
    {% with avatar_thumb=avatar.small %}
        {% if avatar_thumb %}
            <img src="{{ avatar_thumb.url }}" alt="" />
        {% else %}
            <img src="{% static 'img/default-avatar-small.png' %}"
                alt="" />
        {% endif %}
    {% endwith %}
{% endwith %}

Finally, if you want to have an image inserted inline into the template as a data URI, use this filter:

easy_thumbnails.templatetags.thumbnail.data_uri(thumbnail)

This filter will return the base64 encoded data URI for a given thumbnail object.

Example usage:

{% thumbnail sample_image 25x25 crop as thumb %}
<img src="{{ thumb|data_uri }}">

will for instance be rendered as:

Models

You can use the ThumbnailerField or ThumbnailerImageField fields (based on FileField and ImageField, respectively) for easier access to retrieve (or generate) thumbnail images, use different storages and resize source images before saving.

class easy_thumbnails.fields.ThumbnailerField(*args, **kwargs)

A file field which provides easier access for retrieving (and generating) thumbnails.

To use a different file storage for thumbnails, provide the thumbnail_storage keyword argument.

class easy_thumbnails.fields.ThumbnailerImageField(*args, **kwargs)

An image field which provides easier access for retrieving (and generating) thumbnails.

To use a different file storage for thumbnails, provide the thumbnail_storage keyword argument.

To thumbnail the original source image before saving, provide the resize_source keyword argument, passing it a usual thumbnail option dictionary. For example:

ThumbnailerImageField(
    ..., resize_source=dict(size=(100, 100), sharpen=True))

Forms

class easy_thumbnails.widgets.ImageClearableFileInput(thumbnail_options=None, attrs=None)

Use this widget to show a thumbnail of the image next to the image file.

If using the admin and ThumbnailerField, you can use this widget automatically with the following code:

class MyModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        ThumbnailerField: {'widget': ImageClearableFileInput},
    }
__init__(thumbnail_options=None, attrs=None)

Set up the thumbnail options for this widget.

Parameters:

thumbnail_options – options used to generate the thumbnail. If no size is given, it’ll be (80, 80). If not provided at all, default options will be used from the THUMBNAIL_WIDGET_OPTIONS setting.

Python

Easy thumbnails uses a Django File-like object called a Thumbnailer to generate thumbnail images from the source file which it references.

get_thumbnailer

The easy way to create a Thumbnailer instance is to use the following utility function:

easy_thumbnails.files.get_thumbnailer(obj, relative_name=None)

Get a Thumbnailer for a source file.

The obj argument is usually either one of the following:

  • FieldFile instance (i.e. a model instance file/image field property).

  • A string, which will be used as the relative name (the source will be set to the default storage).

  • Storage instance - the relative_name argument must also be provided.

Or it could be:

  • A file-like instance - the relative_name argument must also be provided.

    In this case, the thumbnailer won’t use or create a cached reference to the thumbnail (i.e. a new thumbnail will be created for every Thumbnailer.get_thumbnail() call).

If obj is a Thumbnailer instance, it will just be returned. If it’s an object with an easy_thumbnails_thumbnailer then the attribute is simply returned under the assumption it is a Thumbnailer instance)

Once you have an instance, you can use the Thumbnailer.get_thumbnail() method to retrieve a thumbnail, which will (by default) generate it if it doesn’t exist (or if the source image has been modified since it was created).

For example, assuming an aardvark.jpg image exists in the default storage:

from easy_thumbnails.files import get_thumbnailer

thumbnailer = get_thumbnailer('animals/aardvark.jpg')

thumbnail_options = {'crop': True}
for size in (50, 100, 250):
    thumbnail_options.update({'size': (size, size)})
    thumbnailer.get_thumbnail(thumbnail_options)

# or to get a thumbnail by alias
thumbnailer['large']

Prefetching thumbnails

Using an existing thumbnail costs database queries: one to look it up if thumbnails are in remote storage, and one to read its width or height. Prefetching replaces these with a single query up front:

  • With THUMBNAIL_CACHE_DIMENSIONS enabled, using the thumbnails afterwards needs no further queries.

  • With remote storage and without that setting, the lookups are saved, but reading the dimensions still costs a query per thumbnail.

  • With local storage and without that setting, prefetching saves nothing, so don’t use it.

Choose the method by what you need to fetch:

Use

For

Thumbnails to fetch

Queries

Thumbnailer.prefetch_aliases()

One file

Given alias names

One

Thumbnailer.prefetch_thumbnails()

One file

Given thumbnail options

One

prefetch_aliases()

Several files

Given alias names, or by default all aliases of each file

One per combination of source and thumbnail storage

To fetch several thumbnails of one source (e.g. for a srcset), call the method of its thumbnailer:

thumbnailer = get_thumbnailer('animals/aardvark.jpg')
thumbnailer.prefetch_aliases(['small', 'large'])
for alias in ('small', 'large'):
    thumb = thumbnailer[alias]
    thumb.url, thumb.width, thumb.height

To show thumbnails of several sources, e.g. the profile pictures of a list of users, use the prefetch_aliases() function, which needs a single query instead of one per source. Thumbnails with explicit options can only be prefetched per source:

from easy_thumbnails.files import prefetch_aliases

users = list(User.objects.all())
prefetch_aliases(user.avatar for user in users)
for user in users:
    user.avatar['small'].url

The Thumbnail records are fetched together with their Source and ThumbnailDimensions and kept on the thumbnailer instance. Prefetching doesn’t generate anything: thumbnails that are missing are generated as usual when they are accessed.

Because the records are kept on the instance, you need to use the same instances afterwards:

  • Don’t call get_thumbnailer() with a path again, as it returns a new thumbnailer.

  • Evaluate querysets once, as in the list() above. Iterating over a new queryset creates new model instances, and so new field files.

  • Prefetching again replaces the records fetched before, so fetch everything you need in one call.

The example above needs a ThumbnailerImageField or ThumbnailerField, whose files are thumbnailers. Files of a plain ImageField or FileField raise an AttributeError. Wrap them with get_thumbnailer() and keep the result, as each call returns a new thumbnailer:

thumbnailers = [get_thumbnailer(user.avatar) for user in users]
prefetch_aliases(thumbnailers)
for thumbnailer in thumbnailers:
    thumbnailer['small'].url

Prefetched thumbnails also work in templates, if the template gets the same instances:

{% thumbnail user.avatar 'small' %}
{{ user.avatar|thumbnail_url:'small' }}

An alias with overriding options, like {% thumbnail user.avatar 'small' crop %}, is a different thumbnail, which prefetching the alias doesn’t cover.

Thumbnailer.prefetch_thumbnails(thumbnail_options_list)

Fetch the database records of several thumbnails with a single query.

The Thumbnail records are fetched together with their ThumbnailDimensions (and the Source), so the following calls to get_thumbnail() for the same options need no further queries for existing thumbnails, and their dimensions are available without reading the file (if THUMBNAIL_CACHE_DIMENSIONS is enabled).

Thumbnails that are missing are generated as usual.

The records are kept on this instance, so use it for the following calls. Prefetching again replaces the records fetched before.

Arguments:

thumbnail_options_list

Iterable of dicts or ThumbnailOptions, as for get_thumbnail(). Options of aliases must contain ALIAS, see prefetch_aliases().

Thumbnailer.prefetch_aliases(aliases_names)

Like prefetch_thumbnails() for thumbnail aliases.

Arguments:

aliases_names

Iterable of alias names, looked up for the target of this thumbnailer like thumbnailer[alias] does.

Raises a KeyError if one of the aliases does not exist.

To prefetch the thumbnails of several files with a single query, use the prefetch_aliases() function.

easy_thumbnails.files.prefetch_aliases(thumbnailers, aliases_names=None)

Fetch the thumbnails of several files with a single query.

Like Thumbnailer.prefetch_aliases(), which needs a query per file. Accessing the aliases of these thumbnailers afterwards needs no further queries for existing thumbnails. Thumbnails that are missing are generated as usual.

A query is needed per combination of source and thumbnail storage, so files of one field use a single query.

The thumbnails are kept on the given instances, so use these instances to access the aliases, and prefetching them again replaces the thumbnails fetched before.

Parameters:
  • thumbnailers – Iterable of Thumbnailer instances, including ThumbnailerFieldFile. Wrap the files of plain Django file fields with get_thumbnailer(). Empty files and remote sources are skipped.

  • aliases_names – Iterable of alias names (optional). By default all aliases of the target of each thumbnailer are fetched.

Raises:

KeyError – If one of the given aliases does not exist for the target of one of the thumbnailers.

Non-Django file objects

If you need to process a standard file-like object, use get_thumbnailer() and provide a relative_name like this:

picture = open('/home/zookeeper/pictures/my_anteater.jpg')
thumbnailer = get_thumbnailer(picture, relative_name='animals/anteater.jpg')
thumb = thumbnailer.get_thumbnail({'size': (100, 100)})

If you don’t even need to save the thumbnail to storage because you are planning on using it in some more direct way, you can use the Thumbnailer.generate_thumbnail() method.

Thumbnails generated in this manner don’t use any cache reference, i.e. every call to Thumbnailer.get_thumbnail() will generate a fresh thumbnail image.

Maintenance

easy-thumbnails provides a thumbnail management command with several sub-commands to help maintain the thumbnail database cache and files on disk. See Management Commands for the full reference. In short:

  • To remove thumbnail files and database records for source images that have been deleted from storage, use the thumbnail cleanup management command.

  • To list configured storage aliases and their storage hashes, use thumbnail storages.

  • To list or audit the source files referenced by ThumbnailerImageField values across your project, use thumbnail source_files.

  • To remove Source database records that no longer match any ThumbnailerImageField value, use thumbnail source_cleanup.