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 teststemplates/
views.py
- keep your views and view sets hereurls.py
- component’s URL definitionsserializers.py
filters.py
- keep here DRF’s filter backends and anything else related to query set filteringpermissions.py
- DRF permission classesexport.py
- export related utilitiesmodels.py
behaviors.py
- custom model behaviors (aka mixins). LikeSoftDeletable
,Timestampable
, etc.validators.py
- contains various Validator subclasses and other utilities we use to validate datatasks.py
- for Celery or RQ tasksmails.py
- functions that send emails (likesend_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
- Phoenix Contexts. Contexts are dedicated modules that expose and group related functionality.