Update README.md
This commit is contained in:
parent
eb5ab42e1c
commit
36af43cd3d
162
README.md
162
README.md
|
@ -1,9 +1,21 @@
|
|||
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
|
||||
[![Python 3.10.8](https://img.shields.io/badge/python-3.10.8-blue.svg)](https://www.python.org/downloads/release/python-3108//)
|
||||
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
|
||||
|
||||
![Django](https://img.shields.io/badge/django-%23092E20.svg?style=for-the-badge&logo=django&logoColor=white)
|
||||
![DjangoREST](https://img.shields.io/badge/DJANGO-REST-ff1709?style=for-the-badge&logo=django&logoColor=white&color=ff1709&labelColor=gray)
|
||||
![Postgres](https://img.shields.io/badge/postgres-%23316192.svg?style=for-the-badge&logo=postgresql&logoColor=white)
|
||||
![Swagger](https://img.shields.io/badge/-Swagger-%23Clojure?style=for-the-badge&logo=swagger&logoColor=white)
|
||||
|
||||
|
||||
# Django Project Structure
|
||||
This is a template/project structure for developing django-based applications -
|
||||
either strictly through the `django-rest-framework` or just `django`.
|
||||
|
||||
The project is meant to be easily clone-able, and used as the starter template for
|
||||
the next big thing our team develops.
|
||||
The project is meant to be easily clone-able, and used as the starter template
|
||||
for the next big thing you develop. Note, this is a folder structure only, not
|
||||
“best practices”.
|
||||
|
||||
|
||||
## Getting Started
|
||||
1. Clone the repo from GitHub
|
||||
|
@ -16,53 +28,42 @@ success page provided by Django at [http://127.0.0.1:8000/](http://127.0.0.1:800
|
|||
|
||||
### Creating an App
|
||||
1. Create a folder with the app name in `apps`. For example: `poll`
|
||||
1. Run `python manage.py startapp poll apps/poll` from the root directory of the project
|
||||
|
||||
|
||||
## Scope
|
||||
- Goal: Develop a structure for both `django-rest-framework` and `django` projects.
|
||||
- Easily clone-able when starting new projects
|
||||
- Folder structure only, not “best practices”
|
||||
- We won’t be enforcing about best practices in implementation details
|
||||
- We’ll hold all questions in a GitHub repository, so things can move forward
|
||||
- The discussions also serve historic significance - people can backtrack why some decisions were made.
|
||||
1. Run `python manage.py startapp poll apps/poll` from the root directory of the
|
||||
project
|
||||
|
||||
|
||||
## Project Tree
|
||||
```bash
|
||||
``` bash
|
||||
.
|
||||
├── apps
|
||||
│ └── example_api # A django rest app
|
||||
│ └── example # A django rest app
|
||||
│ ├── api
|
||||
│ │ ├── v1
|
||||
│ │ ├── v1 # Only the "presentation" layer exists here.
|
||||
│ │ │ ├── __init__.py
|
||||
│ │ │ ├── serializers.py
|
||||
│ │ │ ├── services.py
|
||||
│ │ │ ├── tests.py
|
||||
│ │ │ ├── urls.py
|
||||
│ │ │ └── views.py
|
||||
│ │ ├── v2
|
||||
│ │ ├── v2 # Only the "presentation" layer exists here.
|
||||
│ │ │ ├── __init__.py
|
||||
│ │ │ ├── serializers.py
|
||||
│ │ │ ├── services.py
|
||||
│ │ │ ├── tests.py
|
||||
│ │ │ ├── urls.py
|
||||
│ │ │ └── views.py
|
||||
│ │ └── __init__.py
|
||||
│ ├── fixtures # Constant "seeders" to populate your database
|
||||
│ ├── management
|
||||
│ │ ├── commands
|
||||
│ │ ├── commands # Try and write some database seeders here
|
||||
│ │ │ └── command.py
|
||||
│ │ └── __init__.py
|
||||
│ ├── migrations
|
||||
│ │ └── __init__.py
|
||||
│ ├── templates
|
||||
│ ├── tests
|
||||
│ ├── templates # App-specific templates go here
|
||||
│ ├── tests # All your integration and unit tests for an app go here.
|
||||
│ ├── admin.py
|
||||
│ ├── apps.py
|
||||
│ ├── __init__.py
|
||||
│ ├── models.py
|
||||
│ ├── services.py # Your business logic and data abstractions go here.
|
||||
│ ├── urls.py
|
||||
│ ├── utils.py
|
||||
│ └── views.py
|
||||
├── common # An optional folder containing common "stuff" for the entire project
|
||||
├── config
|
||||
|
@ -71,13 +72,7 @@ success page provided by Django at [http://127.0.0.1:8000/](http://127.0.0.1:800
|
|||
│ ├── __init__.py
|
||||
│ ├── urls.py
|
||||
│ └── wsgi.py
|
||||
├── deployments
|
||||
│ ├── django-project
|
||||
│ │ └── Dockerfile
|
||||
│ ├── nginx
|
||||
│ │ ├── default.conf
|
||||
│ │ └── Dockerfile
|
||||
│ └── docker-compose.yml
|
||||
├── deployments # Isolate Dockerfiles and docker-compose files here.
|
||||
├── docs
|
||||
│ ├── CHANGELOG.md
|
||||
│ ├── CONTRIBUTING.md
|
||||
|
@ -85,31 +80,47 @@ success page provided by Django at [http://127.0.0.1:8000/](http://127.0.0.1:800
|
|||
│ ├── local-development.md
|
||||
│ └── swagger.yaml
|
||||
├── requirements
|
||||
│ ├── common.txt
|
||||
│ ├── development.txt
|
||||
│ ├── local.txt
|
||||
│ └── production.txt
|
||||
├── static
|
||||
├── entrypoint.sh
|
||||
│ ├── common.txt # Same for all environments
|
||||
│ ├── development.txt # Only for a development server
|
||||
│ ├── local.txt # Only for a local server (example: docs, performance testing, etc.)
|
||||
│ └── production.txt # Production only
|
||||
├── static # Your static files
|
||||
├── .env.example # An example of your .env configurations. Add necessary comments.
|
||||
├── static # Your static files
|
||||
├── .gitignore # https://github.com/github/gitignore/blob/main/Python.gitignore
|
||||
├── entrypoint.sh # Any bootstrapping necessary for your application
|
||||
├── manage.py
|
||||
├── pytest.ini
|
||||
└── README.md
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Rationale
|
||||
Each `app` should be designed in way to be plug-able, that is, dragged and dropped
|
||||
into any other project and it’ll work independently.
|
||||
|
||||
### `apps`
|
||||
* A mother-folder containing all apps for our project. Congruent to any JS-framework's `src` folder.
|
||||
* An app can be a django template project, or an API.
|
||||
|
||||
### `api`
|
||||
### `apps` Folder
|
||||
* A mother-folder containing all apps for our project. Congruent to any
|
||||
JS-framework's `src` folder. If you really wanted to, you could even call it the
|
||||
`src` folder. Again, it's up to you.
|
||||
* An app can be a django template project, or an rest framework API.
|
||||
|
||||
### `services`
|
||||
* We’ll be writing business logic in services instead of anywhere else.
|
||||
* There's a common argument: "Why not just use model managers?", and honestly,
|
||||
that's a fair point. However, for our use case, we've often noticed that a single
|
||||
service can leverage more zero to many models. Either way, managers or services,
|
||||
both work towards the same goal - isolating business logic away from views, and
|
||||
brings it closer to the data.
|
||||
|
||||
### `api` Folder
|
||||
* We like to place all our API components into a package within an app called
|
||||
`api`. For example, in this repository it's the `example_api/api` folder. That allows us to isolate our API components in a consistent location. If
|
||||
`api`. For example, in this repository it's the `example/api` folder. That
|
||||
allows us to isolate our API components in a consistent location. If
|
||||
we were to put it in the root of our app, then we would end up with a huge list
|
||||
of API-specific modules in the general area of the app.
|
||||
of API-specific modules in the general area of the app. That's without getting
|
||||
into the mess of API versioning.
|
||||
|
||||
For projects with a lot of small, interconnecting apps, it can be hard to hunt
|
||||
down where a particular API view lives. In contrast to placing all API code
|
||||
|
@ -117,23 +128,43 @@ within each relevant app, sometimes it makes more sense to build an app
|
|||
specifically for the API. This is where all the serializers, renderers, and views
|
||||
are placed. Therefore, the name of the app should reflect its API version
|
||||
|
||||
### `api-versioning`
|
||||
It might often be necessary to support multiple versions of an API throughout the lifetime of a project. Therefore, we're adding in support right from the start.
|
||||
|
||||
#### API Versioning
|
||||
It might often be necessary to support multiple versions of an API throughout
|
||||
the lifetime of a project. Therefore, we're adding in support right from the
|
||||
start.
|
||||
|
||||
For different API versions, we're assuming the following will change:
|
||||
- Serializers
|
||||
- Views
|
||||
- URLs
|
||||
- Services
|
||||
- Serializers: That is, how the data is presented to a consumer
|
||||
- Views: That is, how the data is accessed and modified by a consumer
|
||||
- URLs: That is, where the consumer access the data
|
||||
|
||||
`model`s can be thought of as shared between versions. Therefore, migrating changes should be versioned carefully without breaking different versions of the API.
|
||||
`model`s and `service`s can be thought of as shared between versions. Therefore,
|
||||
migrating changes should be versioned carefully without breaking different
|
||||
versions of the API. After all, your API version is simply a presentation of how
|
||||
data is handled and managed within your application.
|
||||
|
||||
Sufficient unit tests and integration tests should wrap services and API
|
||||
endpoints to ensure full compatibility.
|
||||
|
||||
|
||||
### What's Version 2?
|
||||
#### What's `v2` of an API?
|
||||
Currently we're proposing that major changes to the following, constitutes a new API version:
|
||||
1. Representation of data, either for submission or retrieval
|
||||
1. Major optimizations
|
||||
1. Major code reorganization and code refactor
|
||||
1. Usually, in a Django project, you won't need to worry about API versioning
|
||||
|
||||
|
||||
### `config`
|
||||
* Contains project configuration files, including the primary URL file
|
||||
* ~~Contains settings split into `base`, `local`, `production` and `development`.~~.
|
||||
Update: As environment specific variables will be handled using environment
|
||||
variables, we've deemed it unnecessary to have separate settings files for now.
|
||||
|
||||
### `deployments`
|
||||
* Contains Docker, Docker-Compose and nginx specific files for deploying in
|
||||
different environments.
|
||||
|
||||
|
||||
### Exception handling
|
||||
|
@ -142,32 +173,6 @@ who consumes your APIs. To learn how to create a custom exception handler,
|
|||
you can check out the Django Rest Framework documentation at:
|
||||
https://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-handling
|
||||
|
||||
### `config`
|
||||
* Contains project configuration files, including the primary URL file
|
||||
* ~~Contains settings split into `base`, `local`, `production` and `development`.~~. Update: As environment
|
||||
specific variables will be handled using environment variables, we've deemed it unnecessary to have
|
||||
separate settings files.
|
||||
|
||||
|
||||
### `deployments`
|
||||
* Contains Docker, Docker-Compose and nginx specific files for deploying in different
|
||||
environments
|
||||
|
||||
|
||||
### `documentation`
|
||||
* We’ll have CHANGELOG.md
|
||||
* We’ll have CONTRIBUTING.md
|
||||
* We’ll have deployment instructions
|
||||
* We’ll have local startup instructions
|
||||
|
||||
|
||||
### `services`
|
||||
* We’ll be writing business logic in services instead of anywhere else.
|
||||
|
||||
|
||||
### `gitignore`
|
||||
* https://github.com/github/gitignore/blob/main/Python.gitignore
|
||||
|
||||
|
||||
## References
|
||||
- [Two Scoops of Django by Daniel and Audrey Feldroy](https://www.feldroy.com/books/two-scoops-of-django-3-x)
|
||||
|
@ -175,3 +180,4 @@ environments
|
|||
- [Cookiecutter Django](https://github.com/cookiecutter/cookiecutter-django)
|
||||
- [HackSoft Django Style Guide](https://github.com/HackSoftware/Django-Styleguide)
|
||||
- [Radoslav Georgiev - Django Structure for Scale and Longevity](https://www.youtube.com/watch?v=yG3ZdxBb1oo)
|
||||
- [Build APIs You Won't Hate](https://apisyouwonthate.com/books/build-apis-you-wont-hate/)
|
||||
|
|
Loading…
Reference in New Issue