← Back to context

Comment by stevex

6 days ago

One thing Django has going for it is that the "batteries included" nature of it is perfect for AI code generation.

You can get a working site with the usual featuers (admin panel, logins, forgot reset/password flow, etc) with minimal code thanks to the richness of the ecosystem, and because of the minimal code it's relatively easy for the AI to keep iterating on it since it's small enough to be understandable in context.

On top of this, it's understandable to humans when reviewing generated code. There's no 2000-line FooBarAdmin component where bugs could be located. And if you're having it generate HTML templates, you can see exactly what backend model property/method was used without needing to follow the indirection through backends and prop drilling.

And when you do create backends and React components, you can have a known-good ground truth in your Django admin that's independent from that frontend. This is incredibly useful in practice - if a certain e.g. malformed input triggers a catastrophic frontend crash, you have an entirely separate admin system you can use to play with the data, without needing to trace to find the exact cause of the frontend crash, or dropping into direct database access.

(My one gripe with Django, which is more with the broader Python ecosystem, is that if the community had leaned into the gevent programming model (no explicit async, all socket calls are monkey-patched to yield, you just write sync code), there would be no need for async versions/ports of every Django library function, no confusion in the library ecosystem, and instant upgrades of every Django library in existence to an async world. gevent is a thing of beauty and that's a hill I'll die on.)

  • One meeting with the original gevent author explains why it has not achieved broad acceptability.

    It is rather sad for humanity that good ideas through-out time have been lost thanks to neurodiversity / social-acceptability constraints.

  • I prefer gevent over explicit async so I'll die on that hill with you. The cooperative model adopted by Python async is... bad.

  • I just do not use Python async. Mostly I do not need it. If I do I would rather use something else.

Now I've been dabbling outside of Django, I realised some of those things come from bits people don't think about much:

INSTALLED_APPS and other bits in the settings provide a central registration point, from there the system where a project is made up of apps is enabled.

Each app, has it's own migrations, models, templates and static files.

This enables the whole ecosystem of parts that's easy to add, and makes it easy to toggle things (e.g. enabling the django-debug-toolbar only on your dev and local instance).

In the outside world of Flask, Fast API etc - things hang together much more loosely and it means the integration just isn't as complete.

This manifests itself in 1,000 little papercuts that make things take longer.

  • It can be similar to WordPress plugins, but as problematic as WordPress plugins are, they went a lot farther in terms of ecosystem. While stored in the database, the WordPress plugins do the equivalent of INSTALLED_APPS, calling the code to register them.

    Someone tried to make an ecosystem of Django apps, called Pinax, and it was pretty nice, but didn't pick up that much market share.

  • Yes, 100%, you end up with a massive main.py file instantiating everything and trying to couple and register stuff.

I have tried both Django and Rails for this, and honestly, very surprisingly, Rails did much better, at least with Claude Code. This is for a rewrite of an old .net application. Claude nailed it almost perfectly with Rails, but struggled with Django. YMMV.

  • Ive been pleasantly surprised by claudes ability to handle a real-world rails codebase thats 5-10 years old in various spots. We dont do a lot of ruby magic / metaprogramming, and arent particularly 'railsy' in our patterns, but its had no issues figuring things out (even the light metaprogramming we _do_ use).

Ruby and Rails are even better candidates. CSP, Background workers, and many other features that Django still lacks have been standard offerings for sometimes 10+ years!

  • Rails tries to more tightly integrate with the front-end which causes a lot of turn over the years. Django projects from 10 years ago are still upgradable in a day or two. Rails does include some nice stuff though, but I much prefer Django's code first database models than Rail's ActiveRecord.

    • Those Django models are a pain to work with if you have to access the database with any other tool that is not the original Django app. The only sane way to design a database managed by Django models and migrations is not using any inheritance between models or you'll end up with a number of tables, each one adding a few fields. Django ORM will join them for you but you are on your own if you ever have to write queries with some other tool.

      2 replies →

    • I do agree that Rails' asset stuff has been giant pain over the years and has not kept up well. On the other hand, some apps that adopted separate Rails APIs and a separate (for example, React) frontend have been fine. You're right though that their opinion here added more headaches that necessary!

      1 reply →

  • CSP is literally in this release, and background workers are intentionally not part of Django because you usually want to offload tasks to other nodes so your CPU can keep serving HTTP requests.

    Edit: Background tasks for light work are also included in this release.

    • My point was that these features that are considered new and exciting have been standard in Rails for many, many years. There are many _other_ features that Django still lacks!

      I don't understand your point about the workers, since you argue it doesn't belong in Django, but then in your edit mention they have been added. To be clear I'm talking about a worker abstraction, not actually running the workers pods themselves.

      1 reply →

And because Django is so popular in open source projects and it has been around for such a long time, there's tons of code out there for AI to train on.

Claude is insanely good with Django and React. I think the best thing that happened to Python was type hints because it lets LLMs reason Python code easier.

why would you need batteries included? the ai can code most integrations (from scratch, if you want, so if you need something slightly off the beaten path it's easy

  • I think the logic can be applied to humans as well as AI:

    Sure, the AI _can_ code integrations, but it now has to maintain them, and might be tempted to modify them when it doesn't need to (leaky abstractions), adding cognitive load (in LLM parlance: "context pollution") and leading to worse results.

    Batteries-included = AI and humans write less code, get more "headspace"/"free context" to focus on what "really matters".

    As a very very heavy LLM user, I also notice that projects tend to be much easier for LLMs (and humans alike) to work on when they use opinionated well-established frameworks.

    Nonetheless, I'm positive in a couple of years we'll have found a way for LLMs to be equally good, if not better, with other frameworks. I think we'll find mechanisms to have LLMs learn libraries and projects on the fly much better. I can imagine crazy scenarios where LLMs train smaller LLMs on project parts or libraries so they don't get context pollution but also don't need a full-retraining (or incredibly pricey inference). I can also think of a system in line with Anthropic's view of skills, where LLMs very intelligently switch their knowledge on or off. The technology isn't there yet, but we're moving FAST!

    Love this era!!

    • > As a very very heavy LLM user, I also notice that projects tend to be much easier for LLMs (and humans alike) to work on when they use opinionated well-established frameworks.

      i have the exact opposite experience. its far better to have llms start from scratch than use batteries that are just slightly the wrong shape... the llm will run circles and hallucinate nonexistent solutions.

      that said, i have had a lot of success having llms write opinionated (my opinions) packages that are shaped in the way that llms like (very little indirection, breadcrumbs to follow for code paths etc), and then have the llm write its own documentation.

    • Maybe if they could learn how to switch their intelligence on, that would help more?

  • What’s more likely to have a major security problem – Django’s authentication system or something custom an LLM rolled?

    • I don't even particularly care for Django, but darned if I'd want to reimplement on my own any of the great many problems they've thoroughly solved. It's so widely used that any weird little corner case you can think of has already been addressed. No way I'd start over on that.

  • Its literally the opposite.

    Why would you generate sloppy version of core systems that must be included by default in every project.

    It makes absolutely zero sense to generate auth/email sending/bg tasks integration/etc

  • Because then every app is a special snowflake.

    At some point you'll need to understand things to fix it, and if it's laid out in a standard way you'll get further, quicker.