Django app structure that I favor.

Instead of having all views in one file I separate components by domain and put each in the own python package (represented as a directory). If you are familiar with DDD terminology, then package can represent a bounded context.

Package structure

Here is a file and directory structure that I use in my projects. I try to keep as close to Django’s default app structure as possible.

Don’t make each module a Django app. Usually, it is not necessary at all and only adds maintenance complexity. Django’s apps are great for sharing code between projects, and mostly useless when used only in one project.

Where to put my API modules?

The recommended place for them is the root of your project package:

.
└── myproject
    ├── auth
    ├── comments
    ├── posts
    ├── users
    └── __init__.py

Common files and subdirectories

  • tests/ - module unit tests
  • templates/
  • views.py - keep your views and view sets here
  • urls.py - component’s URL definitions
  • serializers.py
  • filters.py - keep here DRF’s filter backends and anything else related to query set filtering
  • permissions.py - DRF permission classes
  • export.py - export related utilities
  • models.py
  • behaviors.py - custom model behaviors (aka mixins). Like SoftDeletable, Timestampable, etc.
  • validators.py - contains various Validator subclasses and other utilities we use to validate data
  • tasks.py - for Celery or RQ tasks
  • mails.py - functions that send emails (like send_password_reset_mail)

Example file layout you can find in my project

.
├── export.py
├── filters.py
├── __init__.py
├── permissions.py
├── serializers.py
├── urls.py
└── views.py

Module nesting

If the domain component is large, and you know how to split it into subdomains, then you can reflect this structure on the file system using subdirectories of your component.

.
└── myproject
    ├── feature_one
    │   └── __init__.py
    ├── feature_two          <-- base module
    │   ├── subfeature_one   <-- sub module 1
    │   │   └── __init__.py
    │   ├── subfeature_two   <-- sub module 2
    │   │   └── __init__.py
    │   └── __init__.py
    └── __init__.py

Prefer to have only one level of nesting.

A real world well-structured example can be seen in this repo taigaio/taiga-back.

Further reading

  1. Phoenix Contexts. Contexts are dedicated modules that expose and group related functionality.
Alex Oleshkevich

Alex Oleshkevich

Alex is a full-stack software developer with 15+ years of web development experience. His primary stack is Python, PHP, and JavaScript.
Minsk, Belarus