Django Modern REST¶
Django Modern REST (DMR) is a typed REST framework for Django with sync and async support and OpenAPI schema generation. Use imgproxykit’s Django shortcuts in DMR controllers to return image URLs and named variants in typed response models.
Explore the DMR getting started guide and the project on GitHub.
Installation¶
In your DMR project, install imgproxykit with Django support:
uv add 'imgproxykit[django]'
poetry add 'imgproxykit[django]'
pip install 'imgproxykit[django]'
The integration uses the Django shortcuts directly. No DMR-specific plugin
or addition to INSTALLED_APPS is required.
Configuration¶
Define IMGPROXYKIT in your Django settings. These settings are shared with
the Django integration:
from imgproxykit import Transform
from imgproxykit.integrations.django import SettingsDict
thumbnail = Transform(width=300, height=300, format='webp')
IMGPROXYKIT: SettingsDict = {
'client': { # (1)!
'base_url': 'https://imgproxy.example.com',
'key': '736563726574', # (2)!
'salt': '73616c74',
},
'transforms': {'thumbnail': thumbnail}, # (3)!
'variants': { # (4)!
'product': {
'small': thumbnail,
'large': Transform(width=1280, format='webp'),
},
},
}
Configure the shared client with your imgproxy server’s URL.
Use your server’s hex-encoded key and salt, or omit both if the server accepts unsigned URLs.
Define the
thumbnailtransformation used by the URL example.Define the
productvariant set used by the variants example.
Return an image URL¶
Generate a URL with imgproxy_url and return it in a Pydantic response model.
URL generation makes no network requests; imgproxy processes the image when
its URL is requested.
The examples use PydanticFastSerializer for JSON requests and responses.
See DMR’s Pydantic plugin guide
for serializer options.
from typing import Final
from dmr import Controller
from dmr.plugins.pydantic import PydanticFastSerializer
from pydantic import BaseModel
from imgproxykit.integrations.django import imgproxy_url
_SOURCE_URL: Final = 'https://originals.example.com/photo.jpg'
class ImageResponse(BaseModel):
"""Generated image URL."""
image: str
class ImageController(Controller[PydanticFastSerializer]):
"""Serve a transformed image URL."""
def get(self) -> ImageResponse:
"""Return a transformed image URL."""
image = imgproxy_url(_SOURCE_URL, 'thumbnail') # (1)!
return ImageResponse(image=image) # (2)!
Apply
IMGPROXYKIT['transforms']['thumbnail']to the source image.Return the generated URL as a string in the response model.
See DMR’s guides to controllers and path parameters for request parsing and handler definitions.
Return variants¶
For several image sizes, use imgproxy_variants and a nested response model.
Keep the imports and _SOURCE_URL from the previous example,
replacing the shortcut import with
from imgproxykit.integrations.django import imgproxy_variants:
class ProductImages(BaseModel):
"""Named image variants exposed by the API."""
small: str
large: str
class ImageResponse(BaseModel):
"""Named image variants."""
images: ProductImages # (1)!
class ImageController(Controller[PydanticFastSerializer]):
"""Serve named image variants."""
def get(self) -> ImageResponse:
"""Return the configured image variants."""
images = imgproxy_variants(_SOURCE_URL, 'product') # (2)!
return ImageResponse(images=ProductImages(**images)) # (3)!
Expose
smallandlargeas named fields in the response model and its OpenAPI schema.Generate URLs with
IMGPROXYKIT['variants']['product'].Validate the generated mapping against the response model. Keep its fields in sync with the configured variant names.
Use images: dict[str, str] and return the mapping directly when variant
names can vary. A dedicated model describes a fixed set of fields in the API.
See DMR’s OpenAPI guide
to publish the schema and interactive API documentation.
Model file fields¶
For a product loaded from your database, pass product.image directly to
imgproxy_url in the controller. Here, Product is your Django model
with an optional image field. ProductPath declares a product_id: int
path parameter using a Pydantic model. Imports, the Django model, path model,
and the route are omitted from this snippet:
class ProductResponse(BaseModel):
"""Product with an optional image URL."""
id: int
image: str | None
class ProductController(Controller[PydanticFastSerializer]):
"""Serve a product with its image URL."""
def get(self, parsed_path: Path[ProductPath]) -> ProductResponse:
"""Return a product and transform its image when present."""
product = get_object_or_404(Product, pk=parsed_path.product_id)
return ProductResponse(
id=product.pk,
image=(
imgproxy_url(product.image, 'thumbnail')
if product.image # (1)!
else None
),
)
Generate a URL only when the file field has an associated file; otherwise return
None, serialized as JSONnull.
Without the empty-field check, the default source
resolver raises ValueError for a field without an associated file.
Source resolution¶
Both shortcuts use the shared Django source resolver: strings are passed
unchanged and model file fields use .url. Relative URLs are not expanded
automatically. See Django to configure relative URLs and storage URIs.
Next steps¶
DMR documentation covers controllers, validation, serializers, and API schemas.
DMR on GitHub provides the source code, issues, and contribution guide.
Variants describes reusable variant sets.
Django documents the shared client and shortcuts.