811 lines
27 KiB
HTML
811 lines
27 KiB
HTML
|
|
|||
|
<!doctype html>
|
|||
|
<html lang="en" class="no-js">
|
|||
|
<head>
|
|||
|
|
|||
|
<meta charset="utf-8">
|
|||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|||
|
|
|||
|
<meta name="description" content="This is a template/project structure for developing django-based applications - either strictly through the django-rest-framework or just django.">
|
|||
|
|
|||
|
|
|||
|
<meta name="author" content="Saqibur Rahman">
|
|||
|
|
|||
|
|
|||
|
<link rel="canonical" href="https://github.com/saqibur/django-project-structure/">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<link rel="icon" href="assets/images/favicon.png">
|
|||
|
<meta name="generator" content="mkdocs-1.5.3, mkdocs-material-9.4.12">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<title>Django Project Structure</title>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<link rel="stylesheet" href="assets/stylesheets/main.fad675c6.min.css">
|
|||
|
|
|||
|
|
|||
|
<link rel="stylesheet" href="assets/stylesheets/palette.356b1318.min.css">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
|
|||
|
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<script>__md_scope=new URL(".",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</head>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<body dir="ltr" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="indigo">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
|||
|
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
|||
|
<label class="md-overlay" for="__drawer"></label>
|
|||
|
<div data-md-component="skip">
|
|||
|
|
|||
|
|
|||
|
<a href="#django-project-structure" class="md-skip">
|
|||
|
Skip to content
|
|||
|
</a>
|
|||
|
|
|||
|
</div>
|
|||
|
<div data-md-component="announce">
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<header class="md-header md-header--shadow" data-md-component="header">
|
|||
|
<nav class="md-header__inner md-grid" aria-label="Header">
|
|||
|
<a href="." title="Django Project Structure" class="md-header__button md-logo" aria-label="Django Project Structure" data-md-component="logo">
|
|||
|
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
|
|||
|
|
|||
|
</a>
|
|||
|
<label class="md-header__button md-icon" for="__drawer">
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
|
|||
|
</label>
|
|||
|
<div class="md-header__title" data-md-component="header-title">
|
|||
|
<div class="md-header__ellipsis">
|
|||
|
<div class="md-header__topic">
|
|||
|
<span class="md-ellipsis">
|
|||
|
Django Project Structure
|
|||
|
</span>
|
|||
|
</div>
|
|||
|
<div class="md-header__topic" data-md-component="header-topic">
|
|||
|
<span class="md-ellipsis">
|
|||
|
|
|||
|
Home
|
|||
|
|
|||
|
</span>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<label class="md-header__button md-icon" for="__search">
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
|
|||
|
</label>
|
|||
|
<div class="md-search" data-md-component="search" role="dialog">
|
|||
|
<label class="md-search__overlay" for="__search"></label>
|
|||
|
<div class="md-search__inner" role="search">
|
|||
|
<form class="md-search__form" name="search">
|
|||
|
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
|
|||
|
<label class="md-search__icon md-icon" for="__search">
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
|
|||
|
</label>
|
|||
|
<nav class="md-search__options" aria-label="Search">
|
|||
|
|
|||
|
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
|
|||
|
</button>
|
|||
|
</nav>
|
|||
|
|
|||
|
</form>
|
|||
|
<div class="md-search__output">
|
|||
|
<div class="md-search__scrollwrap" data-md-scrollfix>
|
|||
|
<div class="md-search-result" data-md-component="search-result">
|
|||
|
<div class="md-search-result__meta">
|
|||
|
Initializing search
|
|||
|
</div>
|
|||
|
<ol class="md-search-result__list" role="presentation"></ol>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
<div class="md-header__source">
|
|||
|
<a href="https://github.com/saqibur/django-project-structure" title="Go to repository" class="md-source" data-md-component="source">
|
|||
|
<div class="md-source__icon md-icon">
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
|
|||
|
</div>
|
|||
|
<div class="md-source__repository">
|
|||
|
saqibur/django-project-structure
|
|||
|
</div>
|
|||
|
</a>
|
|||
|
</div>
|
|||
|
|
|||
|
</nav>
|
|||
|
|
|||
|
</header>
|
|||
|
|
|||
|
<div class="md-container" data-md-component="container">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<main class="md-main" data-md-component="main">
|
|||
|
<div class="md-main__inner md-grid">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
|||
|
<div class="md-sidebar__scrollwrap">
|
|||
|
<div class="md-sidebar__inner">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
|
|||
|
<label class="md-nav__title" for="__drawer">
|
|||
|
<a href="." title="Django Project Structure" class="md-nav__button md-logo" aria-label="Django Project Structure" data-md-component="logo">
|
|||
|
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
|
|||
|
|
|||
|
</a>
|
|||
|
Django Project Structure
|
|||
|
</label>
|
|||
|
|
|||
|
<div class="md-nav__source">
|
|||
|
<a href="https://github.com/saqibur/django-project-structure" title="Go to repository" class="md-source" data-md-component="source">
|
|||
|
<div class="md-source__icon md-icon">
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
|
|||
|
</div>
|
|||
|
<div class="md-source__repository">
|
|||
|
saqibur/django-project-structure
|
|||
|
</div>
|
|||
|
</a>
|
|||
|
</div>
|
|||
|
|
|||
|
<ul class="md-nav__list" data-md-scrollfix>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<li class="md-nav__item md-nav__item--active">
|
|||
|
|
|||
|
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<label class="md-nav__link md-nav__link--active" for="__toc">
|
|||
|
|
|||
|
|
|||
|
<span class="md-ellipsis">
|
|||
|
Home
|
|||
|
</span>
|
|||
|
|
|||
|
|
|||
|
<span class="md-nav__icon md-icon"></span>
|
|||
|
</label>
|
|||
|
|
|||
|
<a href="." class="md-nav__link md-nav__link--active">
|
|||
|
|
|||
|
|
|||
|
<span class="md-ellipsis">
|
|||
|
Home
|
|||
|
</span>
|
|||
|
|
|||
|
|
|||
|
</a>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<label class="md-nav__title" for="__toc">
|
|||
|
<span class="md-nav__icon md-icon"></span>
|
|||
|
Table of contents
|
|||
|
</label>
|
|||
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#getting-started" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
Getting Started
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
<nav class="md-nav" aria-label="Getting Started">
|
|||
|
<ul class="md-nav__list">
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#creating-an-app" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
Creating an App
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</nav>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#project-tree" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
Project Tree
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#rationale" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
Rationale
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
<nav class="md-nav" aria-label="Rationale">
|
|||
|
<ul class="md-nav__list">
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#apps-folder" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
apps Folder
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#services" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
services
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#api-folder" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
api Folder
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
<nav class="md-nav" aria-label="api Folder">
|
|||
|
<ul class="md-nav__list">
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#api-versioning" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
API Versioning
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#whats-v2-of-an-api" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
What's v2 of an API?
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</nav>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#config" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
config
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#deployments" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
deployments
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#exception-handling" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
Exception handling
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</nav>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#references" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
References
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
|
|||
|
</nav>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</ul>
|
|||
|
</nav>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
|
|||
|
<div class="md-sidebar__scrollwrap">
|
|||
|
<div class="md-sidebar__inner">
|
|||
|
|
|||
|
|
|||
|
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<label class="md-nav__title" for="__toc">
|
|||
|
<span class="md-nav__icon md-icon"></span>
|
|||
|
Table of contents
|
|||
|
</label>
|
|||
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#getting-started" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
Getting Started
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
<nav class="md-nav" aria-label="Getting Started">
|
|||
|
<ul class="md-nav__list">
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#creating-an-app" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
Creating an App
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</nav>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#project-tree" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
Project Tree
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#rationale" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
Rationale
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
<nav class="md-nav" aria-label="Rationale">
|
|||
|
<ul class="md-nav__list">
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#apps-folder" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
apps Folder
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#services" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
services
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#api-folder" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
api Folder
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
<nav class="md-nav" aria-label="api Folder">
|
|||
|
<ul class="md-nav__list">
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#api-versioning" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
API Versioning
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#whats-v2-of-an-api" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
What's v2 of an API?
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</nav>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#config" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
config
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#deployments" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
deployments
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#exception-handling" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
Exception handling
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</nav>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="md-nav__item">
|
|||
|
<a href="#references" class="md-nav__link">
|
|||
|
<span class="md-ellipsis">
|
|||
|
References
|
|||
|
</span>
|
|||
|
</a>
|
|||
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
|
|||
|
</nav>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="md-content" data-md-component="content">
|
|||
|
<article class="md-content__inner md-typeset">
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<p><a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg" /></a>
|
|||
|
<a href="https://www.python.org/downloads/release/python-3108//"><img alt="Python 3.10.8" src="https://img.shields.io/badge/python-3.10.8-blue.svg" /></a>
|
|||
|
<a href="https://github.com/astral-sh/ruff"><img alt="Ruff" src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" /></a></p>
|
|||
|
<p><img alt="Django" src="https://img.shields.io/badge/django-%23092E20.svg?style=for-the-badge&logo=django&logoColor=white" />
|
|||
|
<img alt="DjangoREST" src="https://img.shields.io/badge/DJANGO-REST-ff1709?style=for-the-badge&logo=django&logoColor=white&color=ff1709&labelColor=gray" />
|
|||
|
<img alt="Postgres" src="https://img.shields.io/badge/postgres-%23316192.svg?style=for-the-badge&logo=postgresql&logoColor=white" />
|
|||
|
<img alt="Swagger" src="https://img.shields.io/badge/-Swagger-%23Clojure?style=for-the-badge&logo=swagger&logoColor=white" /></p>
|
|||
|
<h1 id="django-project-structure">Django Project Structure</h1>
|
|||
|
<p>This is a template/project structure for developing django-based applications -
|
|||
|
either strictly through the <code>django-rest-framework</code> or just <code>django</code>.</p>
|
|||
|
<p>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”.</p>
|
|||
|
<h2 id="getting-started">Getting Started</h2>
|
|||
|
<ol>
|
|||
|
<li>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.</li>
|
|||
|
<li>Run the project using <code>python manage.py runserver</code> and you should see the
|
|||
|
default success page provided by Django at
|
|||
|
<a href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>.</li>
|
|||
|
</ol>
|
|||
|
<h3 id="creating-an-app">Creating an App</h3>
|
|||
|
<ol>
|
|||
|
<li>Create a folder with the app name in <code>apps</code>. For example: <code>poll</code></li>
|
|||
|
<li>Run <code>python manage.py startapp poll apps/poll</code> from the root directory of the
|
|||
|
project</li>
|
|||
|
</ol>
|
|||
|
<h2 id="project-tree">Project Tree</h2>
|
|||
|
<pre><code class="language-bash">.
|
|||
|
├── 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.
|
|||
|
│ │ │ ├── __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
|
|||
|
│ │ │ └── command.py
|
|||
|
│ │ └── __init__.py
|
|||
|
│ ├── migrations
|
|||
|
│ │ └── __init__.py
|
|||
|
│ ├── 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
|
|||
|
│ └── views.py
|
|||
|
├── common # An optional folder containing common "stuff" for the entire project
|
|||
|
├── config
|
|||
|
│ ├── settings.py
|
|||
|
│ ├── asgi.py
|
|||
|
│ ├── __init__.py
|
|||
|
│ ├── urls.py
|
|||
|
│ └── wsgi.py
|
|||
|
├── 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
|
|||
|
├── manage.py
|
|||
|
├── pytest.ini
|
|||
|
└── README.md
|
|||
|
</code></pre>
|
|||
|
<h2 id="rationale">Rationale</h2>
|
|||
|
<p>Each <code>app</code> should be designed in way to be plug-able, that is, dragged and dropped
|
|||
|
into any other project and it’ll work independently.</p>
|
|||
|
<h3 id="apps-folder"><code>apps</code> Folder</h3>
|
|||
|
<ul>
|
|||
|
<li>A mother-folder containing all apps for our project. Congruent to any
|
|||
|
JS-framework's <code>src</code> folder. If you really wanted to, you could even call it the
|
|||
|
<code>src</code> folder. Again, it's up to you.</li>
|
|||
|
<li>An app can be a django template project, or an rest framework API.</li>
|
|||
|
</ul>
|
|||
|
<h3 id="services"><code>services</code></h3>
|
|||
|
<ul>
|
|||
|
<li>We’ll be writing business logic in services instead of anywhere else.</li>
|
|||
|
<li>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.</li>
|
|||
|
</ul>
|
|||
|
<h3 id="api-folder"><code>api</code> Folder</h3>
|
|||
|
<ul>
|
|||
|
<li>We like to place all our API components into a package within an app called
|
|||
|
<code>api</code>. For example, in this repository it's the <code>example/api</code> 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. That's without getting
|
|||
|
into the mess of API versioning.</li>
|
|||
|
</ul>
|
|||
|
<p>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</p>
|
|||
|
<h4 id="api-versioning">API Versioning</h4>
|
|||
|
<p>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.</p>
|
|||
|
<p>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</p>
|
|||
|
<p><code>model</code>s and <code>service</code>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.</p>
|
|||
|
<p>Sufficient unit tests and integration tests should wrap services and API
|
|||
|
endpoints to ensure full compatibility.</p>
|
|||
|
<h4 id="whats-v2-of-an-api">What's <code>v2</code> of an API?</h4>
|
|||
|
<p>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</p>
|
|||
|
<h3 id="config"><code>config</code></h3>
|
|||
|
<ul>
|
|||
|
<li>Contains project configuration files, including the primary URL file</li>
|
|||
|
<li>~~Contains settings split into <code>base</code>, <code>local</code>, <code>production</code> and <code>development</code>.~~.
|
|||
|
Update: As environment specific variables will be handled using environment
|
|||
|
variables, we've deemed it unnecessary to have separate settings files for now.</li>
|
|||
|
</ul>
|
|||
|
<h3 id="deployments"><code>deployments</code></h3>
|
|||
|
<ul>
|
|||
|
<li>Contains Docker, Docker-Compose and nginx specific files for deploying in
|
|||
|
different environments.</li>
|
|||
|
</ul>
|
|||
|
<h3 id="exception-handling">Exception handling</h3>
|
|||
|
<p>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</p>
|
|||
|
<h2 id="references">References</h2>
|
|||
|
<ul>
|
|||
|
<li><a href="https://www.feldroy.com/books/two-scoops-of-django-3-x">Two Scoops of Django by Daniel and Audrey Feldroy</a></li>
|
|||
|
<li><a href="https://django-best-practices.readthedocs.io/en/latest/index.html">Django Best Practices</a></li>
|
|||
|
<li><a href="https://github.com/cookiecutter/cookiecutter-django">Cookiecutter Django</a></li>
|
|||
|
<li><a href="https://github.com/HackSoftware/Django-Styleguide">HackSoft Django Style Guide</a></li>
|
|||
|
<li><a href="https://www.youtube.com/watch?v=yG3ZdxBb1oo">Radoslav Georgiev - Django Structure for Scale and Longevity</a></li>
|
|||
|
<li><a href="https://apisyouwonthate.com/books/build-apis-you-wont-hate/">Build APIs You Won't Hate</a></li>
|
|||
|
<li><a href="https://github.com/saqibur/tuxedo">Tuxedo Style Guides</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</article>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
</main>
|
|||
|
|
|||
|
<footer class="md-footer">
|
|||
|
|
|||
|
<div class="md-footer-meta md-typeset">
|
|||
|
<div class="md-footer-meta__inner md-grid">
|
|||
|
<div class="md-copyright">
|
|||
|
|
|||
|
<div class="md-copyright__highlight">
|
|||
|
Copyright © 2022 - 2023 Saqibur Rahman
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
Made with
|
|||
|
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
|||
|
Material for MkDocs
|
|||
|
</a>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</footer>
|
|||
|
|
|||
|
</div>
|
|||
|
<div class="md-dialog" data-md-component="dialog">
|
|||
|
<div class="md-dialog__inner md-typeset"></div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
<script id="__config" type="application/json">{"base": ".", "features": [], "search": "assets/javascripts/workers/search.f886a092.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
|
|||
|
|
|||
|
|
|||
|
<script src="assets/javascripts/bundle.6c14ae12.min.js"></script>
|
|||
|
|
|||
|
|
|||
|
</body>
|
|||
|
</html>
|