Django QuerySets: Chained vs Evaluated

Writing a Django query does not mean it hits the database! Writing a Django query and hitting the database are two different things. The ORM makes it easy to forget the difference between these. Here's what actually happens: 1. When a QuerySet is written, Django builds a query object internally. 2. This has no SQL. No database connection. Just a description of what data is needed. 3. This description can be chained, filtered, sliced, and passed around as required. Still no database hit. 4. The database is only contacted at the moment of evaluation, when Python actually needs the data. This is powerful when used intentionally. Build a complex query across multiple functions, evaluate once, pay the DB cost once! This can backfire too! A QuerySet evaluated inside a loop, once per iteration, is the N+1 problem. Takeaway: -> Efficiency: Chain and pass QuerySets, zero DB cost until evaluation -> Danger: Evaluation inside loops fires one query per row silently -> Control: Knowing evaluation points is the foundation of ORM performance I’m deep-diving into Django internals and performance. Do follow along and tell your experiences in comments. #Python #Django #DjangoInternals #SoftwareEngineering #BackendDevelopment

  • No alternative text description for this image

I like the look of django-mantle. It's based around efficient lightweight attrs defined "Shapes" with type safety, and optimised querysets with django-readers--which prefetch only the specified fields in a "spec" (in this case taken from the Shape class) with clean separation of concerns. It seems to need a bit of override logic to get it to use select_related instead of just prefetch_related for everything, though. The associated mantle-drf lib provides APIView and ViewSet variants that work with the data Shape classes to bypass Serializer overhead. Looking forward to Carlton Gibson putting it on github! Weirdly just on PyPi. https://noumenal.es/mantle/ Have you used django-ninja? Been meaning to play with that for a while, looks like it brings in FastAPI concepts.

if using python django or DRF ; it is best to use graph ql to mostly avoid the N+1 problem ; Ideally just use Fastapi if you want to work with python ; it is a small learning curve but much faster

Nice breakdown of QuerySet laziness Onkar Lapate 👍. But Django builds the SQL when the qs is created, it’s just executed later during evaluation.

See more comments

To view or add a comment, sign in

Explore content categories