diff --git a/README.md b/README.md index 27761f9..048eaf5 100644 --- a/README.md +++ b/README.md @@ -215,3 +215,9 @@ defaults, but let's hope we have time to work on it on the `cookiecutter` branch - [Build APIs You Won't Hate](https://apisyouwonthate.com/books/build-apis-you-wont-hate/) - [Tuxedo Style Guides](https://github.com/saqibur/tuxedo) - [Django Anti Patterns](https://www.django-antipatterns.com/) + + +## Documentation +* Copy README.md to `mkdocs` folder +* Build: `mkdocs build -d docs` +* Serve: `mkdocs serve` diff --git a/docs/404.html b/docs/404.html index 7d3fad2..967f89e 100644 --- a/docs/404.html +++ b/docs/404.html @@ -2,94 +2,94 @@ - + - - - - + + + + - - - - - + + + + + - - - - + + + + Django Project Structure - - - + + + - - + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - + + + + + + + - - - + + +
- +
- -
- - - - + + + + + +
- +
- +
- - - - - - + + + + + +
- - - + + +
- +
- - - + + +
- +
- - - + + +
- +

404 - Not found

- - + +
- +
- + - +
- - + + - - + + - - + + - \ No newline at end of file + diff --git a/docs/index.html b/docs/index.html index 211e33c..fd6923a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2,101 +2,101 @@ - + - - - - + + + + - - + + - - - - + + + + - - - - + + + + Django Project Structure - - - + + + - - + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - + + + + + + + - - - + + +
- - + + Skip to content - +
- -
- - - - + + + + + +
- +
- +
- - - - - - + + + + + +
- - - + + +
- + + + + + +
- - - + + +
- +
- - - + + +
- - - - - -

Code style: black -Python 3.10.8 -Ruff

+ + + + + +

Python 3.12.3 +Ruff +Pre-commit

Django DjangoREST Postgres Swagger

Django Project Structure

This is a template/project structure for developing django-based applications - -either strictly through the django-rest-framework or just django.

+using django-rest-framework along with django.

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”.

+

Some batteries included:

+

Getting Started

  1. Since this is a template repository, simply hit "Use this template" on GitHub @@ -612,7 +656,18 @@ anything you see fit.
  2. Run the project using python manage.py runserver and you should see the default success page provided by Django at http://127.0.0.1:8000/.
  3. +
  4. [Optional] If you want to configure database, in the DATABASE section of +settings.py we have added postgresql as the default DATABASE (As most of +the application are using it). You can roll back to the sqlite by adding the +following code snippet, removing the current one.
+
DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+    }
+}
+

Creating an App

  1. Create a folder with the app name in apps. For example: poll
  2. @@ -621,60 +676,59 @@ project

Project Tree

.
-├── apps
-│   └── example # A django rest app
-│       ├── api
-│       │   ├── v1 # Only the "presentation" layer exists here.
+├── apps/
+│   └── example/                    # A django rest app
+│       ├── api/
+│       │   ├── v1/                 # Only the "presentation" layer exists here.
 │       │   │   ├── __init__.py
 │       │   │   ├── serializers.py
 │       │   │   ├── urls.py
 │       │   │   └── views.py
-│       │   ├── v2 # Only the "presentation" layer exists here.
+│       │   ├── v2                  # Only the "presentation" layer exists here.
 │       │   │   ├── __init__.py
 │       │   │   ├── serializers.py
 │       │   │   ├── urls.py
 │       │   │   └── views.py
 │       │   └── __init__.py
-│       ├── fixtures # Constant "seeders" to populate your database
-│       ├── management
-│       │   ├── commands # Try and write some database seeders here
+│       ├── fixtures/               # Constant "seeders" to populate your database
+│       ├── management/
+│       │   ├── commands/           # Try and write some database seeders here
 │       │   │   └── command.py
 │       │   └── __init__.py
-│       ├── migrations
+│       ├── migrations/
 │       │   └── __init__.py
-│       ├── templates # App-specific templates go here
-│       ├── tests # All your integration and unit tests for an app go here.
+│       ├── templates/              # App-specific templates go here
+│       ├── tests/                  # All your integration and unit tests for an app go here.
+│       ├── __init__.py
 │       ├── admin.py
 │       ├── apps.py
-│       ├── __init__.py
 │       ├── models.py
-│       ├── services.py # Your business logic and data abstractions go here.
+│       ├── services.py             # Your business logic and data abstractions go here.
 │       ├── urls.py
 │       └── views.py
-├── common # An optional folder containing common "stuff" for the entire project
-├── config
-│   ├── settings.py
-│   ├── asgi.py
+├── common/                         # An optional folder containing common "stuff" for the entire project
+├── config/
 │   ├── __init__.py
+│   ├── asgi.py
+│   ├── settings.py
 │   ├── urls.py
 │   └── wsgi.py
-├── deployments # Isolate Dockerfiles and docker-compose files here.
-├── docs
+├── deployments/                    # Isolate Dockerfiles and docker-compose files here.
+├── docs/
 │   ├── CHANGELOG.md
 │   ├── CONTRIBUTING.md
 │   ├── deployment.md
 │   ├── local-development.md
 │   └── swagger.yaml
-├── requirements
-│   ├── 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
+├── requirements/
+│   ├── 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.
+├── .gitignore                      # https://github.com/github/gitignore/blob/main/Python.gitignore
+├── entrypoint.sh                   # Any bootstrapping necessary for your application
 ├── manage.py
 ├── pytest.ini
 └── README.md
@@ -687,7 +741,7 @@ into any other project and it’ll work independently.

  • 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.
  • +
  • An app can be a django template project, or a rest framework API.
  • services

      @@ -727,7 +781,8 @@ 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 v2 of an API?

      -

      Currently we're proposing that major changes to the following, constitutes a new API version: +

      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 @@ -749,6 +804,16 @@ different environments. 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

      +

      FAQ

      +
      +

      Why not just make a cookiecutter out of this?

      +
      +

      Honestly, GitHub templates are so much easier. It's a one-click solution and +you're good to go. If we want to turn this into a cookiecutter, we'd have to also +start deciding sensible defaults, for instance, sentry, DRF version, formatters, +linters, etc. And that's something better left to the developer. Although, I am +playing around with the idea of having a cookiecutter with those sensible +defaults, but let's hope we have time to work on it on the cookiecutter branch.

      References

      - +
    - - + +
    - +
    - + - +
    - - + + - - + + - - + + - \ No newline at end of file + diff --git a/docs/search/search_index.json b/docs/search/search_index.json index df37c72..7f1656c 100644 --- a/docs/search/search_index.json +++ b/docs/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":""},{"location":"#django-project-structure","title":"Django Project Structure","text":"

    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 you develop. Note, this is a folder structure only, not \u201cbest practices\u201d.

    "},{"location":"#getting-started","title":"Getting Started","text":"
    1. Since this is a template repository, simply hit \"Use this template\" on GitHub and follow the instructions. Otherwise, you can just clone the repo, remove/add anything you see fit.
    2. Run the project using python manage.py runserver and you should see the default success page provided by Django at http://127.0.0.1:8000/.
    "},{"location":"#creating-an-app","title":"Creating an App","text":"
    1. Create a folder with the app name in apps. For example: poll
    2. Run python manage.py startapp poll apps/poll from the root directory of the project
    "},{"location":"#project-tree","title":"Project Tree","text":"
    .\n\u251c\u2500\u2500 apps\n\u2502   \u2514\u2500\u2500 example # A django rest app\n\u2502       \u251c\u2500\u2500 api\n\u2502       \u2502   \u251c\u2500\u2500 v1 # Only the \"presentation\" layer exists here.\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 __init__.py\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 serializers.py\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 urls.py\n\u2502       \u2502   \u2502   \u2514\u2500\u2500 views.py\n\u2502       \u2502   \u251c\u2500\u2500 v2 # Only the \"presentation\" layer exists here.\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 __init__.py\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 serializers.py\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 urls.py\n\u2502       \u2502   \u2502   \u2514\u2500\u2500 views.py\n\u2502       \u2502   \u2514\u2500\u2500 __init__.py\n\u2502       \u251c\u2500\u2500 fixtures # Constant \"seeders\" to populate your database\n\u2502       \u251c\u2500\u2500 management\n\u2502       \u2502   \u251c\u2500\u2500 commands # Try and write some database seeders here\n\u2502       \u2502   \u2502   \u2514\u2500\u2500 command.py\n\u2502       \u2502   \u2514\u2500\u2500 __init__.py\n\u2502       \u251c\u2500\u2500 migrations\n\u2502       \u2502   \u2514\u2500\u2500 __init__.py\n\u2502       \u251c\u2500\u2500 templates # App-specific templates go here\n\u2502       \u251c\u2500\u2500 tests # All your integration and unit tests for an app go here.\n\u2502       \u251c\u2500\u2500 admin.py\n\u2502       \u251c\u2500\u2500 apps.py\n\u2502       \u251c\u2500\u2500 __init__.py\n\u2502       \u251c\u2500\u2500 models.py\n\u2502       \u251c\u2500\u2500 services.py # Your business logic and data abstractions go here.\n\u2502       \u251c\u2500\u2500 urls.py\n\u2502       \u2514\u2500\u2500 views.py\n\u251c\u2500\u2500 common # An optional folder containing common \"stuff\" for the entire project\n\u251c\u2500\u2500 config\n\u2502   \u251c\u2500\u2500 settings.py\n\u2502   \u251c\u2500\u2500 asgi.py\n\u2502   \u251c\u2500\u2500 __init__.py\n\u2502   \u251c\u2500\u2500 urls.py\n\u2502   \u2514\u2500\u2500 wsgi.py\n\u251c\u2500\u2500 deployments # Isolate Dockerfiles and docker-compose files here.\n\u251c\u2500\u2500 docs\n\u2502   \u251c\u2500\u2500 CHANGELOG.md\n\u2502   \u251c\u2500\u2500 CONTRIBUTING.md\n\u2502   \u251c\u2500\u2500 deployment.md\n\u2502   \u251c\u2500\u2500 local-development.md\n\u2502   \u2514\u2500\u2500 swagger.yaml\n\u251c\u2500\u2500 requirements\n\u2502   \u251c\u2500\u2500 common.txt # Same for all environments\n\u2502   \u251c\u2500\u2500 development.txt # Only for a development server\n\u2502   \u251c\u2500\u2500 local.txt # Only for a local server (example: docs, performance testing, etc.)\n\u2502   \u2514\u2500\u2500 production.txt # Production only\n\u251c\u2500\u2500 static # Your static files\n\u251c\u2500\u2500 .env.example # An example of your .env configurations. Add necessary comments.\n\u251c\u2500\u2500 static # Your static files\n\u251c\u2500\u2500 .gitignore # https://github.com/github/gitignore/blob/main/Python.gitignore\n\u251c\u2500\u2500 entrypoint.sh # Any bootstrapping necessary for your application\n\u251c\u2500\u2500 manage.py\n\u251c\u2500\u2500 pytest.ini\n\u2514\u2500\u2500 README.md\n
    "},{"location":"#rationale","title":"Rationale","text":"

    Each app should be designed in way to be plug-able, that is, dragged and dropped into any other project and it\u2019ll work independently.

    "},{"location":"#apps-folder","title":"apps Folder","text":""},{"location":"#services","title":"services","text":""},{"location":"#api-folder","title":"api Folder","text":"

    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 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

    "},{"location":"#api-versioning","title":"API Versioning","text":"

    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: 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

    models and services 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.

    "},{"location":"#whats-v2-of-an-api","title":"What's v2 of an API?","text":"

    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

    "},{"location":"#config","title":"config","text":""},{"location":"#deployments","title":"deployments","text":""},{"location":"#exception-handling","title":"Exception handling","text":"

    You should probably add a custom exception handler to your project based on 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

    "},{"location":"#references","title":"References","text":""}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":""},{"location":"#django-project-structure","title":"Django Project Structure","text":"

    This is a template/project structure for developing django-based applications - using django-rest-framework along with django.

    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 \u201cbest practices\u201d.

    "},{"location":"#some-batteries-included","title":"Some batteries included:","text":""},{"location":"#getting-started","title":"Getting Started","text":"
    1. Since this is a template repository, simply hit \"Use this template\" on GitHub and follow the instructions. Otherwise, you can just clone the repo, remove/add anything you see fit.
    2. Run the project using python manage.py runserver and you should see the default success page provided by Django at http://127.0.0.1:8000/.
    3. [Optional] If you want to configure database, in the DATABASE section of settings.py we have added postgresql as the default DATABASE (As most of the application are using it). You can roll back to the sqlite by adding the following code snippet, removing the current one.
    DATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.sqlite3',\n        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),\n    }\n}\n
    "},{"location":"#creating-an-app","title":"Creating an App","text":"
    1. Create a folder with the app name in apps. For example: poll
    2. Run python manage.py startapp poll apps/poll from the root directory of the project
    "},{"location":"#project-tree","title":"Project Tree","text":"
    .\n\u251c\u2500\u2500 apps/\n\u2502   \u2514\u2500\u2500 example/                    # A django rest app\n\u2502       \u251c\u2500\u2500 api/\n\u2502       \u2502   \u251c\u2500\u2500 v1/                 # Only the \"presentation\" layer exists here.\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 __init__.py\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 serializers.py\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 urls.py\n\u2502       \u2502   \u2502   \u2514\u2500\u2500 views.py\n\u2502       \u2502   \u251c\u2500\u2500 v2                  # Only the \"presentation\" layer exists here.\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 __init__.py\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 serializers.py\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 urls.py\n\u2502       \u2502   \u2502   \u2514\u2500\u2500 views.py\n\u2502       \u2502   \u2514\u2500\u2500 __init__.py\n\u2502       \u251c\u2500\u2500 fixtures/               # Constant \"seeders\" to populate your database\n\u2502       \u251c\u2500\u2500 management/\n\u2502       \u2502   \u251c\u2500\u2500 commands/           # Try and write some database seeders here\n\u2502       \u2502   \u2502   \u2514\u2500\u2500 command.py\n\u2502       \u2502   \u2514\u2500\u2500 __init__.py\n\u2502       \u251c\u2500\u2500 migrations/\n\u2502       \u2502   \u2514\u2500\u2500 __init__.py\n\u2502       \u251c\u2500\u2500 templates/              # App-specific templates go here\n\u2502       \u251c\u2500\u2500 tests/                  # All your integration and unit tests for an app go here.\n\u2502       \u251c\u2500\u2500 __init__.py\n\u2502       \u251c\u2500\u2500 admin.py\n\u2502       \u251c\u2500\u2500 apps.py\n\u2502       \u251c\u2500\u2500 models.py\n\u2502       \u251c\u2500\u2500 services.py             # Your business logic and data abstractions go here.\n\u2502       \u251c\u2500\u2500 urls.py\n\u2502       \u2514\u2500\u2500 views.py\n\u251c\u2500\u2500 common/                         # An optional folder containing common \"stuff\" for the entire project\n\u251c\u2500\u2500 config/\n\u2502   \u251c\u2500\u2500 __init__.py\n\u2502   \u251c\u2500\u2500 asgi.py\n\u2502   \u251c\u2500\u2500 settings.py\n\u2502   \u251c\u2500\u2500 urls.py\n\u2502   \u2514\u2500\u2500 wsgi.py\n\u251c\u2500\u2500 deployments/                    # Isolate Dockerfiles and docker-compose files here.\n\u251c\u2500\u2500 docs/\n\u2502   \u251c\u2500\u2500 CHANGELOG.md\n\u2502   \u251c\u2500\u2500 CONTRIBUTING.md\n\u2502   \u251c\u2500\u2500 deployment.md\n\u2502   \u251c\u2500\u2500 local-development.md\n\u2502   \u2514\u2500\u2500 swagger.yaml\n\u251c\u2500\u2500 requirements/\n\u2502   \u251c\u2500\u2500 common.txt                  # Same for all environments\n\u2502   \u251c\u2500\u2500 development.txt             # Only for a development server\n\u2502   \u251c\u2500\u2500 local.txt                   # Only for a local server (example: docs, performance testing, etc.)\n\u2502   \u2514\u2500\u2500 production.txt              # Production only\n\u251c\u2500\u2500 static/                         # Your static files\n\u251c\u2500\u2500 .env.example                    # An example of your .env configurations. Add necessary comments.\n\u251c\u2500\u2500 .gitignore                      # https://github.com/github/gitignore/blob/main/Python.gitignore\n\u251c\u2500\u2500 entrypoint.sh                   # Any bootstrapping necessary for your application\n\u251c\u2500\u2500 manage.py\n\u251c\u2500\u2500 pytest.ini\n\u2514\u2500\u2500 README.md\n
    "},{"location":"#rationale","title":"Rationale","text":"

    Each app should be designed in way to be plug-able, that is, dragged and dropped into any other project and it\u2019ll work independently.

    "},{"location":"#apps-folder","title":"apps Folder","text":""},{"location":"#services","title":"services","text":""},{"location":"#api-folder","title":"api Folder","text":"

    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 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

    "},{"location":"#api-versioning","title":"API Versioning","text":"

    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: 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

    models and services 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.

    "},{"location":"#whats-v2-of-an-api","title":"What's v2 of an API?","text":"

    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

    "},{"location":"#config","title":"config","text":""},{"location":"#deployments","title":"deployments","text":""},{"location":"#exception-handling","title":"Exception handling","text":"

    You should probably add a custom exception handler to your project based on 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

    "},{"location":"#faq","title":"FAQ","text":"

    Why not just make a cookiecutter out of this?

    Honestly, GitHub templates are so much easier. It's a one-click solution and you're good to go. If we want to turn this into a cookiecutter, we'd have to also start deciding sensible defaults, for instance, sentry, DRF version, formatters, linters, etc. And that's something better left to the developer. Although, I am playing around with the idea of having a cookiecutter with those sensible defaults, but let's hope we have time to work on it on the cookiecutter branch.

    "},{"location":"#references","title":"References","text":""}]} diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 99060ff..e0b5998 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -2,7 +2,7 @@ https://github.com/saqibur/django-project-structure/ - 2023-11-26 + 2024-11-05 daily - \ No newline at end of file + diff --git a/docs/sitemap.xml.gz b/docs/sitemap.xml.gz index f6bce4c..3dad79c 100644 Binary files a/docs/sitemap.xml.gz and b/docs/sitemap.xml.gz differ diff --git a/mkdocs/index.md b/mkdocs/index.md index 57a4c1b..27761f9 100644 --- a/mkdocs/index.md +++ b/mkdocs/index.md @@ -1,6 +1,6 @@ -[![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//) +[![Python 3.12.3](https://img.shields.io/badge/python-3.12.3-blue.svg)](https://www.python.org/downloads/release/python-3123/) [![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) +[![Pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://pre-commit.com/) ![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) @@ -10,13 +10,21 @@ # Django Project Structure This is a template/project structure for developing django-based applications - -either strictly through the `django-rest-framework` or just `django`. +using `django-rest-framework` along with `django`. 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”. +## Some batteries included: +* [Django Storages](https://django-storages.readthedocs.io/en/stable/) - To integrate with different types of storages +* [Django Rest Framework](https://www.django-rest-framework.org/) - For API development +* [Django CORS Headers](https://github.com/adamchainz/django-cors-headers) - To allow requests from other origins +* [Sentry](https://docs.sentry.io/platforms/python/) - For crashes +* [Gunicorn](https://gunicorn.org/) - As a web server + + ## Getting Started 1. Since this is a template repository, simply hit "Use this template" on GitHub and follow the instructions. Otherwise, you can just clone the repo, remove/add @@ -24,6 +32,20 @@ anything you see fit. 1. Run the project using `python manage.py runserver` and you should see the default success page provided by Django at [http://127.0.0.1:8000/](http://127.0.0.1:8000/). +1. [Optional] If you want to configure database, in the `DATABASE` section of +`settings.py` we have added `postgresql` as the default `DATABASE` (As most of +the application are using it). You can roll back to the `sqlite` by adding the +following code snippet, removing the current one. + +```bash +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + ### Creating an App 1. Create a folder with the app name in `apps`. For example: `poll` @@ -34,60 +56,59 @@ project ## Project Tree ``` bash . -├── apps -│ └── example # A django rest app -│ ├── api -│ │ ├── v1 # Only the "presentation" layer exists here. +├── apps/ +│ └── example/ # A django rest app +│ ├── api/ +│ │ ├── v1/ # Only the "presentation" layer exists here. │ │ │ ├── __init__.py │ │ │ ├── serializers.py │ │ │ ├── urls.py │ │ │ └── views.py -│ │ ├── v2 # Only the "presentation" layer exists here. +│ │ ├── v2 # Only the "presentation" layer exists here. │ │ │ ├── __init__.py │ │ │ ├── serializers.py │ │ │ ├── urls.py │ │ │ └── views.py │ │ └── __init__.py -│ ├── fixtures # Constant "seeders" to populate your database -│ ├── management -│ │ ├── commands # Try and write some database seeders here +│ ├── fixtures/ # Constant "seeders" to populate your database +│ ├── management/ +│ │ ├── commands/ # Try and write some database seeders here │ │ │ └── command.py │ │ └── __init__.py -│ ├── migrations +│ ├── migrations/ │ │ └── __init__.py -│ ├── templates # App-specific templates go here -│ ├── tests # All your integration and unit tests for an app go here. +│ ├── templates/ # App-specific templates go here +│ ├── tests/ # All your integration and unit tests for an app go here. +│ ├── __init__.py │ ├── admin.py │ ├── apps.py -│ ├── __init__.py │ ├── models.py -│ ├── services.py # Your business logic and data abstractions go here. +│ ├── services.py # Your business logic and data abstractions go here. │ ├── urls.py │ └── views.py -├── common # An optional folder containing common "stuff" for the entire project -├── config -│ ├── settings.py -│ ├── asgi.py +├── common/ # An optional folder containing common "stuff" for the entire project +├── config/ │ ├── __init__.py +│ ├── asgi.py +│ ├── settings.py │ ├── urls.py │ └── wsgi.py -├── deployments # Isolate Dockerfiles and docker-compose files here. -├── docs +├── deployments/ # Isolate Dockerfiles and docker-compose files here. +├── docs/ │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── deployment.md │ ├── local-development.md │ └── swagger.yaml -├── requirements -│ ├── 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 +├── requirements/ +│ ├── 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. +├── .gitignore # https://github.com/github/gitignore/blob/main/Python.gitignore +├── entrypoint.sh # Any bootstrapping necessary for your application ├── manage.py ├── pytest.ini └── README.md @@ -103,7 +124,7 @@ into any other project and it’ll work independently. * 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. +* An app can be a django template project, or a rest framework API. ### `services` * We’ll be writing business logic in services instead of anywhere else. @@ -148,7 +169,8 @@ endpoints to ensure full compatibility. #### What's `v2` of an API? -Currently we're proposing that major changes to the following, constitutes a new API version: +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 @@ -173,6 +195,17 @@ you can check out the Django Rest Framework documentation at: https://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-handling +## FAQ +> Why not just make a cookiecutter out of this? + +Honestly, GitHub templates are so much easier. It's a one-click solution and +you're good to go. If we want to turn this into a cookiecutter, we'd have to also +start deciding sensible defaults, for instance, sentry, DRF version, formatters, +linters, etc. And that's something better left to the developer. Although, I am +playing around with the idea of having a cookiecutter with those sensible +defaults, but let's hope we have time to work on it on the `cookiecutter` branch. + + ## References - [Two Scoops of Django by Daniel and Audrey Feldroy](https://www.feldroy.com/books/two-scoops-of-django-3-x) - [Django Best Practices](https://django-best-practices.readthedocs.io/en/latest/index.html) @@ -181,3 +214,4 @@ https://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-han - [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/) - [Tuxedo Style Guides](https://github.com/saqibur/tuxedo) +- [Django Anti Patterns](https://www.django-antipatterns.com/)