Skip to main content

Automatic image thumbnail generation for Django storages (local & S3).

Project description

django-storage-thumbnails

Automatically generate image thumbnails whenever a file is saved through a Django storage backend. Works with local filesystem storage and Amazon S3 (via django-storages).

Install

pip install django-storage-thumbnails          # local filesystem
pip install "django-storage-thumbnails[s3]"     # + S3 support

Configure

Add the sizes you want to your Django settings. Sizes accept either a (width, height) tuple or a "WxH" string:

THUMBNAIL_SIZES = {
    "small": (10, 10),
    "med": (20, 20),
}

Then point your model/field (or STORAGES) at a thumbnail-aware storage.

Local filesystem

from thumbnail_storage import ThumbnailFileSystemStorage

storage = ThumbnailFileSystemStorage()
name = storage.save("photos/cat.jpg", my_image_file)
# also writes: thumbnails/small/photos/cat.jpg, thumbnails/med/photos/cat.jpg

Amazon S3

from thumbnail_storage import ThumbnailS3Storage

storage = ThumbnailS3Storage(bucket_name="my-bucket")
storage.save("photos/cat.jpg", my_image_file)

In a model

from django.db import models
from thumbnail_storage import ThumbnailFileSystemStorage

class Photo(models.Model):
    image = models.ImageField(
        upload_to="photos/",
        storage=ThumbnailFileSystemStorage(),
    )

Getting thumbnail links

Thumbnails are stored under a dedicated thumbnails/<size>/ prefix so they can never collide with or overwrite a user's uploaded file. Deleting the original also removes its thumbnails.

storage.thumbnail_url("photos/cat.jpg", "small")
# -> "/media/thumbnails/small/photos/cat.jpg"

storage.get_thumbnails("photos/cat.jpg")
# -> {"small": "/media/thumbnails/small/photos/cat.jpg",
#     "med":   "/media/thumbnails/med/photos/cat.jpg"}

Use it with any backend

ThumbnailMixin can be mixed into any Django Storage subclass:

from thumbnail_storage import ThumbnailMixin
from storages.backends.azure_storage import AzureStorage

class ThumbnailAzureStorage(ThumbnailMixin, AzureStorage):
    pass

Async generation with Celery (S3)

For S3, you usually don't want to block the upload request while thumbnails are generated. Use the async storage: it saves the original immediately and hands the thumbnail work to a Celery worker, which re-reads the original from S3 — so only the file name travels over the broker, never the image bytes.

pip install "django-storage-thumbnails[s3,celery]"

Register the storage under a key in STORAGES and pass that key as alias (the worker uses it to rebuild the same backend):

# settings.py
STORAGES = {
    "default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
    "thumbnails": {
        "BACKEND": "thumbnail_storage.AsyncThumbnailS3Storage",
        "OPTIONS": {"alias": "thumbnails", "bucket_name": "my-bucket"},
    },
}
from django.core.files.storage import storages

storage = storages["thumbnails"]
storage.save("photos/cat.jpg", img)   # returns immediately; thumbnails follow

Make sure your Celery app autodiscovers thumbnail_storage.tasks, and that the worker can reach the same S3 bucket. If Celery isn't installed, generation quietly falls back to running inline.

Fetching while a thumbnail is still being made

Names are deterministic, so thumbnail_url() returns the URL right away — even before the worker finishes. Use it with a fallback to the original so there's no broken image in the brief window before the thumbnail exists:

<img src="{{ small_url }}" onerror="this.onerror=null; this.src='{{ original_url }}'">

Need a guaranteed "ready" signal or to generate sizes only on first view? The get_thumbnail_name and store_thumbnail methods are overridable — subclass to record a status row or to generate lazily, without forking the package.

How it works

On _save, if the saved file's extension is a known image type and THUMBNAIL_SIZES is non-empty, a thumbnail is generated for each size with Pillow (Image.thumbnail, which preserves aspect ratio — so a "10x10" size is a bounding box, not an exact crop) and saved under thumbnails/<key>/<name> in the same backend. Non-images and unreadable files are passed through untouched, and any per-size failure is logged and skipped without affecting the upload or the other sizes. Override thumbnail_prefix to change the namespace, or get_thumbnail_name / store_thumbnail to change naming or write behavior.

Cleanup on delete() removes the thumbnails for the current THUMBNAIL_SIZES / thumbnail_prefix. If you remove a size key or change the prefix later, thumbnails generated under the old config are not tracked and won't be cleaned up automatically — prune them out of band if needed.

Running the tests

pip install -e ".[test]"
pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_storage_thumbnails-0.1.1.tar.gz (12.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_storage_thumbnails-0.1.1-py3-none-any.whl (11.4 kB view details)

Uploaded Python 3

File details

Details for the file django_storage_thumbnails-0.1.1.tar.gz.

File metadata

  • Download URL: django_storage_thumbnails-0.1.1.tar.gz
  • Upload date:
  • Size: 12.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for django_storage_thumbnails-0.1.1.tar.gz
Algorithm Hash digest
SHA256 d82d969fe363d32449f164413121d12006651e9f7c6d6c36923b1e228646605e
MD5 b745fca106a6f5f9c164ddb53fed21b3
BLAKE2b-256 483c8c8d55893a0c580c1f62c48085f95706b63c5cd8c3ef73766528757624ce

See more details on using hashes here.

File details

Details for the file django_storage_thumbnails-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: django_storage_thumbnails-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 11.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for django_storage_thumbnails-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 dba1320782f794bf2fca46a99688353725f54cb683b3eef85e6825c0b52e2205
MD5 921eb815244cbde43a94e77a22e60fe5
BLAKE2b-256 c06fa7bc9fc9fad9bbe0dd83d38251b2aaa386312d7749b23f77721e672b599e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page