Hacker News new | past | comments | ask | show | jobs | submit login
How to Structure Django Projects (jamesbeith.co.uk)
43 points by thornycrackers on June 27, 2018 | hide | past | favorite | 11 comments

This is a totally acceptable approach but not one I personally would prefer.

One of the advantages of django apps is having cleanly divided responsibility. For example, I worked on a large django project that had 70+ apps and several dozen developers. Engineers were encouraged to create new apps for new functionality. In some cases apps could be cleanly pulled out of the code base and converted into a library. The ability to pull libraries out of the "main" repo also meant that certain teams could more easily "own" parts of the codebase. At a different company we actually decided to split our monolith into 3 separately deployed services and it was pretty easy for us to copy the appropriate Django apps into new services.

In general I've found that early in a company's life it is much easier to manage the complexity of a monolith and I've found that Django's app abstraction allows developers to communicate which parts of the codebase shouldn't be overly intimate with one another, which at least gives you a hope of breaking pieces into separately deployable libraries or services as the company/project scales up.

The problem I have with the multi-app approach is that it's really hard to change apps once you've defined them; migrating a model from one app to another is a massive PITA. Because of this, in my experience you pay a high price if you don't define the service boundaries correctly first try. The whole idea behind the "build the monolith first" advice is that in general you don't really know what the appropriate boundaries are going to be ahead of time, so I view this as problematic.

Also over the last few years I've hit multiple schema-migration bugs that only occur on relations spanning apps, and no such bugs within single apps, so there's definitely a "less well-trodden path" argument against multiple apps.

Finally migration squashing didn't work well when I tried it on my multiple-app project; it wasn't able to squash past the first foreign key to another app. This might have improved in the last couple releases.

I've not worked on a project as large as the one you describe, so I'm open to the possibility that at that scale there are new problems that crop up (e.g. managing a single migrations directory could be fun with that many developers), but I'd guess that most developers won't hit that scale, and yet the common wisdom for getting started is to try to split out small apps early, which I consider harmful.

(I'm working on a big Scala Application, but this was migrated from a large Django Application) well in a large project the migrations folder is not your problem. no matter if it is big or small. It's mostly the seperation of concern that can kill your ability to add code to your application. Once your application gets big it's really hard to have a good structure to scale further. The correct "app layout" is pretty important and I think the app structure is a good way to structure __most__ applications.

> Once your application gets big it's really hard to have a good structure to scale further

Agreed - I would note that there is nothing stopping you from having good structure (with multiple independent/encapsulated services/apps) inside a single Django "app" (as the OP suggests).

I couldn't agree more with your approach. If you maintain highly cohesive/loosely coupled django apps in your greenfield monolith, it's relatively trivial to switch to SOA/microservices as you scale the software with your organization.

As described by the documentation, Django applications are “a Python package that provides some set of features”, reusable, and are “a combination of models, views, templates, …, URLs, etc”. What this approach describes is not standard at all to the Django app structure. Some cons to this include: no ability to make new versions of an app and use them concurrently, removing set standards and confusing ANY new engineer that must work on the project, no compartmentalization of business logic, etc etc. There is a reason why Django is structured the way it is. Removing the battle tested skeleton may mean it is not the web framework for your particular project.

For a detailed explanation of what Django app's are and why they are structured the way they are please refer to the `2. Intro to Django Applications` section of https://medium.com/@djstein/modern-django-part-2-rest-apis-a...

For any new Django engineers reading this, I would point you towards https://github.com/pydanny/cookiecutter-django for the best / most complete structure.

> no compartmentalization of business logic, etc etc

The proposed design does compartmentalize business logic; it's all in the `domain` package, divided by business application/use-case. This looks to be to be inspired by the DDD approach.

> no ability to make new versions of an app and use them concurrently

Anecdotal, but I've never required this in my monolithic web app (6 developers), and I don't foresee requiring it any time soon.

> Removing the battle tested skeleton may mean it is not the web framework for your particular project.

This is a bit dogmatic for my taste; Django is just a tool. If the default layout works for you, great. When your project outgrows that default, change it. (But I'd advise being sure that you really have outgrown the defaults before doing so).

Doesn't manage.py have expectations of where things are?

I also think it depends on the project. If your project has 12 apps, you might want to do it around the apps. If it has 3, you might do it around data, domain, and interfaces.

Why data domain and interfaces, btw?

> Doesn't manage.py have expectations of where things are?

Yes, but this is all configurable/remappable; FTA:

> One last note to add is that this project structure results in fewer INSTALLED_APPS entries. The data/ directory, containing the models, and the interfaces directories, containing templates, static files, management commands, etc., all need to be included as entries.

Related; here's an example of an extreme surgery resulting in a single-file Django app:


manage.py is just an convention about the entrypoint to your application, and for manage.py your application is basically just a python modules that are imported (yours and 3rd party app modules). So in the end it boils down to what is in your settings.py regarding 'installed apps' and if manage.py can find and import your settings.py, which is dictated by DJANGO_SETTINGS_MODULE.

> Here are some notes on how to layout a Django project.

Step 0, don't use Django, use Pyramid, unless most of your app is DRF.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact