Django project layout alternatives
Laying out and organizing a development project (Django or otherwise) is a task to which many people do not give much consideration, typically deferring to some default layout. This default layout is usually obtained in one of several ways:
- using Django's admin tool (django-admin.py startproject) to create a new project
- copying an old project and using it as the basis of the new project
- cloning a project found on GitHub or elsewhere and stripping it down to its bones
Most developers won't stop to think about the project layout and whether a different alternative may work better. Many don't even realize that there are different ways you can layout a Django project.
Unfortunately, laying out and organizing a Django project is a task best completed at the very start of the project. Although the layout can be changed once the project development has begun, refactoring to a different layout adds unnecessary time, risk and frustration to the development process. Whatever layout was chosen at the start of the project, the best approach is to stick with it.
Here are a few of the options for a starting Django project layout.
Django's out of the box layout
The following layout (accurate as of Django version 1.9.x) should be familiar as the default out-of-the-box layout created by Django's startproject
and startapp
management commands.
myproject
├── app1
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── app2
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── myproject
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── settings.py
│ ├── settings.pyc
│ ├── urls.py
│ └── wsgi.py
└── manage.py
As this layout should be familiar to Django developers I won't go into detail. The most important points to take away are that the source code for the project is placed immediately under to root directory of the project and that the generated boilerplate layout is very sparse. The Django out of the box project layout does not give you very much help in bootstrapping the project.
cookiecutter-django layout
The Django out of the box project layout is OK as a starting point, but it leaves out a lot of common configuration and setup, and is not very version control system friendly. Another approach to laying out a Django project is exemplified by cookiecutter-django. cookiecutter-django
is built on top of the cookiecutter project templating tool.
cookiecutter
is installed simply by using pip
:
pip install cookiecutter
Once cookiecutter
is installed you can go ahead and create a project:
cookiecutter https://github.com/pydanny/cookiecutter-django
Cloning into 'cookiecutter-django'...
remote: Counting objects: 5326, done.
remote: Compressing objects: 100% (42/42), done.
remote: Total 5326 (delta 17), reused 0 (delta 0), pack-reused 5284
Receiving objects: 100% (5326/5326), 962.92 KiB | 332.00 KiB/s, done.
Resolving deltas: 100% (3365/3365), done.
Checking connectivity... done.
project_name [project_name]: my-cookiecutter-django-project
repo_name [my-cookiecutter-django-project]:
author_name [Your Name]: Jody Boucher
email [Your email]: jody@sample.com
description [A short description of the project.]: cookiecutter-django sample
domain_name [example.com]:
version [0.1.0]:
timezone [UTC]:
now [2016/03/05]:
year [2016]:
use_whitenoise [y]:
use_celery [n]:
use_mailhog [n]:
use_sentry [n]:
use_newrelic [n]:
use_opbeat [n]:
windows [n]:
use_python2 [n]:
Select open_source_license:
1 - MIT
2 - BSD
3 - Not open source
Choose from 1, 2, 3 [1]: 1
Here is a sample project layout. The content of the actual project created will vary based on the answers provided to the questions.
my-cookiecutter-django-project
├── .coveragerc
├── .dockerignore
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .pylintrc
├── .travis.yml
├── CONTRIBUTORS.txt
├── Dockerfile
├── Dockerfile-dev
├── Gruntfile.js
├── LICENSE
├── Procfile
├── README.rst
├── app.json
├── compose
│ ├── django
│ │ ├── entrypoint.sh
│ │ └── gunicorn.sh
│ └── nginx
│ ├── Dockerfile
│ └── nginx.conf
├── config
│ ├── __init__.py
│ ├── settings
│ │ ├── __init__.py
│ │ ├── common.py
│ │ ├── local.py
│ │ └── production.py
│ ├── urls.py
│ └── wsgi.py
├── dev.yml
├── docker-compose.yml
├── docs
│ ├── Makefile
│ ├── __init__.py
│ ├── conf.py
│ ├── deploy.rst
│ ├── docker_ec2.rst
│ ├── index.rst
│ ├── install.rst
│ └── make.bat
├── env.example
├── install_os_dependencies.sh
├── install_python_dependencies.sh
├── manage.py
├── my-cookiecutter-django-project
│ ├── __init__.py
│ ├── contrib
│ │ ├── __init__.py
│ │ └── sites
│ │ ├── __init__.py
│ │ └── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_set_site_domain_and_name.py
│ │ └── __init__.py
│ ├── static
│ │ ├── css
│ │ │ └── project.css
│ │ ├── fonts
│ │ │ └── .gitkeep
│ │ ├── images
│ │ │ └── favicon.ico
│ │ ├── js
│ │ │ └── project.js
│ │ └── sass
│ │ └── project.scss
│ ├── templates
│ │ ├── 404.html
│ │ ├── 500.html
│ │ ├── account
│ │ │ ├── base.html
│ │ │ ├── email.html
│ │ │ ├── email_confirm.html
│ │ │ ├── email_confirmed.html
│ │ │ ├── login.html
│ │ │ ├── logout.html
│ │ │ ├── password_change.html
│ │ │ ├── password_reset.html
│ │ │ ├── password_reset_done.html
│ │ │ ├── password_reset_from_key.html
│ │ │ ├── password_reset_from_key_done.html
│ │ │ ├── password_set.html
│ │ │ ├── signup.html
│ │ │ ├── signup_closed.html
│ │ │ ├── verification_sent.html
│ │ │ └── verified_email_required.html
│ │ ├── base.html
│ │ ├── pages
│ │ │ ├── about.html
│ │ │ └── home.html
│ │ └── users
│ │ ├── user_detail.html
│ │ ├── user_form.html
│ │ └── user_list.html
│ └── users
│ ├── __init__.py
│ ├── adapters.py
│ ├── admin.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── models.py
│ ├── tests
│ │ ├── __init__.py
│ │ ├── factories.py
│ │ ├── test_admin.py
│ │ ├── test_models.py
│ │ └── test_views.py
│ ├── urls.py
│ └── views.py
├── package.json
├── pytest.ini
├── requirements
│ ├── base.txt
│ ├── local.txt
│ ├── production.txt
│ └── test.txt
├── requirements.apt
├── requirements.txt
├── runtime.txt
├── setup.cfg
└── tests
├── all.settings
├── base.yml
├── ci.settings
├── engine.py
├── hitchreqs.txt
├── register-and-log-in.test
├── system.packages
└── tdd.settings
WOW! It created a completely different layout, and quite a lot of files for an empty project. Don't let the volume of content created for this boilerplate project layout scare you. cookiecutter-django
incorporates a lot of bells and whistles into the boilerplate layout. Take your time to go through the files and understand what everything is and why it is there. If there is something you do not need or want you should remove it.
Here are a few notable points about the project layout created by cookiecutter-django
:
- The source code for the project is no longer directly in the root of the project directory - it is moved a level lower. This makes it a lot easier to manage the source code as well as any related project files in your version control system of choice.
- The root directory now contains a number of items that are needed for most projects - documentation, Django configuration, build scripts/configuration, tests, etc.
- The boilerplate includes a sensible starting point for the project's Django configuration.
- The boilerplate includes some helpful starter user and account management code.
Other alternatives
There are a number of other cookiecutter
project templates available. And you can always find other layouts by searching the web.
Recommendations
The cookiecutter-django
project template really is a great start for most projects. Fork it and customize it to your exact needs.