<a id="image-renditions"></a>

# Generating renditions in Python

Rendered versions of original images generated by the Wagtail `{% image %}` template tag are called “renditions”,
and are stored as new image files in the site’s `[media]/images` directory on the first invocation.

Image renditions can also be generated dynamically from Python via the native `get_rendition()` method, for example:

```python
newimage = myimage.get_rendition('fill-300x150|jpegquality-60')
```

If `myimage` had a filename of `foo.jpg`, a new rendition of the image file called
`foo.fill-300x150.jpegquality-60.jpg` would be generated and saved into the site’s `[media]/images` directory.
Argument options are identical to the `{% image %}` template tag’s filter spec, and should be separated with `|`.

The generated `Rendition` object will have properties specific to that version of the image, such as
`url`, `width` and `height`. Hence, something like this could be used in an API generator, for example:

```python
url = myimage.get_rendition('fill-300x186|jpegquality-60').url
```

Properties belonging to the original image from which the generated Rendition was created, such as `title`, can
be accessed through the Rendition’s `image` property:

```python
    >>> newimage.image.title
    'Blue Sky'
    >>> newimage.image.is_landscape()
    True
```

See also: [How to use images in templates](../../topics/images.md#image-tag)

<a id="image-renditions-multiple"></a>

## Generating multiple renditions for an image

You can generate multiple renditions of the same image from Python using the native `get_renditions()` method. It will accept any number of ‘specification’ strings or `Filter instances`, and will generate a set of matching renditions much more efficiently than generating each one individually. For example:

```python
image.get_renditions('width-600', 'height-400', 'fill-300x186|jpegquality-60')
```

The return value is a dictionary of renditions keyed by the specifications that were provided to the method. The return value from the above example would look something like this:

```python
{
    "width-600": <Rendition: Rendition object (7)>,
    "height-400": <Rendition: Rendition object (8)>,
    "fill-300x186|jpegquality-60": <Rendition: Rendition object (9)>,
}
```

If any specification contains the `preserve-svg` directive, the resulting dictionary key will be the final filter specification used for the rendition (omitting the `preserve-svg` directive, and any non-SVG-safe operations in the case that the image is an SVG) rather than the one originally passed. This may result in multiple specifications in the list resolving to the same final value - for example, if the list contains `width-400|format-jpeg|preserve-svg` and `width-400|format-webp|preserve-svg`, these will both reduce to `width-400` when applied to an SVG image. In this case, the return value will have fewer items than the original list.

<a id="caching-image-renditions"></a>

## Caching image renditions

Wagtail will cache image rendition lookups, which can improve the performance of pages which include many images.

By default, Wagtail will try to use the cache called “renditions”. If no such cache exists, it will fall back to using the default cache.

<a id="prefetching-image-renditions"></a>

## Prefetching image renditions

When using a queryset to render a list of images or objects with images, you can prefetch the renditions needed with a single additional query. For long lists of items, or where multiple renditions are used for each item, this can provide a significant boost to performance.

<a id="regenerate-image-renditions"></a>

## Regenerating existing renditions

You can also directly use the image management command from the console to regenerate the renditions:

```sh
./manage.py wagtail_update_image_renditions --purge
```

You can read more about this command from [wagtail_update_image_renditions](../../reference/management_commands.md#wagtail-update-image-renditions)

### Image QuerySets

When working with an Image QuerySet, you can make use of Wagtail’s built-in `prefetch_renditions` queryset method to prefetch the renditions needed.

For example, say you were rendering a list of all the images uploaded by a user:

```python
def get_images_uploaded_by_user(user):
    return ImageModel.objects.filter(uploaded_by_user=user)
```

The above can be modified slightly to prefetch the renditions of the images returned:

```python
def get_images_uploaded_by_user(user):
    return ImageModel.objects.filter(uploaded_by_user=user).prefetch_renditions()
```

The above will prefetch all renditions even if we may not need them.

If images in your project tend to have very large numbers of renditions, and you know in advance the ones you need, you might want to consider specifying a set of filters to the `prefetch_renditions` method and only select the renditions you need for rendering. For example:

```python
def get_images_uploaded_by_user(user):
    # Only specify the renditions required for rendering
    return ImageModel.objects.filter(uploaded_by_user=user).prefetch_renditions(
        "fill-700x586", "min-600x400", "max-940x680"
    )
```

### Non Image Querysets

If you’re working with a non Image Model, you can make use of Django’s built-in `prefetch_related()` queryset method to prefetch renditions.

For example, say you were rendering a list of events (with thumbnail images for each). Your code might look something like this:

```python
def get_events():
    return EventPage.objects.live().select_related("listing_image")
```

The above can be modified slightly to prefetch the renditions for listing images:

```python
def get_events():
    return EventPage.objects.live().select_related("listing_image").prefetch_related("listing_image__renditions")
```

If you know in advance the renditions you’ll need, you can filter the renditions queryset to use:

```python
from django.db.models import Prefetch
from wagtail.images import get_image_model


def get_events():
    Image = get_image_model()
    filters = ["fill-300x186", "fill-600x400", "fill-940x680"]

    # `Prefetch` is used to fetch only the required renditions
    prefetch_images_and_renditions = Prefetch(
        "listing_image",
        queryset=Image.objects.prefetch_renditions(*filters)
    )
    return EventPage.objects.live().prefetch_related(prefetch_images_and_renditions)
```

<a id="image-rendition-methods"></a>

## Model methods involved in rendition generation

The following `AbstractImage` model methods are involved in finding and generating renditions. If using a custom image model, you can customize the behavior of either of these methods by overriding them on your model:

<a id="module-wagtail.images.models"></a>

### *class* wagtail.images.models.AbstractImage

#### get_rendition(filter: Filter | [str](https://docs.python.org/3/library/stdtypes.html#str)) → [AbstractRendition](custom_image_model.md#wagtail.images.models.AbstractRendition)

Returns a `Rendition` instance with a `file` field value (an
image) reflecting the supplied `filter` value and focal point values
from this object.

Note: If using custom image models, an instance of the custom rendition
model will be returned.

#### find_existing_rendition(filter: Filter) → [AbstractRendition](custom_image_model.md#wagtail.images.models.AbstractRendition)

Returns an existing `Rendition` instance with a `file` field value
(an image) reflecting the supplied `filter` value and focal point
values from this object.

If no such rendition exists, a `DoesNotExist` error is raised for the
relevant model.

Note: If using custom image models, an instance of the custom rendition
model will be returned.

#### create_rendition(filter: Filter) → [AbstractRendition](custom_image_model.md#wagtail.images.models.AbstractRendition)

Creates and returns a `Rendition` instance with a `file` field
value (an image) reflecting the supplied `filter` value and focal
point values from this object.

This method is usually called by `Image.get_rendition()`, after first
checking that a suitable rendition does not already exist.

Note: If using custom image models, an instance of the custom rendition
model will be returned.

#### get_renditions(\*filters: Filter | [str](https://docs.python.org/3/library/stdtypes.html#str)) → [dict](https://docs.python.org/3/library/stdtypes.html#dict)[[str](https://docs.python.org/3/library/stdtypes.html#str), [AbstractRendition](custom_image_model.md#wagtail.images.models.AbstractRendition)]

Returns a `dict` of `Rendition` instances with image files reflecting
the supplied `filters`, keyed by filter spec patterns.

Note: If using custom image models, instances of the custom rendition
model will be returned.

#### find_existing_renditions(\*filters: Filter) → [dict](https://docs.python.org/3/library/stdtypes.html#dict)[Filter, [AbstractRendition](custom_image_model.md#wagtail.images.models.AbstractRendition)]

Returns a dictionary of existing `Rendition` instances with `file`
values (images) reflecting the supplied `filters` and the focal point
values from this object.

Filters for which an existing rendition cannot be found are omitted
from the return value. If none of the requested renditions have been
created before, the return value will be an empty dict.

#### create_renditions(\*filters: Filter) → [dict](https://docs.python.org/3/library/stdtypes.html#dict)[Filter, [AbstractRendition](custom_image_model.md#wagtail.images.models.AbstractRendition)]

Creates multiple `Rendition` instances with image files reflecting the supplied
`filters`, and returns them as a `dict` keyed by the relevant `Filter` instance.
Where suitable renditions already exist in the database, they will be returned instead,
so as not to create duplicates.

This method is usually called by `Image.get_renditions()`, after first
checking that a suitable rendition does not already exist.

Note: If using custom image models, an instance of the custom rendition
model will be returned.

#### generate_rendition_file(filter: Filter, \*, source: [django.core.files.File](https://docs.djangoproject.com/en/stable/ref/files/file/#django.core.files.File) = None) → [django.core.files.File](https://docs.djangoproject.com/en/stable/ref/files/file/#django.core.files.File)

Generates an in-memory image matching the supplied `filter` value
and focal point value from this object, wraps it in a `File` object
with a suitable filename, and returns it. The return value is used
as the `file` field value for rendition objects saved by
`AbstractImage.create_rendition()`.

If the contents of `self.file` has already been read into memory, the
`source` keyword can be used to provide a reference to the in-memory
`File`, bypassing the need to reload the image contents from storage.

NOTE: The responsibility of generating the new image from the original
falls to the supplied `filter` object. If you want to do anything
custom with rendition images (for example, to preserve metadata from
the original image), you might want to consider swapping out `filter`
for an instance of a custom `Filter` subclass of your design.
