upvote

  - Django apps are an anitipattern for large internal / single purpose products due to migration overhead as FKs cross application boundaries
Totally agree with this. Now we have thousands of unsquashable migrations that require a ton of work to fix.
reply
Can you share more on this? Is it better to keep all models in one app?
reply
I found parts of the Django RAPID architecture [0] to speak to me. It specifically advocates for just one app. Here's a part of the justification.

> Slicing up your project into apps is something that must be done early, often at the very start of development. This is a simple result of the fact that you need somewhere to put the code you're writing as you go along. In the early days and weeks of work on a new codebase, manage.py startapp gets used a lot, as the high-level structure of the project starts to take shape.

> The issue here is that at this early stage, you often don't really know enough about what the project's final form will look like to correctly draw the boundaries around the apps. Functionality that feels separate at first often becomes deeply entangled, and features that sound similar end up sharing little. Over time, the key concepts and models in your system become clear, and if these are colocated with unrelated or irrelevant code, the waters of the project become muddy and maintenance becomes difficult - before the project is even in production!

> While it is technically possible to migrate models between apps, Django doesn't make it easy, particularly if the models in question have foreign key or many-to-many relationships with other models. And if you think about it, it's not really a technical limitation of the sort that could easily be solved with a PR into Django. It's a conceptual problem: if migrations are a historical record of changes to models, and migrations are encapsulated in the same app as those models, then moving a model to a different app necessarily creates a historical coupling between the two apps that shouldn't really exist.

[0] https://www.django-rapid-architecture.org/structure/

reply
Well whether it's better or worse depends on your specific situation.

What I'm facing right now is a 10 year monolith modularized with applications. Like a sibling comment already discussed these applications are not reusable application so almost all advantages of having that are moot.

Now, the consequence of having this structure is that we now have complex dependencies between the migrations of these apps i.e. cyclic dependencies, dependecy constrains that are underspecified. Thousands of migrations that now take a significant amount of CI time. We would like to squash them but it requires a lot of review and manual work and if we keep using multiple apps we are going to ave the same problem in the future.

The only meaningfull gain we had with multiple apps is that we have less migration conflicts when people create migrations concurrently.

Is that advantage worth the pain? I don't think so.

reply
We have a distributed monolith that's 20-30 years old, that has various systems written in various different languages interacting with multiple interconnected databases. We're working on migrating all of it to python, using django models.

The key thing in a system like this, that was kind of stumbled upon by previous devs who started the python migrations, is the database should be treated as its own independent unit and managed separately from the individual applications that connect to it. For example, we've defined the django models in an independent library that the individual applications import. It also contains the configuration for routing queries to the different databases - only takes a couple of lines of boilerplate in the application's settings file.

We haven't yet switched to using django migrations and are still doing updates manually, but after some work the past couple of years it would now be an option. They would go in the common library, avoiding the pain points you've listed, and could be run from any application that needed it - django tracks the migrations that were run inside the database so they'd all see the same thing and act the same way.

For us, it has absolutely been a major benefit.

reply
Not the author, but I no not understand the desire to use multiple apps. I am never going to want to carve one out as a separate module I re-use in another product. It is all interconnected, why add arbitrary boundaries separating them? Put everything into a "core" app and move on with life. Maybe if you are an enormous organization working on Instagram where you have rigid responsibilities per team.
reply
So you’d prefer one file with all models? Do you break out into apps for business logic? Keep models in one app/file. Then domain driven design elsewhere?
reply
As things get more complicated, I will separate out by some kind of concept. Which can be something as simple as:

  /coreapp
    /forms_foo.py
    /forms_bar.py
    /models_bar.py
    /models_foo.py
    /views_bar.py
    /views_foo.py
You can do a more sophisticated module layout, but essentially something as straightforward as the above, all under a single "core" application. Prevents Django from fighting you when you want to work across the arbitrary "app" boundary.
reply
You don't have to put all your modules into a single file. You can break them into multiple files and the import them into a model file just so that Django loads it from the expected location.

Instead of apps you can just split your components inside a single app using regular python modules.

reply