Skip to main content

Asynchronous Tortoise ORM field for handling image uploads with cropping, caching, and support for AWS S3 or local storage.

Project description

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!

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

tortoise_imagefield-0.2.0.tar.gz (26.5 kB view details)

Uploaded Source

Built Distribution

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

tortoise_imagefield-0.2.0-py3-none-any.whl (25.7 kB view details)

Uploaded Python 3

File details

Details for the file tortoise_imagefield-0.2.0.tar.gz.

File metadata

  • Download URL: tortoise_imagefield-0.2.0.tar.gz
  • Upload date:
  • Size: 26.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for tortoise_imagefield-0.2.0.tar.gz
Algorithm Hash digest
SHA256 3efa448189eea1030739d2c1ef3f657614303cfd1327bf7cae237c5092c76f09
MD5 ed397c784112f1173a44ef4e16b02190
BLAKE2b-256 4c8fcc3bbbafd9605180d976398cde43194a14aaf00d85c73833828880558e23

See more details on using hashes here.

File details

Details for the file tortoise_imagefield-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for tortoise_imagefield-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bf640eb8f23b6f8724e9ab39deb8a0a6349af121ee433288cb4dad28f13589fa
MD5 69be23ba7aa4e47e8b10508d73ae2f93
BLAKE2b-256 3fd66222ec8130617332d99ae20001dcc88183c4cdda49f3c05a1754de9fedf3

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