Best practices, tips and tricks around Python, Django, Django REST Framework, FastAPI and Flask. TDD, SOLID and DDD approaches for building solid backend APIs.
Anthony.D
Python Developer · Django · FastAPI · Flask · Freelance
Python Developer · Django · FastAPI · Flask · Freelance
Best practices, tips and tricks around Python, Django, Django REST Framework, FastAPI and Flask. TDD, SOLID and DDD approaches for building solid backend APIs.
Teams often claim “we have a REST API in place.” But when you look at the actual JSON responses, there are no links anywhere. Just raw data. That’s not REST, it’s CRUD exposed over HTTP. The difference comes down to one principle most developers overlook: HATEOAS. What Is HATEOAS in a REST API? HATEOAS stands for Hypermedia As The Engine Of Application State. It is one of the fundamental constraints of REST, defined by Roy Fielding in his 2000 dissertation, the same paper that coined the term REST itself. ...
Django ORM gives you two ways to add a computed value across a set of rows: annotate() with a classic aggregation (Max, Count, Sum…) or annotate() with a Window function. On the surface they look similar. In practice, they behave in fundamentally different ways — and picking the wrong one can break your entire filtering chain. GROUP BY with annotate(): rows that collapse When you combine values() and annotate() with an aggregation, Django generates a GROUP BY in SQL. The result: rows get merged, and you end up with one row per group. ...
When you have a list of identifiers and want to retrieve the corresponding instances, the usual reflex in Django is filter(pk__in=[...]). It works — one SQL query. But in_bulk() is an often-overlooked ORM optimization: it returns a dictionary {id: instance} instead of a QuerySet, which fundamentally changes how you access results. Where filter() forces an O(n) traversal to find an object by ID, in_bulk() gives direct O(1) access. in_bulk() signature and behavior QuerySet.in_bulk(id_list=(), *, field_name='pk') id_list: list of identifiers to retrieve. If omitted (called without arguments), returns all objects in the table. field_name: field used as the dictionary key. Must have unique=True, otherwise Django raises a ValueError. The generated SQL is a simple WHERE pk IN (...) clause — one query regardless of list size. ...
We keep hearing the same promise lately: “No need to know how to code anymore — AI handles it.” And honestly, it’s tempting. You open an agent, describe what you want, and within seconds, code appears. Magic. Except not really. Agentic development — but for whom? AI-assisted development is a genuine revolution. I’m not going to pretend otherwise. For a senior or intermediate developer who has already wrestled with complex problems, debugged twisted algorithms, and shipped systems to production, productivity reaches unprecedented heights. You delegate repetitive tasks, prototype in hours what used to take days, and stay in your high-value zone: architecture, critical decisions, validation. ...
This blog is first and foremost a place to share: discoveries, thoughts, things that have been useful to me and might be useful to others. Python, Django, FastAPI and DRF: the heart of this blog The heart of the blog is Python development, and more specifically the frameworks that shape my daily work: Django, FastAPI and Flask. Each has its strengths, its use cases, its pitfalls. We’ll dig into all of them. ...