Comprehensive Django toolkit for Cloudflare Images with direct creator upload, transformations, and management
Project description
Django Cloudflare Images Toolkit
A comprehensive Django toolkit for Cloudflare Images with direct creator upload, advanced image management, transformations, and secure upload workflows.
Features
- Direct Creator Upload: Secure image uploads without exposing API keys to clients
- Comprehensive Image Management: Track upload status, metadata, and variants
- Advanced Transformations: Full support for Cloudflare Images transformations
- Template Tags: Easy integration with Django templates
- RESTful API: Complete API for image management
- Webhook Support: Handle Cloudflare webhook notifications
- Management Commands: CLI tools for maintenance and cleanup
- Type Safety: Full type hints throughout the codebase
- Responsive Images: Built-in support for responsive image delivery
Installation
Using uv (Recommended)
# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create a new project or navigate to existing one
uv init my-project
cd my-project
# Add django-cloudflareimages-toolkit to your project
uv add django-cloudflareimages-toolkit
# Or install in development mode from source
uv add --editable .
Using pip
pip install django-cloudflareimages-toolkit
Quick Start
1. Add to Django Settings
# settings.py
INSTALLED_APPS = [
# ... your other apps
'rest_framework',
'django_cloudflareimages_toolkit',
]
# Cloudflare Images Configuration
CLOUDFLARE_IMAGES = {
'ACCOUNT_ID': 'your-cloudflare-account-id',
'API_TOKEN': 'your-cloudflare-api-token',
'BASE_URL': 'https://api.cloudflare.com/client/v4', # Optional
'DEFAULT_EXPIRY_MINUTES': 30, # Optional
'REQUIRE_SIGNED_URLS': True, # Optional
'WEBHOOK_SECRET': 'your-webhook-secret', # Optional
'MAX_FILE_SIZE_MB': 10, # Optional
}
# REST Framework (if not already configured)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
2. Add URL Patterns
# urls.py
from django.urls import path, include
urlpatterns = [
# ... your other URLs
path('cloudflare-images/', include('django_cloudflareimages_toolkit.urls')),
]
3. Run Migrations
python manage.py makemigrations django_cloudflareimages_toolkit
python manage.py migrate
4. Django Admin Integration (Optional)
The module includes comprehensive Django admin integration for monitoring and managing images:
# settings.py - Admin is automatically registered when the app is installed
# No additional configuration needed
# To access the admin interface:
# 1. Create a superuser: python manage.py createsuperuser
# 2. Visit /admin/ and navigate to "Cloudflare Images" section
Usage
API Endpoints
Create Upload URL
POST /cloudflare-images/api/upload-url/
Content-Type: application/json
{
"metadata": {"type": "avatar", "user_id": "123"},
"require_signed_urls": true,
"expiry_minutes": 60,
"filename": "avatar.jpg"
}
Response:
{
"id": "uuid-here",
"cloudflare_id": "cloudflare-image-id",
"upload_url": "https://upload.imagedelivery.net/...",
"expires_at": "2024-01-01T12:00:00Z",
"status": "pending"
}
List Images
GET /cloudflare-images/api/images/
Check Image Status
POST /cloudflare-images/api/images/{id}/check_status/
Get Image Statistics
GET /cloudflare-images/api/stats/
Template Tags
Load the template tags in your templates:
{% load cloudflare_images %}
Basic Image Transformations
<!-- Simple thumbnail -->
{% cf_thumbnail image.public_url 200 %}
<!-- Avatar with transformations -->
{% cf_avatar user.profile_image.public_url 100 %}
<!-- Custom transformations -->
{% cf_image_transform image.public_url width=800 height=600 fit='cover' quality=85 %}
<!-- Hero image -->
{% cf_hero_image banner.public_url 1920 800 %}
Responsive Images
<!-- Responsive image with srcset -->
{% cf_responsive_img image.public_url "Alt text" "img-responsive" "320,640,1024" %}
<!-- Picture element for different screen sizes -->
{% cf_picture image.public_url "Alt text" "responsive-img" 320 768 1200 %}
<!-- Generate srcset manually -->
<img src="{% cf_responsive_image image.public_url 800 %}"
srcset="{% cf_srcset image.public_url '320,640,1024,1920' %}"
sizes="{% cf_sizes 'max-width: 768px:100vw,default:800' %}"
alt="Responsive image">
Upload Form
<!-- Simple upload form -->
{% cf_upload_form %}
<!-- Custom upload form -->
{% cf_upload_form "my-upload-form" "custom-class" "Choose File" %}
Image Gallery
{% cf_image_gallery user_images 4 250 %}
Python API
Creating Upload URLs
from django_cloudflareimages_toolkit.services import cloudflare_service
# Create upload URL
image = cloudflare_service.create_direct_upload_url(
user=request.user,
metadata={'type': 'product', 'category': 'electronics'},
require_signed_urls=True,
expiry_minutes=60
)
print(f"Upload URL: {image.upload_url}")
print(f"Expires at: {image.expires_at}")
Image Transformations
from django_cloudflareimages_toolkit.transformations import CloudflareImageTransform
# Build transformation URL
transform = CloudflareImageTransform(image.public_url)
thumbnail_url = (transform
.width(300)
.height(300)
.fit('cover')
.quality(85)
.build())
# Use predefined variants
from django_cloudflareimages_toolkit.transformations import CloudflareImageVariants
avatar_url = CloudflareImageVariants.avatar(image.public_url, 100)
hero_url = CloudflareImageVariants.hero_image(image.public_url, 1920, 800)
Checking Image Status
# Check if image is uploaded
if image.is_uploaded:
print(f"Image available at: {image.public_url}")
# Refresh status from Cloudflare
cloudflare_service.check_image_status(image)
Management Commands
Clean Up Expired Images
# Dry run to see what would be cleaned up
python manage.py cleanup_expired_images --dry-run
# Mark expired images as expired
python manage.py cleanup_expired_images
# Delete old expired images (older than 7 days)
python manage.py cleanup_expired_images --delete --days 7
Django Admin Interface
The module provides a comprehensive Django admin interface for monitoring and managing Cloudflare Images:
Features:
- Image List View: View all images with status, thumbnails, and key information
- Detailed Image View: Complete image details with transformation examples
- Status Management: Check status, refresh from Cloudflare, mark as expired
- Bulk Actions: Perform operations on multiple images at once
- Upload Logs: View complete audit trail for each image
- Statistics Dashboard: Overview of upload success rates and system health
- Search & Filtering: Find images by ID, filename, user, status, or date
- Image Previews: Thumbnail previews and full-size image viewing
- Transformation Examples: Live examples of different image transformations
Admin Actions:
- Check Status from Cloudflare: Refresh status for selected images
- Mark as Expired: Manually mark images as expired
- Delete from Cloudflare: Remove images from Cloudflare and local database
- Refresh All Pending/Draft: Update status for all non-final images
Access the Admin:
- Create a superuser:
python manage.py createsuperuser - Visit
/admin/in your browser - Navigate to "Cloudflare Images" section
- Manage images through the intuitive interface
Webhooks
Configure webhooks in your Cloudflare dashboard to point to:
https://yourdomain.com/cloudflare-images/api/webhook/
The webhook endpoint will automatically update image status when uploads complete.
📋 For detailed webhook setup instructions, see the Webhook Configuration documentation
This guide includes:
- Step-by-step Cloudflare dashboard configuration
- Django settings and URL configuration
- Security considerations and signature validation
- Troubleshooting common webhook issues
- Local development setup with ngrok
Advanced Features
Custom Image Variants
from django_cloudflareimages_toolkit.transformations import CloudflareImageTransform
def create_product_variant(image_url: str, size: int = 400) -> str:
"""Create a product image with white background and border."""
return (CloudflareImageTransform(image_url)
.width(size)
.height(size)
.fit('pad')
.background('ffffff')
.border(2, 'cccccc')
.quality(90)
.build())
Responsive Image Sets
from django_cloudflareimages_toolkit.transformations import CloudflareImageUtils
# Generate srcset for responsive images
srcset = CloudflareImageUtils.get_srcset(
image.public_url,
[320, 640, 1024, 1920],
quality=85
)
# Generate sizes attribute
sizes = CloudflareImageUtils.get_sizes_attribute({
'max-width: 768px': 100, # 100vw on mobile
'max-width: 1024px': 50, # 50vw on tablet
'default': 800 # 800px on desktop
})
Bulk Operations
from django_cloudflareimages_toolkit.models import CloudflareImage
# Bulk status check
images = CloudflareImage.objects.filter(status='pending')
for image in images:
try:
cloudflare_service.check_image_status(image)
except Exception as e:
print(f"Failed to check {image.cloudflare_id}: {e}")
Configuration Options
| Setting | Default | Description |
|---|---|---|
ACCOUNT_ID |
Required | Your Cloudflare Account ID |
API_TOKEN |
Required | Cloudflare API Token with Images permissions |
BASE_URL |
https://api.cloudflare.com/client/v4 |
Cloudflare API base URL |
DEFAULT_EXPIRY_MINUTES |
30 |
Default expiry time for upload URLs |
REQUIRE_SIGNED_URLS |
True |
Require signed URLs by default |
WEBHOOK_SECRET |
None |
Secret for webhook signature validation |
MAX_FILE_SIZE_MB |
10 |
Maximum file size in MB |
Models
CloudflareImage
Tracks image uploads and their metadata:
cloudflare_id: Unique Cloudflare image identifieruser: Associated Django user (optional)upload_url: One-time upload URLstatus: Current upload status (pending, draft, uploaded, failed, expired)metadata: Custom metadata JSONvariants: Available image variantsexpires_at: Upload URL expiration time
ImageUploadLog
Tracks events and changes for debugging:
image: Associated CloudflareImageevent_type: Type of event (upload_url_created, status_checked, etc.)message: Human-readable messagedata: Additional event data
Development
Setting up with uv
# Clone the repository
git clone https://github.com/Pacificient-Labs/django-cloudflareimages-toolkit.git
cd django-cloudflareimages-toolkit
# Install dependencies
uv sync
# Install development dependencies
uv sync --group dev
# Run tests
uv run pytest
# Format code
uv run black .
uv run isort .
# Type checking
uv run mypy django_cloudflareimages_toolkit
Running Tests
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=django_cloudflareimages_toolkit
# Run specific test file
uv run pytest tests/test_services.py
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for your changes
- Run the test suite (
uv run pytest) - Format your code (
uv run black . && uv run isort .) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
- Documentation: https://django-cloudflareimages-toolkit.readthedocs.io/
- Issues: https://github.com/Pacificient-Labs/django-cloudflareimages-toolkit/issues
- Discussions: https://github.com/Pacificient-Labs/django-cloudflareimages-toolkit/discussions
Changelog
v1.0.0
- Initial release
- Direct Creator Upload support
- Comprehensive image transformations
- Template tags and filters
- RESTful API
- Webhook support
- Management commands
- Full type safety
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_cloudflareimages_toolkit-1.0.1.tar.gz.
File metadata
- Download URL: django_cloudflareimages_toolkit-1.0.1.tar.gz
- Upload date:
- Size: 126.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d454293bb95e64b96f807d86b49cab1bb5446af24159226a2da2ca64ac45dde0
|
|
| MD5 |
5691248a75a5da9378bf497f990a1a28
|
|
| BLAKE2b-256 |
d6559f49c8b9bb9b786826930f3c0ee8ebbf76ece8b0ca6af33ba4ace311e8a9
|
Provenance
The following attestation bundles were made for django_cloudflareimages_toolkit-1.0.1.tar.gz:
Publisher:
publish.yml on Pacficient-Labs/django-cloudflareimages-toolkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_cloudflareimages_toolkit-1.0.1.tar.gz -
Subject digest:
d454293bb95e64b96f807d86b49cab1bb5446af24159226a2da2ca64ac45dde0 - Sigstore transparency entry: 453040184
- Sigstore integration time:
-
Permalink:
Pacficient-Labs/django-cloudflareimages-toolkit@32ba6184e6914d8f6c2455d4e8f704c4c9e8de3d -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/Pacficient-Labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@32ba6184e6914d8f6c2455d4e8f704c4c9e8de3d -
Trigger Event:
release
-
Statement type:
File details
Details for the file django_cloudflareimages_toolkit-1.0.1-py3-none-any.whl.
File metadata
- Download URL: django_cloudflareimages_toolkit-1.0.1-py3-none-any.whl
- Upload date:
- Size: 35.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
923cf56b0ba606def45b1e6255420ae71ec24434cbe4fc058cc3d6d07f4f293b
|
|
| MD5 |
3d31713753169502ecbb3ccde0cf0132
|
|
| BLAKE2b-256 |
77a9a8ff2460231d9836294d0f2d26a9bca1d7aa3b6d75c8535867cd25cb4d55
|
Provenance
The following attestation bundles were made for django_cloudflareimages_toolkit-1.0.1-py3-none-any.whl:
Publisher:
publish.yml on Pacficient-Labs/django-cloudflareimages-toolkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_cloudflareimages_toolkit-1.0.1-py3-none-any.whl -
Subject digest:
923cf56b0ba606def45b1e6255420ae71ec24434cbe4fc058cc3d6d07f4f293b - Sigstore transparency entry: 453040192
- Sigstore integration time:
-
Permalink:
Pacficient-Labs/django-cloudflareimages-toolkit@32ba6184e6914d8f6c2455d4e8f704c4c9e8de3d -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/Pacficient-Labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@32ba6184e6914d8f6c2455d4e8f704c4c9e8de3d -
Trigger Event:
release
-
Statement type: