[HN Gopher] Some notes on starting to use Django
       ___________________________________________________________________
        
       Some notes on starting to use Django
        
       Author : ingve
       Score  : 176 points
       Date   : 2026-01-27 22:58 UTC (1 days ago)
        
 (HTM) web link (jvns.ca)
 (TXT) w3m dump (jvns.ca)
        
       | synack wrote:
       | Claude Code is also very good at building basic CRUD apps with
       | Django.
        
         | jdahlin wrote:
         | No kidding, it is really good especially with htmx which helps
         | you get some of the advantages of a full SPA without the
         | complexity of a separate frontend.
         | 
         | Been building a project in the side to help my studies and it
         | usually implement new complete apps from one prompt, working on
         | the first try
        
           | sgt wrote:
           | Yeah, I've noticed it regularly suggests htmx (and perhaps
           | something light like alpinejs or some vanilla JS glue logic)
           | to build powerful yet simple interfaces in Django. And it
           | seems to get them right - saving you a lot of time.
        
           | megaman821 wrote:
           | It is probably good a HTMX for the same reason it is good at
           | Tailwind CSS; HTMX puts the functionality on the elements
           | being reasoned about (e.g. click this button, load the result
           | here).
        
         | 6bb32646d83d wrote:
         | That's a huge bonus point for Django. It's so prevalent that
         | Claude/Codex are very good at setting it up the right way,
         | using tried and true patterns.
         | 
         | I've been vibe coding some side projects with Claude Code +
         | Django + htmx/tailwind, and when it's time to go some manual
         | work in the codebase I know exactly where things are and what
         | they do, there's way fewer weird patterns or hack the way
         | Claude tends to do when it's not as guided
        
       | striking wrote:
       | Thanks for this! I wish there were more cross-comparisons like
       | this out there of what it is actually like to use some of these
       | frameworks, the note on Django being a little less magic than
       | Rails makes me genuinely interested in it.
        
         | dnautics wrote:
         | if you want "less magic than rails" check out ecto, i would say
         | it has less magic than django
        
       | giancarlostoro wrote:
       | I always return to Django for any project. It's fantastic. Enough
       | batteries are included with it that it is very powerful.
        
       | selcuka wrote:
       | Django is objectively the most productive "boring technology"
       | I've ever worked with for developing web applications. They don't
       | regularly add too many bells and whistles on every release, but
       | they keep it stable and reasonably backwards compatible.
        
       | interroboink wrote:
       | Django aside, I think this is a really important point:
       | Being able to abandon a project for months or years and then come
       | back       to it is really important to me (that's how all my
       | projects work!) ...
       | 
       | It's perhaps especially true for a hobbyist situation, but even
       | in a bigger environment, there is a cost to keeping people on
       | hand who understand how XYZ works, getting new people up to
       | speed, etc.
       | 
       | I, too, have found found that my interactions with past versions
       | of myself across decades has been a nice way to learn good habits
       | that also benefit me professionally.
        
         | simonw wrote:
         | This is the main reason I'm extremely disciplined about making
         | sure all of my personal projects have automated tests
         | (configure to run in CI) and decent documentation.
         | 
         | It makes it _so much easier_ to pick them up again in the
         | future when enough time has passed that I 've forgotten almost
         | everything about them.
        
           | sriram_malhar wrote:
           | I'm finding that in this build fast and break things culture,
           | it is hard to revisit a project that is more than 3 years
           | old.
           | 
           | I have a couple of android projects that are four years old.
           | I have the architecture documented, my notes (to self) about
           | some important details that I thought I was liable to forget,
           | a raft of tests. Now I can't even get it to load inside the
           | new version of Android Studio or to build it. There's a ton
           | of indirection between different components spread over
           | properties, xml, kotlin but what makes it worse is that any
           | attempt to upgrade is a delicate dance between different
           | versions and working one's ways around deprecated APIs. It
           | isn't just the mobile ecosystem.
        
             | alansaber wrote:
             | Build fast and break things works great if you're the
             | consumer, not the dev polishing the dark side of the
             | monolith (helps if you're getting paid well though)
        
               | dotancohen wrote:
               | As a consumer, I can not remember any feature that I was
               | so enamored about having a week earlier than I otherwise
               | would have, at the expense of breaking things.
        
               | alansaber wrote:
               | The point is that companies don't actually know what
               | consumers want so a volume / meandering approach is
               | required
        
             | wink wrote:
             | I have relatively good experience with both Rust and Go
             | here. It still works and maybe you need update 2-3
             | dependencies that released an incompatible version, but
             | it's not all completely falling apart just because you went
             | on a vacation (looking at you npm)
        
           | appplication wrote:
           | Totally relate. My main project lately is for my wife, and
           | it's absolutely rock solid from a testing/automation
           | standpoint. The last thing I want to do is accidentally break
           | something and give her a headache when i'm just trying to
           | build her a nice thing that brings her joy.
        
         | dgroshev wrote:
         | "Cold-blooded software" is a great term for that
         | https://dubroy.com/blog/cold-blooded-software/ (HN:
         | https://news.ycombinator.com/item?id=46488261 )
        
           | skylurk wrote:
           | If you know what you are doing, you can hibernate other kinds
           | of tortoises by placing them in a fridge (as opposed to a
           | freezer). One of my friends does this with their Russian
           | tortoise.
           | 
           | If you need to travel, make sure you have someone reliable
           | who can check on them, in case of a power outage.
        
       | bb88 wrote:
       | After spending a lot of my time on Django, it's fine for simple
       | to moderately complex things. The ORM mostly good. DRF is fine
       | for APIs. And the admin is super nice as well.
       | 
       | But once something gets significantly complex, the ORM starts to
       | fall down, and DRF becomes more of a hindrance.
       | 
       | But if you're just doing simple CRUD apps, Django is perfectly
       | serviceable.
        
         | sgt wrote:
         | What does significantly complex mean though? You have to make
         | sure you understand the queries made by the ORM, avoid pitfalls
         | like SELECT N+1 queries and so on. If you don't do this, it'll
         | be slow but it's not the ORM's fault - it's that of the
         | programmer.
        
           | compounding_it wrote:
           | Significantly complex means when ORM starts to become bigger
           | and bigger and you need multiple threads and more complex
           | processes that run in workers. When you start to run into
           | scaling problems, your solution is within that framework and
           | that becomes a limiting factor from my experience.
           | 
           | Then as a programmer, you have to find workarounds in Django
           | instead of workarounds with programming.
           | 
           | PS: Dealing with a lot of scaling issues right now with a
           | Django app.
        
             | sgt wrote:
             | You can absolutely scale Django.
             | 
             | The framework itself is not the limiting factor. The main
             | constraint of performance usually comes from Python itself
             | (really slow). And possibly I/O.
             | 
             | There are well established ways to work around that. In
             | practice, lots of heavy lifting happens in the DB, can you
             | can offload workloads to separate processes as well
             | (whether those are Python, Go, Rust, Java etc).
             | 
             | You need to identify the hotspots, and blindly trusting a
             | framework to "do the job for you" (or for that matter,
             | trusting an LLM to write the code for you without
             | understanding the underlying queries) is not a good idea.
             | 
             | I'm not saying you are doing that, but how often do you use
             | the query planner? Whenever I've heard someone saying
             | Django can't scale, it's not Django's fault.
             | 
             | > When you start to run into scaling problems, your
             | solution is within that framework and that becomes a
             | limiting factor from my experience.
             | 
             | Using Django doesn't mean that everything needs to run
             | inside of it. I am working on an API that needs async perf,
             | and I run separate FastAPI containers will still using
             | Django to maintain the data model + migrations.
             | 
             | Occasionally I will drop down to raw SQL, or materialized
             | views (if you are not using them with Django, you are
             | missing out). And the obvious for any Django dev;
             | select_related, prefetch_related, annotate, etc etc.
        
               | tclancy wrote:
               | Yeah, I don't get the issues here. I've led projects that
               | served millions of requests a day, had dozens of apps and
               | while there are always going to be pain points and
               | bottlenecks, nothing about the framework itself is a
               | hinderance to refactoring. If anything, Django plus good
               | tests made me much braver about what I would try.
        
               | otherme123 wrote:
               | > And the obvious for any Django dev; select_related,
               | prefetch_related, annotate
               | 
               | And sometimes not so obvious, I have been bitten by
               | forgetting one select_related while inadvertedly joining
               | 5 tables but using only 4 select_related: the tests work
               | OK, but the real data has a number of records that cause
               | a N+1. A request that used to take 100ms now issues "30
               | seconds timeout" from time to time.
               | 
               | Once we added the missing select_related we went back to
               | sub-second request, but it was very easy to start blaming
               | Django itself because the number of records to join was
               | getting high.
               | 
               | The cases that we usually walk out of the Django path is
               | for serializations and representations, trying to avoid
               | the creation of intermediate objects when we only need
               | the "values()" return.
        
             | halfcat wrote:
             | > Then as a programmer, you have to find workarounds in
             | Django instead of workarounds with programming.
             | 
             | The mental unlock here is: Django is only a convention, not
             | strictly enforced. It's just Python. You can change how it
             | works.
             | 
             | See the Instagram playbook. They didn't reach a point where
             | Django stopped scaling and move away from Django. They
             | started modifying Django because it's pluggable.
             | 
             | As an example, if you're dealing with complex background
             | tasks, at some point you need something more
             | architecturally robust, like a message bus feeding a pool
             | of workers. One simple example could be, Django gets a
             | request, you stick a message on Azure Service Bus (or AWS
             | SQS, GCP PubSub, etc), and return HTTP 202 Accepted to the
             | client with a URL they can poll for the result. Then you
             | have a pool of workers in Azure Container Apps (or AWS/GCP
             | thing that runs containers) that can scale to zero, and
             | gets woken up when there's a message on the service bus.
             | Usually I'd implement the worker as a Django management
             | command, so it can write back results to Django models.
             | 
             | Or if your background tasks have complex workflow
             | dependencies then you need an orchestrator that can run
             | DAGs (directed acyclic graph) like Airflow or Dagster or
             | similar.
             | 
             | These are patterns you'd need to reach for regardless of
             | tech stack, but Django makes it sane to do the plumbing.
             | 
             | The lesson from Instagram is that you don't have to hit a
             | wall and do a rewrite. You can just keep modifying Django
             | until it's almost unrecognizable as a Django project.
             | Django just starts you with a good convention that (mostly)
             | prevents you from doing things that you'll regret later
             | (except for untangling cross-app foreign keys, this part
             | requires curse words and throwing things).
        
         | boxed wrote:
         | If you're doing simple CRUD apps, try https://iommi.rocks/
         | which we built because imo it's way way too slow and produces
         | too much code to use standard Django to make CRUD stuff.
        
           | graemep wrote:
           | I am using it, and its a great time saver and very
           | maintainable.
           | 
           | I am not using the main menu module, but tables and forms
           | work really well.
        
         | dgroshev wrote:
         | In my experience, django-ninja is a great alternative to DRF,
         | precisely because it's so thin, unlike DRF.
        
       | jszymborski wrote:
       | > I love being able to backup by just doing a VACUUM INTO and
       | then copying the resulting single file.
       | 
       | Naively, I would probably just copy the sqlite file. Is that a
       | bad idea?
        
         | amanzi wrote:
         | I learned about the VACUUM INTO command through the following
         | guide on how to backup your sqlite database:
         | https://litestream.io/alternatives/cron/
        
         | simonw wrote:
         | That's fine if SQLite isn't running, but you risk corruption if
         | you copy a file while it is being actively written to.
         | 
         | VACUUM INTO eliminates that risk.
        
           | modo_mario wrote:
           | Thank you for mentioning this. I was planning to do exactly
           | this soon and had no idea.
        
       | jgavris wrote:
       | The Django ORM / migrations are still basically unmatched in
       | happiness factor.
        
         | hansonkd wrote:
         | Its crazy to me after all these years that django-like
         | migrations aren't in every language. On the one hand they seem
         | so straightforward and powerful, but there must be some
         | underlying complexities of having it autogenerate migrations.
         | 
         | Its always a surprise when i went to Elixir or Rust and the
         | migration story was more complicated and manual compared to
         | just changing a model, generating a migration and committing.
         | 
         | In the pre-LLM world, I was writing ecto files, and it was
         | super repetitive to define make large database strucutres
         | compared to Django.
        
           | dnautics wrote:
           | well in elixir you can have two schemas for the same table,
           | which could represent different views, for example, an admin
           | view and a user view. this is not (necessarily) for security
           | but it reduces the number of columns fetched in the query to
           | only what you need for the purpose.
        
           | IceDane wrote:
           | There is no way to autogenerate migrations that work in all
           | cases. There are lots of things out there that can generate
           | migrations that work for most simple cases.
        
             | etchalon wrote:
             | Django manages to autogenerate migrations that work in the
             | VAST majority of cases.
        
             | boxed wrote:
             | That's why you can do your own migrations in Django for
             | those edge cases.
        
             | frankwiles wrote:
             | I end up needing to write a manual migration maybe once
             | every other year in real world use.
        
             | hansonkd wrote:
             | They don't need to work in every case. For the past `~15
             | years 100% of the autogenerated migrations to generating
             | tables, columns or column names I have made _just work_.
             | and i have made thousands of migrations at this point.
             | 
             | The only thing to manually migrate are data migrations from
             | one schema to the other.
        
           | igsomething wrote:
           | Going from Django to Phoenix I prefer manual migrations.
           | Despite being a bit tedious and repetitive, by doing a
           | "double pass" on the schema I often catch bugs, typos,
           | missing indexes, etc. that I would have missed with Django.
           | You waste a bit of time on the simple schemas, but you save a
           | ton of time when you are defining more complex ones. I lost
           | count on how many bugs were introduced because someone was
           | careless with Django migrations, and it is also surprising
           | that some Django devs don't know how to translate the
           | migrations to the SQL equivalent.
           | 
           | At least you can opt-in to automated migrations in Elixir if
           | you use Ash.
        
           | wiredfool wrote:
           | There are some subtle edge cases in the django migrations
           | where doing all the migrations at once is not the same as
           | doing migrations one by one. This has bitten me on multiple
           | django projects.
        
             | cuu508 wrote:
             | Can you give an example how this would happen?
        
               | wiredfool wrote:
               | Ok, from memory --
               | 
               | There's a pre, do and post phase for the migrations. When
               | you run a single migration, it's: pre, do, post. When you
               | run 2 migrations, it's: pre [1,2], do: [1,2], post:
               | [1,2].
               | 
               | So, if you have a migration that depends on a previous
               | migration's post phase, then it will fail if it is run in
               | a batch with the previous migration.
               | 
               | When I've run into this is with data migrations, or if
               | you're adding/assigining permissions to groups.
        
               | brianwawok wrote:
               | There's like an atomic flag you can pull it out of the
               | transaction . Solves a lot of these issues.
        
               | hansonkd wrote:
               | Does that affect the autogenerated migrations at all? Teh
               | only time I ran into that issue as if I generated a
               | table, created a data migration and then it failed
               | because the table was created same transaction. Never had
               | a problem with autogenerated migrations.
        
               | advisedwang wrote:
               | What a crazy design, why don't they just do pre1 do1
               | post1 pre2 do2 post2?
        
         | dnautics wrote:
         | oh the automatic migrations scare the bejesus out of me. i
         | really prefer writing out schemas and migrations like in
         | elixir/ecto. plus i like the _option_ of having two different
         | schemas for the same table (even if i never use it)
        
           | 3eb7988a1663 wrote:
           | I have never done it, but I believe you could setup multiple
           | schemas under the same database -by faking it as different
           | databases and then use a custom router to flip between them
           | as you like.
           | 
           | That sounds like the path to madness, but I do believe it
           | would work out of the box.
        
             | dnautics wrote:
             | sounds inconvenient and error-prone
        
               | 3eb7988a1663 wrote:
               | It is not much code to setup the router. Now, why you
               | would want to bounce between schemas, I do not have a
               | good rationale, but whatever floats your boat.
        
               | dnautics wrote:
               | yeah some frameworks call these "lenses". There's even
               | crazy people who write lenses on top of elixir schemas
               | because they dont realize you can just have multiple
               | schemas.
               | 
               | maybe more concretely: if you have a table with a
               | kajillion columns and you want performant views onto some
               | column (e.g. "give me the metadata only and dont show me
               | blobs columns") without pulling down the entire jungle in
               | the sql request, There's that.
        
           | gtaylor wrote:
           | The nice thing in this case is that Django will meet you
           | where you are with your preferences. Want to go the manual
           | route? Sure. Want it to take a shot at auto-generation and
           | then you customize? Very doable and. Want to let Django take
           | the wheel fully the majority of the time? Sure.
        
             | dnautics wrote:
             | is this like the "it takes 50 hours to set up a project
             | management tool to work the way _you want_ "? what happens
             | if you onboard a superstar that works with django some
             | _other_ way?
        
           | dxdm wrote:
           | You can ask Django to show you what exact SQL will run for a
           | migration using `manage.py sqlmigrate`.
           | 
           | You can run raw SQL in a Django migration. You can even
           | substitute your SQL for otherwise autogenerated operations
           | using `SeparateDatabaseAndState`.
           | 
           | You have a ton of control while not having to deal with
           | boilerplate. Things usually can just happen automatically,
           | and it's easy to find out and intervene when they can't.
           | 
           | https://docs.djangoproject.com/en/6.0/ref/django-
           | admin/#djan...
           | 
           | https://docs.djangoproject.com/en/6.0/ref/migration-
           | operatio...
        
         | danmaz74 wrote:
         | Have you ever tried Rails? I think that Django's approach on
         | those is an adaptation from it.
        
           | jgavris wrote:
           | Of course, ActiveRecord back in 2005.
        
         | ndr wrote:
         | I found it very lacking in how to do CD with no downtime.
         | 
         | It requires a particular dance if you ever want to add/delete a
         | field and make sure both new-code and old-code work with both
         | new-schema and old-schema.
         | 
         | The workaround I found was to run tests with new-schema+old-
         | code in CI when I have schema changes, and then
         | `makemigrations` before deploying new-code.
         | 
         | Are there better patterns beyond "oh you can just be careful"?
        
           | senko wrote:
           | You can do three stage:
           | 
           | 1. Make a schema migration that will work both with old and
           | new code
           | 
           | 2. Make a code change
           | 
           | 3. Clean up schema migration
           | 
           | Example: deleting a field:
           | 
           | 1. Schema migration to make the column optional
           | 
           | 2. Remove the field in the code
           | 
           | 3. Schema migration to remove the column
           | 
           | Yes, it's more complex than creating one schema migration,
           | but that's the price you pay for zero-downtime. If you can
           | relax that to "1s downtime midnight on sunday", you can keep
           | things simpler. And if you do so many schema migrations you
           | need such things often ... I would submit you're holding it
           | wrong :)
        
             | jgavris wrote:
             | I was just in the middle of writing something similar
             | above, thanks!
        
             | ndr wrote:
             | I'm doing all of these and None of it works out of the box.
             | 
             | Adding a field needs a default_db, otherwise old-code fails
             | to `INSERT`. You need to audit all the `create`-like calls
             | otherwise.
             | 
             | Deleting similarly will make old-code fail all `SELECT`s.
             | 
             | For deletion I need a special 3-step dance with
             | managed=False for one deploy. And for all of these I need
             | to run old-tests on new-schema to see if there's some usage
             | any member of our team missed.
        
           | jgavris wrote:
           | The general approach is to do multiple migrations (add first
           | and make new-code work with both, deploy, remove old-code,
           | then delete old-schema) and this is not specific to Django's
           | ORM in any way, the same goes for any database schema
           | deployment. Take a peek at
           | https://medium.com/@pranavdixit20/zero-downtime-
           | migrations-i... for some ideas.
        
           | rorylaitila wrote:
           | I simplify it this way. I don't delete fields or tables in
           | migrations once an app is in production. Only manually clean
           | them up after they are impossible to be used by any
           | production version. I treat the database schema as-if it were
           | "append only" - Only add new fields. This means you always
           | "roll-forward", a database. Rollback migrations are 'not a
           | thing' to me. I don't rename physical columns in production.
           | If you need an old field and a new field to be running
           | simultaneously that represent the same datum, a trigger keeps
           | them in sync.
        
           | aljarry wrote:
           | One option is to do multi-stage rollout of your database
           | schema and code, over some time windows. I recall a blog post
           | here (I think) lately from some Big Company (tm) that would
           | run one step from the below plan every week:
           | 
           | 1. Create new fields in the DB.
           | 
           | 2. Make the code fill in the old fields and the new fields.
           | 
           | 3. Make the code read from new fields.
           | 
           | 4. Stop the code from filling old fields.
           | 
           | 5. Remove the old fields.
           | 
           | Personally, I wouldn't use it until I really need it. But a
           | simpler form is good: do the required schema changes
           | (additive) iteratively, 1 iteration earlier than code
           | changes. Do the destructive changes 1 iteration after your
           | code stops using parts of the schema. There's opposite
           | handling of things like "make non-nullable field nullable"
           | and "make nullable field non-nullable", but that's part of
           | the price of smooth operations.
        
           | m000 wrote:
           | Deploying on Kubernetes using Helm solves a lot of these
           | cases: Migrations are run at the init stage of the pods. If
           | successful, pods of the new version are started one by one,
           | while the pods of the new version are shutdown. For a short
           | period, you have pods of both versions running.
           | 
           | When you add new stuff or make benign modifications to the
           | schema (e.g. add an index somewhere), you won't notice a
           | thing.
           | 
           | If the introduced schema changes are not compatible with the
           | old code, you may get a few ProgramingErrors raised from the
           | old pods, before they are replaced. Which is usually
           | acceptable.
           | 
           | There are still some changes that may require planning for
           | downtime, or some other sort of special handling. E.g.
           | upgrading a SmallIntegerField to an IntegerField in a
           | frequently written table with millions of rows.
        
             | ndr wrote:
             | Without care new-schema will make old-code fail user
             | requests, that is not zero downtime.
        
               | m000 wrote:
               | A request not being served can happen for a multitude of
               | reasons (many of them totally beyond your control) and
               | the web architecture is designed around that premise.
               | 
               | So, if some of your pods fail a fraction of the requests
               | they receive for a few seconds, this is not considered
               | downtime for 99% of the use cases. The service never
               | really stopped serving requests.
               | 
               | The problem is not unique to Django by any means. If you
               | insist on being a purist, sure count it as downtime. But
               | you will have a hard time even measuring it.
        
           | tmarice wrote:
           | This is not specific to Django, but to any project using a
           | database. Here's a list of a couple quite useful resources I
           | used when we had to address this:
           | 
           | * https://github.com/tbicr/django-pg-zero-downtime-migrations
           | 
           | * https://docs.gitlab.com/development/migration_style_guide/
           | 
           | * https://pankrat.github.io/2015/django-migrations-without-
           | dow...
           | 
           | * https://www.caktusgroup.com/blog/2021/05/25/django-
           | migration...
           | 
           | * https://openedx.atlassian.net/wiki/spaces/AC/pages/23003228
           | /...
           | 
           | Generally it's also advisable to set a statement timeout for
           | migrations otherwise you can end up with unintended downtime
           | -- ALTER TABLE operations very often require ACCESS EXCLUSIVE
           | lock, and if you're migrating a table that already has an
           | e.g. very long SELECT operation from a background task on it,
           | all other SELECTs will queue up behind the migration and
           | cause request timeouts.
           | 
           | There are some cases you can work around this limitation by
           | manually composing operations that require less strict locks,
           | but in our case, it was much simpler to just make sure all
           | Celery workers were stopped during migrations.
        
       | pbreit wrote:
       | I much prefer Python but am not really seeing any point to doing
       | anything other than JavaScript for web projects at this point.
       | 
       | I also do not see much reason to do more than emit JSON on the
       | server side.
        
         | vasco wrote:
         | Figuring out which "json" to "emit" is the hard part.
        
         | JodieBenitez wrote:
         | > I much prefer Python
         | 
         | Well... that's a valid reason. Why should I work with tool B
         | when I prefer tool A ?
         | 
         | > I also do not see much reason to do more than emit JSON on
         | the server side.
         | 
         | That's the "SPA over API" mindset we need to reconsider. A lot
         | (and I mean A LOT) of projects are way easier to produce and
         | maintain with server-side rendered views.
        
           | gertburger wrote:
           | HTMX with Django backend really excels in this regard.
        
             | JodieBenitez wrote:
             | I'd prefer Unpoly over HTMX, but yes, it excels.
        
         | senko wrote:
         | You still need clear separation between frontend and backend
         | (react server components notwithstanding), so nothing's
         | stopping you from using Python on the backend if you prefer it.
         | 
         | Django with DRF or django-ninja works really nice for that use
         | case.
        
       | scott_w wrote:
       | The author makes a great last point about Settings and it's
       | something I've not considered... ever! I wonder if there's a
       | feature request for this because having a pre-configured object
       | would be nice for the ability to verify correctness on startup.
        
         | tecoholic wrote:
         | I use a project generator tool for a Django project. One of the
         | things it does is generate setting file using string
         | manipulation. I have been trying to think of a more sane way to
         | do this. leverage something like dataclass or Pydantic models
         | to have the typing information available and render a typed and
         | validated Python object. If Django ever made that possible, it
         | would be amazing for dev ex.
        
           | Nextgrid wrote:
           | https://docs.pydantic.dev/latest/concepts/pydantic_settings/
        
         | christophilus wrote:
         | In TypeScript, I use the same validation library (Zod) anywhere
         | I need to validate data. So, I validate my config / environment
         | variables on startup using a Zod schema, I validate my RPC
         | endpoint arguments the same way, etc.
         | 
         | I presume you could do the same thing with Django-- use
         | Django's validation feature to validate everything including
         | your config. It's a nice pattern that gives uniformity and
         | predictability to all of your validation logic.
        
           | scott_w wrote:
           | Not really, unfortunately. The thing is, if you mistype a
           | configuration key, Django won't pick it up. It'll just leave
           | the default value in place. I also don't think it does any
           | validation on settings values, it'll just pass them to
           | whatever uses them. That's the last time I used it anyway.
           | 
           | The situation is worse than that because any plugins usually
           | define their own settings which also don't validate their
           | contents.
           | 
           | I think something centralised that lets you properly scope
           | and validate settings would be nice. If you mistype a key,
           | you'd want an error that it's just not valid.
        
       | cenamus wrote:
       | Alternatively look at https://sqlite.org/backup.html for backing
       | up the sqlite db, instead of using VACUUM INTO
        
       | Cthulhu_ wrote:
       | In hindsight, maybe I should've tried to use Django for my
       | previous project instead of build a lot of custom stuff in Go and
       | React. It was basically an admin interface, but with dozens of
       | models and hundreds if not thousands of individual fields, each
       | with their own validation / constraints. But it was for internal
       | users, so visually it mainly needed to be clear.
        
       | tmarice wrote:
       | After working with Django for 8 years, I find it hard to move on
       | to anything else. It's just the right amount of magic, and just
       | the right amount of flexibility, and it's just such a joy to work
       | with.
       | 
       | Re: Django is OK for simple CRUD, but falls apart on anything
       | complex - this is just untrue. I have worked in a company with a
       | $500M valuation that is backed by a Django monolith. Reporting,
       | recommender systems, file ingestion pipelines, automatic file
       | tagging with LLM agents -- everything lives inside Django apps
       | and interconnects beautifully. Just because it's a Django app
       | doesn't mean you cannot use other libraries and do other stuff
       | besides basic HTTP request processing.
       | 
       | Recently I had the misfortune of doing a contract on a classic
       | SPA project with Flask and sqlalchemy on the backend and React on
       | the frontend, and the amount of code necessary to add a couple of
       | fields to a form is boggling.
        
         | otherme123 wrote:
         | > Recently I had the misfortune of doing a contract on a
         | classic SPA project with Flask and sqlalchemy on the backend
         | and React on the frontend, and the amount of code necessary to
         | add a couple of fields to a form is boggling.
         | 
         | Same here, and the reason to do all the Flask + SQLAlchemy +
         | React was to keep things simple, as they are simple tools but
         | Django is a complex tool. In particular the Flask part was
         | juggling plugins for admin, forms and templates that Django
         | already has included. But yeah, I am sure it is easier to code
         | and to mantain because Flask is made for simple sites :/.
        
         | bodge5000 wrote:
         | > Re: Django is OK for simple CRUD, but falls apart on anything
         | complex
         | 
         | Maybe my experience of working with Django on complex
         | applications has coloured my view on it a bit, but I always
         | think the opposite; it seems overkill for simple CRUD, even if
         | I love using it
        
       | senko wrote:
       | Some more Django recommendations from Frank Wiles of Revsys
       | (Django consultancy): https://frankwiles.com/questions/starting-
       | django-projects/
       | 
       | I'll add a few of my own:
       | 
       | * Set up the project using uv
       | 
       | * I name the django project "project"; so settings are
       | project/settings.py, main urls are project/urls.py, etc
       | 
       | * I always define a custom Django user model even if I don't need
       | anything extra yet; easier to expand later
       | 
       | * settings.py actually conflates project config (Django apps,
       | middleware, etc) and instance/environment config (Database
       | access, storages, email, auth...); I hardcode the project config
       | (since that doesn't change between environemnts) and use python-
       | dotenv to pull settings from environment / .env; I document all
       | such configurable vars in .env.example, and the defaults are sane
       | for local/dev setup (such as DEBUG=true, SQLIte database,
       | ALLOWED_HOSTS=*, and a randomly-generated SECRET_KEY); oh and I
       | use dj-database-url to use DATABASE_URL (defaults to
       | sqlite:///sqlite.db)
       | 
       | * I immediately set up up ruff, ty, pytest, pre-commit hook and
       | GH workflow to run ruff/ty/pytest
       | 
       | Previously I had elaborate scaffolding/skeleton templates, or
       | nowadays a small shell script and I tell Claude to adapt
       | settings.py as per above instructions :)
        
         | bodge5000 wrote:
         | I'll add one; Add shell_plus. It makes the django shell so much
         | nicer to use, especially on larger projects (mostly because it
         | auto-imports all your models). IIRC, it involves adding ipython
         | and django_extensions as a dependency, and then adding django-
         | extensions (annoyingly, note that the underscore changes to a
         | dash, this trips me up everytime I add it) to your installed
         | apps.
         | 
         | Saying that, I'm sure django-extensions does a lot more than
         | shell_plus but I've never actually explored what those extra
         | features are, so think I'll do that now
         | 
         | Edit: Turns out you can use bpython, ptpython or none at all
         | with shell_plus, so good to know if you prefer any of them to
         | ipython
        
           | el_io wrote:
           | > mostly because it auto-imports all your models
           | 
           | Django does this by default now. Since 5.0 if I'm remembering
           | it correctly.
        
             | bodge5000 wrote:
             | In the default shell? I've definitely started new django
             | projects since 2023 and I seem to remember always having to
             | use shell_plus for that, though maybe thats just become
             | something I automatically add without thinking
             | 
             | Edit: Yep, you're right, wow thats pretty big for me
        
         | graemep wrote:
         | > use python-dotenv to pull settings from environment / .env
         | 
         | I disagree strongly with this one. All you are doing is moving
         | those settings to a different file. You might as well use a
         | local settings file that reads the common settings.
         | 
         | On production keep things like API keys that need to be kept
         | secret elsewhere - as a minimum outside the project directories
         | and owned by a different user.
        
           | senko wrote:
           | Sure, that works as well, for example on some deploys I set
           | the settings in systemd service file. However, it's more
           | convenient to just have .env right there.
           | 
           | > On production keep things like API keys that need to be
           | kept secret elsewhere - as a minimum outside the project
           | directories and owned by a different user.
           | 
           | Curious what extra protection this gives you, considering the
           | environment variables are, well, in the environment, and can
           | be read by process. If someone does a remote code execution
           | attack on the server, they can just read the environment.
           | 
           | The only thing I can imagine it does protect is if you
           | mistakenly expose project root folder on the web server.
        
           | advisedwang wrote:
           | That's something that python-dotenv enables. It can pull from
           | environment, which you can wire up from k8s secrets or
           | whatever is the case for your hosting.
        
       | stuaxo wrote:
       | Nice.
       | 
       | As a mostly-django-dev for the last 15 years, who's been exposed
       | to FastAPI and various ORMs again recently, I should get round to
       | write a doc about some Django bits.
       | 
       | Django is pretty nice, the changes between versions are small and
       | can be managed by a human.
       | 
       | Part of the reason that you can have the big ecosystem is that
       | there is a central place to register settings and INSTALLED_APPS,
       | middleware etc.
       | 
       | That enables addons to bring their own templates and migrations.
       | 
       | There is a central place a bit further up in manage.py and that
       | enables you to bring commandline extras to Django (and many of
       | the things you install will have them).
       | 
       | Coming to a FastAPI app with alembic and finding a lot of that is
       | build-it-yourself (and easily break it) is a bit of a shock.
       | 
       | The Django ORM at first can seem a little alien "why isn't this
       | sqlalchemy" was my reaction a long time ago, but the API is
       | actually pretty pragmatic and allows easy extension.
       | 
       | You can build up some pretty complex queries, and keep them
       | optimised using the Django-Debug-Toolbar and its query viewer.
       | 
       | The ORM, Templates and other parts of Django pre-date many newer
       | standards which is why they have their own versions. As a Django
       | dev I only just discovered the rest of the world has invented
       | testcontainers, and databases as a solution for a problem Django
       | solved years ago with it's test database support.
       | 
       | I quite like the traditional setup where you have
       | settings/common.py and then settings that extend that - e.g
       | local.puy production.py
       | 
       | If you ever need a CMS in your Django project I strongly
       | recommend Wagtail, it came after the initially most popular
       | django-cms and learned a lot of lessons - feeling much more like
       | a part of Django.
       | 
       | It has the same feeling of being productive as Django does when
       | you first use it.
        
         | appplication wrote:
         | > As a Django dev I only just discovered the rest of the world
         | has invented testcontainers, and databases as a solution for a
         | problem Django solved years ago with its test database support.
         | 
         | Testing an API with model-bakery + pytest-django is absolutely
         | joyous. As a TDD nerd, the lack of any remotely similar dev ex
         | in FastAPI is the main reason I've never switched over.
         | 
         | As an aside, as someone who loves ergonomic testing, test
         | containers are not the way. Dockerized services for testing are
         | fine but their management is best done external to your test
         | code. It is far easier to emulate prod by connecting to a
         | general DB/service url that just happens to be running in a
         | local container than have a special test harness that manages
         | this internally to your test suite.
        
       | spapas82 wrote:
       | For anybody starting with Django, I had written a bunch of
       | guidelines some years ago
       | https://spapas.github.io/2022/09/28/django-guidelines/ (after
       | more than 10 years using exclusively Django for my work)
        
         | blorenz wrote:
         | I agree with many -if not all- of these. Thank you for
         | collecting them. These can be readily converted into a
         | SKILL.md.
        
       | kurtis_reed wrote:
       | Here's my notes on starting to use Django: don't
        
       ___________________________________________________________________
       (page generated 2026-01-28 23:01 UTC)