5,977 karma · joined May 28, 2010
High level summary:
* We don’t hide Django under layers of abstraction, we just slice it up a bit differently than you would by default.
* Organise code by responsibility (readers, actions, interfaces, data) rather than by app.
* Put most business logic in plain functions, not in fat models or deep class hierarchies.
* Keep views thin: treat GET as "read some data" and POST as "do an action".
* Design endpoints around real frontend use cases (backend for frontend) instead of idealised resources.
* Control queries carefully to avoid performance traps.
Happy to answer questions!
https://laravelpodcast.com/episodes/c7807d42/transcript (Search for “Paris” to find the relevant section)
https://github.com/j4mie/idiorm
https://github.com/j4mie/paris
Idiorm was started in early 2010 while I was still writing PHP professionally. I’d heard about Django from a talk @simonw gave at the FlashBrighton meet-up group in 2009 and immediately fell in love. Idiorm and Paris, although not direct attempts to duplicate Django’s ORM, came from frustration that such an elegant ORM and query builder didn’t exist in the PHP world.
So in a roundabout way, Laravel’s ORM was absolutely inspired by Django.
As a side note, I’m still doing Django 16 years later and love it more than ever.
uv python pin <version> will create a .python-version file in the current directory.
uv virtualenv will download the version of Python specified in your .python-version file (like pyenv install) and create a virtualenv in the current directory called .venv using that version of Python (like pyenv exec python -m venv .venv)
uv pip install -r requirements.txt will behave the same as .venv/bin/pip install -r requirements.txt.
uv run <command> will run the command in the virtualenv and will also expose any env vars specified in a .env file (although be careful of precedence issues: https://github.com/astral-sh/uv/issues/9465)
* Heroku and most of Salesforce
* Pipedrive: https://news.ycombinator.com/item?id=44234098
* OpenAI: https://status.openai.com/incidents/01JXCAW3K3JAE0EP56AEZ7CB...
* Lobsters: https://news.ycombinator.com/item?id=44234075
What's the common denominator?
[1] https://www.iea.org/reports/the-role-of-critical-minerals-in...
Ollama is supported in LLM via this plugin: https://github.com/simonw/llm-ollama
Repeating my comment from that thread:
from diagrams import Diagram
from diagrams.aws.compute import EC2
with Diagram("Simple Diagram"):
EC2("web")
This has a very odd API. It's using (abusing?) context managers and contextvars to do weird spooky things that you could just as easily do with ordinary objects or functions.https://github.com/j4mie/hotmetal/
The core implementation is only 85 lines of Python, and has no imports at all, so works nicely on minimal/alternative Pythons like Micropython.
I'm using it on a medium-sized side project and it's shockingly productive compared to string templates. I don't think anyone is using it except me, though.
- I think "services" is too much of a loaded term. I prefer "actions", and I always use the function-based style.
- I hate the naming of "APIs" in this document. They use the term "API" when they mean "endpoint" or "view".
- "Reuse serializers as little as possible" is the single best piece of advice when using DRF. The inline InputSerializer thing is brilliant.
- Having each each endpoint only handle a single HTTP verb is brilliant.
- URLs and views should be separate from all other business logic (models, actions etc).
- For read endpoints and associated business logic, I'd encourage https://www.django-readers.org/ (disclaimer: I'm the author).I run an agency and we maintain dozens of large, mature production projects (up to ~100k lines of code each).
I do understand the arguments and examples in the rest of your post, and intuitively they make sense, but practically I have almost never had an experience like the one you describe in 20+ years of working on Python codebases.
> you have to dig into the function to find out what it's actually going to give you
This is exactly what I do, and it's just fine. I find it more difficult to build a mental model of what's happening in type-annotated code.
Like I said, it's subjective. That's why I find "types improve readability" arguments in posts such as this to be problematic. They are stated as basic axioms with no supporting data. It's easier to read for you.
Improved readability
This is very subjective, and is particularly sensitive in a language like Python which (rightly) has such a strong historical emphasis on readability above almost anything else.My personal opinion is that static type annotations are extremely detrimental to readability. They add jarring line noise that makes reading Python much less like reading English. Hitting a type annotation when reading Python forces my brain into little backtracking loops which hugely diminishes my ability to form a mental model of the code from a quick read.
I wonder if people who come to Python from other languages (that are already statically typed) are accustomed to the poor comprehension introduced by types, and so don't experience this drawback.
from diagrams import Diagram
from diagrams.aws.compute import EC2
with Diagram("Simple Diagram"):
EC2("web")
This has a very odd API. It's using (abusing?) context managers and contextvars to do weird spooky things that you could just as easily do with ordinary objects or functions.(I’m the author of django-zen-queries)
I’m not a fan of the hyperbole in the article either. Some of the points are genuine problems but none of them should put off beginners.