layoutEngineering
Django
Batteries-included CRUD: where Django wins, ORM discipline and the N+1 trap, safe migrations, async limits.
1 item
Links1
01NotesNote
Where Django still wins
When you want batteries included: admin, auth, migrations, ORM, forms, and a mature ecosystem out of the box. For CRUD-heavy products with a real data model and an internal admin need, Django + DRF gets you to production faster than assembling the equivalent from FastAPI parts. This is why vorrei.io's core sits on Django.
ORM discipline — the N+1 problem
The single biggest Django performance trap. Accessing a related object inside a loop fires one query per iteration.
# BAD — 1 query for orders + N queries for each order.client
for order in Order.objects.all():
print(order.client.name)
# GOOD — 2 queries total
for order in Order.objects.select_related("client"):
print(order.client.name)
select_related→ SQL JOIN, for forward FK / one-to-one.prefetch_related→ separate query + Python join, for reverse FK / many-to-many.- Catch these in development with
django-debug-toolbaror by asserting query counts in tests (assertNumQueries).
Query efficiency
.only()/.defer()to limit columns on wide tables..values()/.values_list()when you don't need model instances.bulk_create/bulk_updateinstead of per-row saves.QuerySet.iterator()for large result sets to avoid loading everything into memory.- Push aggregation into the DB with
annotate()+Sum/Countrather than computing in Python.
Migrations
- Keep them small and reviewed. A migration that adds a non-null column without a default locks the table on large datasets — add the column nullable, backfill, then constrain.
- For zero-downtime, separate schema changes from data backfills, and run backfills in batches.
Async caveats
- Django's async support is real but partial. The ORM is not fully async; calls inside async views need
sync_to_async, and you don't get true async DB I/O the way you do with SQLAlchemy async. - Rule of thumb: if a service is genuinely async-heavy (lots of concurrent outbound I/O), FastAPI fits better. If it's CRUD + admin, stay sync Django and scale with more workers.