From 36af43cd3d021dc03276ebdcb04538f24a060cad Mon Sep 17 00:00:00 2001 From: Saqibur Rahman Date: Sun, 26 Nov 2023 16:54:19 +0600 Subject: [PATCH] Update README.md --- README.md | 162 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 84 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 541267e..5a44c25 100644 --- a/README.md +++ b/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/)