Management Commands
easy-thumbnails provides management commands to help maintain the thumbnail database cache and files on disk.
thumbnail storages
Usage:
python manage.py thumbnail storages
Lists every storage alias configured in Django’s STORAGES setting
together with its computed storage hash, one <alias>: <storage_hash>
line per storage.
This is useful for identifying which alias a Source.storage_hash
value corresponds to, and as a prerequisite step before running
thumbnail cleanup –delete-with-missing-storage.
Examples
List all configured storages:
python manage.py thumbnail storages
Example output:
default: 275876e34cf609db8f4c1b0c56dfd4ba
media: 1e5f5210a4bec7dc9a1c0e3c1c2e7f6d
thumbnail cleanup
Usage:
python manage.py thumbnail cleanup [options]
Scans every Source record in the database and checks whether the
corresponding source image still exists on its configured storage backend.
For any source that is no longer present, the command:
Deletes each associated thumbnail files from disk.
Removes the
Sourcerecord (and its associatedThumbnailrecords) from the database via cascade delete.
This is useful for keeping the database Source and Thumbnail records
consistent and reclaiming disk space after image files have been removed
outside of Django (e.g., direct filesystem deletion, storage bucket cleanup).
Options
--dry-runReport what would be deleted without making any changes to the database or filesystem. The statistics summary is still printed at the end. Use this to audit the scope of a cleanup before committing.
--last-n-days NRestrict the scan to
Sourcerecords whosemodifieddate falls within the last N days (today inclusive). Records older than N days are left untouched. Default:0(scan all records).Note
The
modifiedfield is updated each time a thumbnail is generated or retrieved for that source — not when the source file was originally uploaded. A source that was accessed recently may have amodifieddate much newer than its actual creation date.--path PREFIXRestrict the scan to
Sourcerecords whose stored name begins with PREFIX. This is a literal string prefix match against the name as stored in the database — not a filesystem glob.To target a directory, include a trailing slash:
python manage.py thumbnail cleanup --path uploads/avatars/
--delete-with-missing-storageDelete
Sourcerecords (and their associatedThumbnailrecords) whose stored storage hash cannot be matched to any alias currently in Django’sSTORAGESsetting. This is useful after a storage backend has been removed from configuration, leaving behind orphaned rows that would otherwise be skipped.Can be combined with
--dry-runto preview the count before deleting, and with--last-n-daysor--pathto limit scope. Use the thumbnail storages command to see which storage hashes are currently recognised.Warning
Only use this flag if you are certain the unrecognised storage hash corresponds to a backend that has been intentionally removed. If a storage alias is temporarily missing due to a misconfiguration, running this flag will permanently delete the associated database records.
Examples
Preview what would be cleaned up without making changes:
python manage.py thumbnail cleanup --dry-run
Clean up only records modified in the last 7 days:
python manage.py thumbnail cleanup --last-n-days 7
Restrict cleanup to a specific path prefix, silently:
python manage.py thumbnail cleanup --path uploads/user_photos/ --verbosity 0
Preview how many sources reference a removed storage backend:
python manage.py thumbnail cleanup --delete-with-missing-storage --dry-run
Remove all sources tied to a removed storage backend:
python manage.py thumbnail cleanup --delete-with-missing-storage
Output
After the scan, the command always prints a statistics summary:
2026-04-16 14:32 ------------------------------
Sources checked: 1024
Sources with missing storage deleted: 12
Source references deleted from DB: 37
Thumbnails deleted from disk: 92
(Completed in 4 seconds)
Note
“Thumbnails deleted from disk” counts thumbnails whose database entries were removed. A thumbnail file that was already absent from disk is still counted if its database entry is cleaned up.
Note
“Sources with missing storage deleted” is only non-zero when
--delete-with-missing-storage is passed.
Caveats
Storage backend must be reachable.
The command calls storage.exists() for each source path. If a
storage backend raises an exception (e.g., a transient network error
with a remote storage), that source is treated as unknown rather than
missing: the error is logged to stderr and the source is skipped, not
deleted. Ensure all configured storage backends are reliably reachable
before running against a large dataset, since sources affected by
transient errors are simply left for the next run rather than cleaned up.
Unrecognised storage hashes are skipped by default.
Each Source record stores a hash of the storage backend used when
it was saved. If that hash cannot be matched to any alias currently
in Django’s STORAGES setting — for example, after a storage backend
has been removed — the source is skipped rather than deleted. A message
is printed to stdout. Pass --delete-with-missing-storage to delete
these records instead.
No signals are fired.
The command deletes Source and Thumbnail records directly via
QuerySet.delete(). Any pre_delete or post_delete signal
handlers attached to those models in your project will not be called.
Orphaned thumbnail files are not removed.
If a thumbnail file exists on disk but its Source record has already
been deleted from the database, the command will not find or remove it.
The command only works from the database outward, not from the filesystem
inward.
Requires Django 4.2+ ``STORAGES`` configuration.
The command reads settings.STORAGES directly. Projects still using
the legacy DEFAULT_FILE_STORAGE string setting will encounter an
error.
thumbnail source_files
Usage:
python manage.py thumbnail source_files [options]
Lists the file paths currently stored in every ThumbnailerImageField
across all installed apps. Useful for auditing which source images are
tracked and for feeding into other tools.
Options
-s/--summaryInstead of printing one path per line, print the count of non-empty values for each field, one field per line, followed by a total on stderr.
--include SPECRestrict output to fields matching SPEC. SPEC can be:
app— matches all fields in the named appapp.model— matches all fields on the named modelapp.model.field— matches a specific field
Wildcards (
*,?) are supported in each component. May be repeated to include multiple specs.--exclude SPECExclude fields matching SPEC from output. Same format as
--include. May be repeated.
Examples
List every source path:
python manage.py thumbnail source_files
Count per field (summary mode):
python manage.py thumbnail source_files --summary
Restrict to a single app:
python manage.py thumbnail source_files --include myapp
thumbnail source_cleanup
Usage:
python manage.py thumbnail source_cleanup [options]
Compares every Source record in the database against the current
values stored in ThumbnailerImageField columns across all installed
apps. Any Source whose (storage_hash, name) pair does not match
a field value is considered orphaned and deleted.
This is useful after a ThumbnailerImageField is removed or renamed,
or after rows are deleted directly from the database, leaving Source
records with no corresponding model field value.
Note
Deleting a Source record cascades to its associated Thumbnail
records in the database, but does not remove thumbnail files from
storage.
Options
--dry-runPrint the name of each
Sourcerecord that would be deleted, without making any changes to the database.
Examples
Preview what would be removed:
python manage.py thumbnail source_cleanup --dry-run
Remove all orphaned Source records:
python manage.py thumbnail source_cleanup
thumbnail regenerate
Usage:
python manage.py thumbnail regenerate [options]
Finds every non-empty ThumbnailerImageField value across all installed
apps, purges any cached thumbnails for that source (database rows and
files), then regenerates every alias configured for its field, model, or
app via THUMBNAIL_ALIASES (see
Thumbnail aliases).
This is useful after changing an alias’s options (e.g. its size), since
existing thumbnails are otherwise left in place under their old computed
filename rather than replaced, or simply to force a bulk refresh of
thumbnails without waiting for each one to be requested individually.
Note
Only options registered as aliases are regenerated. Ad hoc option sets
used directly via {% thumbnail %} that don’t match a configured
alias are purged along with everything else, but not recreated by this
command — they will regenerate the next time they’re requested, the
same as if you had called
delete_thumbnails()
yourself.
Options
--dry-runReport what would be purged and regenerated without making any changes. The statistics summary is still printed at the end.
--path PREFIXRestrict regeneration to source names beginning with PREFIX. Same literal string prefix matching as thumbnail cleanup –path.
--include-globalAlso regenerate project-wide aliases (aliases registered with no specific target), in addition to field/model/app specific ones. This mirrors the difference between the
generate_aliases()andgenerate_aliases_global()pregeneration signal handlers. Off by default, since global aliases can apply broadly across a project.--include SPECRestrict regeneration to fields matching SPEC. Same
app/app.model/app.model.fieldglob syntax as thumbnail source_files –include. May be repeated.--exclude SPECExclude fields matching SPEC from regeneration. Same format as
--include. May be repeated.
Examples
Preview what a full regeneration would do:
python manage.py thumbnail regenerate --dry-run
Regenerate thumbnails for a single app only:
python manage.py thumbnail regenerate --include myapp
Regenerate only sources under a given path, including global aliases:
python manage.py thumbnail regenerate --path uploads/avatars/ --include-global
Output
After the run, the command always prints a statistics summary:
2026-04-16 14:32 ------------------------------
Sources processed: 128
Thumbnails purged: 140
Aliases regenerated: 132
Errors: 0
(Completed in 3 seconds)
Note
“Thumbnails purged” counts previously cached thumbnails removed per source (including ad hoc ones with no matching alias). “Aliases regenerated” counts alias thumbnails created to replace them. These numbers can differ, since not every purged thumbnail has a corresponding alias, and dry runs report what would happen without making changes.
Caveats
A source with an error is skipped, not fatal. If a source image can’t be read (e.g. the file is missing, corrupted, or its storage is unreachable), the error is logged to stderr and counted, and the command continues with the next source rather than aborting.
No signals are fired for the purge step.
Thumbnails are removed directly via
delete_thumbnails(), not
through model delete(), so no pre_delete/post_delete signal
handlers run for the removed Thumbnail records.