Tortoise ImageField
Tortoise ImageField is an image storage solution for Tortoise ORM that supports file uploads, Base64 encoding, and external URLs. It allows storing images locally or in AWS S3 + CloudFront, and includes caching, cropping, and WebP conversion for optimized performance.
✨ Features
- Supports multiple input formats: File Uploads, Base64, and external URLs.
- Storage options: Local filesystem or AWS S3 with CloudFront.
- Automatic caching and WebP conversion to optimize image delivery.
- Built-in cropping support to generate resized images on demand.
- Automatic filename renaming and slugify based on a selected model field.
- Asynchronous interaction with S3 for efficient uploads, deletions, and retrievals.
- Fully asynchronous image processing for non-blocking operations and better scalability.
📌 Installation
pip install tortoise-imagefield
🚀 Quick Start
Define a Model with ImageField
from tortoise import fields, Model
from tortoise_imagefield import ImageField, StorageTypes
class Item(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=255)
image = ImageField() # Store locally
s3_image = ImageField(storage_type=StorageTypes.S3_AWS) # Store in AWS S3
image_ugc = ImageField(directory_name="ugc", field_for_name="name")
🛠 ImageField Parameters
| Parameter | Description | Default |
|---|---|---|
storage_type |
Defines the storage backend (StorageTypes.LOCAL or StorageTypes.S3_AWS). |
StorageTypes.LOCAL |
directory_name |
Custom directory name for storing images. If not set, defaults to {class_name}_images. |
{class_name}_images |
field_for_name |
Specifies a model field that will be used to generate a slugified filename. | None |
Automatically Added Methods in Models
When using ImageField, the following helper methods are dynamically added to your model, based on the field name.
🔹 Generated Methods
| Method Name | Description | Parameters |
|---|---|---|
get_{field_name}_webp |
Returns the WebP-optimized cached image URL. | width: int – Desired width height: int – Desired height position: str = "center" – Cropping position ("center", "top", "left") return_path: bool = False – If True, returns the local path instead of the URL. |
get_{field_name}_url |
Returns the original uploaded image URL. | No parameters |
get_{field_name}_path |
Returns the original file path (for local storage) or S3 key (for AWS S3). | No parameters |
Image Processing
Crop & Convert to WebP (Cached)
item = await Item.get(id=1)
cached_image_webp = await item.get_image_webp(200, 200)
cached_s3_image_webp = await item.get_image_webp(100, 100)
🔹 Example Usage
Assume the model has an ImageField named image:
item = await Item.get(id=1)
# Get WebP-optimized URL (resized to 200x200)
webp_url = await item.get_image_webp(200, 200)
print(webp_url) # Example: "https://cdn.example.com/images/image_200x200.webp"
# Get the original image URL
original_url = await item.get_image_url()
print(original_url) # Example: "https://s3.example.com/uploads/image.jpg"
# Get the file path (local) or S3 key
image_path = await item.get_image_path()
print(image_path) # Example: "/uploads/image.jpg" or "s3://bucket-name/uploads/image.jpg"
Upload an Image
Upload via File Upload
await Item.create(name="Test Item", image=file)
Upload via Base64 string
await Item.create(name="Test Item", image="data:image/png;base64,iVBORw...")
Upload via External URL
await Item.create(name="Test Item", image="https://example.com/image.jpg")
Upload via Fast API
@app.post("/upload/")
async def upload_image(
name: str = Form(...),
image: UploadFile = File(...),
s3_image: UploadFile = File(...)):
"""Handles image upload and saves it to the database with Upload File."""
item = await Item.create(name=name, image=image, s3_image=s3_image)
return {"id": item.id,
"name": item.name,
"image_url": await item.get_image_webp(200, 200),
"s3_image_url": await item.get_s3_image_webp(250, 250)
}
@app.post("/items/")
async def create_item(request: Request):
"""Handles image upload and saves it to the database with base64 or URL."""
data = await request.json()
item = await Item.create(**data)
return {"id": item.id,
"name": item.name,
"image_url": await item.get_image_webp(200, 200),
"s3_image_url": await item.get_s3_image_webp(150)
}
🔧 Configuration via .env and Manual Settings
📂 .env File Configuration
You can configure storage settings using an .env file:
DATABASE_URL = sqlite://db.sqlite3
IMAGES_UPLOAD_DIR = uploads
IMAGES_UPLOAD_URL = uploads
S3_BUCKET =
S3_REGION =
S3_ACCESS_KEY =
S3_SECRET_KEY =
S3_CDN_DOMAIN =
S3_ACL_TYPE = private #default
# or change to "public-read"
from tortoise_imagefield.config import Config, S3AclType
cfg = Config()
cfg.s3_acl_type = S3AclType.PUBLIC_READ.value
# change s3 files cashing to RedisCache (default SimpleMemoryCache)
from aiocache import RedisCache
cfg.s3_cache = RedisCache # with settings
The package uses public access for S3, as it is intended to be a simple storage solution for public images.
📖 For a complete guide, see S3 Configuration.
Make sure to load these variables in your application:
from dotenv import load_dotenv
import os
load_dotenv()
print(os.getenv("S3_BUCKET")) # Prints the configured S3 bucket
⚙️ Manual Configuration via Config
You can also configure the library manually:
from tortoise_imagefield import Config
cfg = Config()
cfg.image_dir = "app/uploads"
cfg.image_url = "static"
Config Class:
class Config:
image_url: str
image_dir: str
s3_bucket: Optional[str]
s3_region: Optional[str]
s3_access_key: Optional[str]
s3_secret_key: Optional[str]
s3_cdn_domain: Optional[str]
📜 License
This project is licensed under the MIT License.
🚀 Now you're ready to optimize image handling with Tortoise ORM!
Metadata
Release files for tortoise-imagefield 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tortoise_imagefield-0.2.0.tar.gz | 26.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tortoise_imagefield-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 52.3 kB
Release files / tortoise_imagefield-0.2.0.tar.gz
| Download URL | tortoise_imagefield-0.2.0.tar.gz |
|---|---|
| Size | 26.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3efa448189eea1030739d2c1ef3f657614303cfd1327bf7cae237c5092c76f09
|
|
BLAKE2b-256 checksum How to use checksums |
4c8fcc3bbbafd9605180d976398cde43194a14aaf00d85c73833828880558e23
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|
Release files / tortoise_imagefield-0.2.0-py3-none-any.whl
| Download URL | tortoise_imagefield-0.2.0-py3-none-any.whl |
|---|---|
| Size | 25.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bf640eb8f23b6f8724e9ab39deb8a0a6349af121ee433288cb4dad28f13589fa
|
|
BLAKE2b-256 checksum How to use checksums |
3fd66222ec8130617332d99ae20001dcc88183c4cdda49f3c05a1754de9fedf3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|