REST API with Django - Part 2
Wed 11 September 2024 by OdolixPart 2 - Project structure
Django project and modules - reuse
Django has a 2 level architecture:
- a project, that contains settings and that is run
- apps, that contain domain specific code and that are included in a project.
When creating a django project, you can either include apps directly as sub folders, or indirectly as external python packages.
I used to split code into different repos to enhance re-usability of the code, but with monorepo and packaging tools like PDM, it's easier to have a single repo and to deploy modules based on your needs and dependencies.
Project structure
A typical project would have this file: manage.py, which is the Django CLI file. It allows to launch management commands like migrations and translations, and launch the dev server.
Here is a common structure on my projects:
- manage.py
- config: project configuration folder, specific to the execution environment
- settings.py: file containing general project settings
- asgi.py: asgi server parameters, asgi is the asynchronous server
- wsgi.py: wsgi server parameters, wsgi is the classic server
- urls.py: project routing, includes module routing
- .gitignore: don't commit cache files or env files
- pyproject.toml: project package settings
- README.md: Explain what your project does
- docker: provide a docker script to run the service
App structure
An app is a domain code. It contains models, views, and controllers for one domain, and should not mix different domains.
The common app / module structure looks like this:
- models.py: contains model classes
- viewsets.py: contains REST CRUD controllers
- serializers.py: Serialization classes, used for validation and formatting of information
- tests.py: Unit and functional tests
- urls.py: routing for this app
When building a pure REST service, I don't use django's views.py because I don't serve Views.
I often use these additional files:
- filters.py: manage django-filters classe to handle query param filtering
- permissions.py: manage REST permisison classes
Micro-service / Domain app
When dealing with a microservice, each app will contain a very simple model, along with serializers and viewsest. In that case, the above structure is sufficient.
If I deal with a domain / macro-service REST API, I have to deal with larger models, serializers and viewsets, so I split the files into subfolders:
- models
__init__.py
- model1.py
- ...
- serializers:
__init__.py
- model1_serializers.py
- ...
and so on.
Wrap up
This is a minimal structure that can be extended, but that covers most of my needs, while keeping things organized and easy to manage and expand.