>Static Islands in a Dynamic Sea
Building typed Python classes on top of Django ORM with Mantle to solve fat models, N+1 queries, and type safety.
Carlton Gibson’s talk at DjangoCon Europe 2026 on building typed layers on top of Django’s ORM using Mantle.
The problem
Django models grow out of control. Display logic, queries, serialization, validation — all crammed into one class. The ORM fetches too much by default and N+1 queries are easy to hit. Static types don’t fit Django’s dynamic core — metaclasses, introspection, and dynamic attributes make type checkers unhappy.
The fix
Build typed dataclasses (using attrs) that define the exact shape of data you need. Mantle bridges from the ORM to those shapes efficiently.
from attrs import define
@define
class BookmarkData:
url: str
comment: str
favourite: bool
This is your “static island” — a plain typed class, no Django magic. Query it with Mantle:
from mantle import Query
bookmarks = Query(Bookmark.objects.all(), BookmarkData).all()
# type: list[BookmarkData]
Mantle generates the ORM query with only() applied — it fetches just the fields you declared. Nothing extra.
Nested related data solves N+1
@define
class UserData:
username: str
@define
class BookmarkData:
url: str
comment: str
favourite: bool
user: UserData
Mantle sees the nested UserData and auto-generates select_related("user") with only("user__username"). Two queries max, regardless of how many bookmarks.
DRF integration
Replace serializers with shape classes:
from mantle_drf.generics import ListCreateAPIView
@attrs.define
class BookmarkShape:
url: str
title: str
comment: str = ""
class BookmarkList(ListCreateAPIView):
queryset = Bookmark.objects.all()
shape_class = BookmarkShape # instead of serializer_class
GET returns shaped data, POST structures incoming JSON into your shape and persists it.
Key takeaways
- Don’t fight Django’s dynamic nature — build typed layers on top instead
- Mantle auto-optimizes queries — no manual
only(),select_related(), orprefetch_related() - Adopt incrementally — start with one view, one shape class
- DRY applies within concerns, not across them — it’s OK to “repeat” a field name in your model and your data shape