elbear

The right Django project layout

Edit on 18 Jan 2024:

Yeah, I was cocky in this one. I still believe this is a good project structure, but not the only good one.

---

I've seen lately a few Django projects in production that have a layout that is very different from what I consider to be the optimal layout. The reason is that the people who started those projects were new to Django and the tutorial doesn't go into a lot of depth about how to structure your project. That's why I'm writing this, because I think there should be a canonical way to lay out a Django project, just as there are coding style standards. The benefit is that this encourages a better code organization and it also makes it easier for new people to navigate through the code.

The layout that I have in mind starts from the one created by Django's startproject command and adds to it, so that it looks like this:

project/
    README.rst
    fabfile.py
    manage.py
    requirements/
        common.pip
        development.pip
        production.pip
    confs/
        development/
            memcached.conf
            postgresql.conf
        production/
            same files plus
            nginx.conf
            supervisord.conf
            uwsgi.ini
        staging/
            same files
    project/
        __init__.py
        urls.py
        wsgi.py
        apps/
            site-specific apps
        settings/
            __init__.py
            common.py
            development.py
            staging.py
            production.py
            local.py
        static/
        media/
        templates/

Now, what are my arguments for this layout? First, it uses the standard layout of a Python package explained on Hitchhiker's Guide to Packaging. Second, it separates requirements, configuration files and settings based on the deployment environment, which makes deployment straightforward. Third, there is an apps directory that holds all site-specific apps, and you can import from the app directly without specifying the project name (you can do from myapp.models import Foo instead of from myproject.myapp.models import Foo). This is an advantage, because if you make the app standalone at some point and install it in site-packages, you won't have to change your imports.

Another common issue that I've seen is that people mistake an app for the entire project, so they end up with a one-app site. Apps offer specific functionality like accounts, profiles, payment, etc. If you find yourself grouping your models with comments (e.g. Profiles models, Stats models, etc.) then you actually need to split them into separate files.

Having said that, django-startproject is such a template. It has some extra things in there, like the var directory for logs and such, but that is a matter of personal preference, so you can change it as you see fit. It's also pretty new in its current form, so if you find issues, please report them.

If you have something to add, you can join the discussion on reddit or Hacker News.