Django project skeleton
We at Haltu use Django in pretty much every web-related project, and therefore it is good to have common starting point for all projects. The use of CI systems, centralized error logging, deployment and maintenance are much easier if all projects conform to the same standards. But the biggest benefit is that this project skeleton makes development really easy.
This is a work in progress as we constantly fine-tune our way of working. Latest updates are always in the repository.
Features in this skeleton:
- Uses Buildout
- Separate Python eggs for each Django app
- Test runner for easy CI integration
- Setting files for development and production
- django-sentry for error reporting
- South for database migrations
- Additions to runserver command
You can get the skeleton project from Bitbucket. It has documentation which is little bit more comprehensive than this explanation.
Maintaining the project
The project bootstrapping, deployment and sandboxing is handled by Buildout.
There’s also bootstrap.py in the repo which can be used to install buildout locally in the project directory if you don’t want to install it system wide.
Buildout handles downloading and installing of all dependencies the project needs. Dependencies can be written in the buildout.cfg file, but Buildout is so clever that it collects the dependencies also from the apps we are developing. This makes it easy to develop self-containing apps even when they are in the same directory tree with the rest of the project.
Developing multiple apps
At first the coding begins in a single repo, just like the Django tutorials explain. The developer doesn’t need to pay any attention to the fact that all apps are also python eggs. When one of the apps reach a point that it is needed in another project, then that directory is split into a separate repository. Public releases are also easy as the egg machinery is there from the beginning.
Buildout makes it easy to switch between installing an egg from PyPi and using local source tree for the egg. When the egg is listed in the develop list in the buildout.cfg file the local copy of the source is used, otherwise it is searched from PyPi.
The directory tree looks like this:
├── doc
├── project
│ └── assets
│ ├── media
│ └── templates
└── src
├── foo
│ └── foo
└── runserver
The src directory contains the eggs. Directories src/foo and src/runserver have the setup.py file needed by all Python eggs. The foo app here is a placeholder, and a template, for your code.
Also the project directory is in the PYTHONPATH so it is possible to put views and other misc stuff in there if you need.
Django settings
Usually development and production environments are little different. Sometimes more. But always it is best to have separate configuration to these two environments. As django settings file is normal python source file it is easy to customize the way it is loaded.
This skeleton uses a three file system. There is project/settings.py which contains the basics and all common settings to other variants. Then files project/production.py and project/development.py start with a line from project.settings import *. After that line it is just matter of overriding the defaults.
Monitoring and error reporting
We use django-sentry for monitoring and error logging. In this skeleton it is configured as a client only to send exceptions and all log messages to separate sentry instance. You can change this behaviour in project/production.py settings file.
First boot
To actually use this skeleton you should rename the parts that are now called foo. Mainly these are the egg name django-foo and the Python module foo the egg contains.
These directories:
- src/foo
- src/foo/foo
And then these locations in the files:
- buildout.cfg:4: src/foo
- buildout.cfg:7: django-foo
- buildout.cfg:23:test = foo
- project/settings.py:64: ‘foo’,
- project/production.py:11: ‘NAME’: os.path.join(BASEDIR, ‘..’, ‘..’, ‘databases’, ‘foo.db’),
- src/foo/setup.py:5: name = “django-foo”,
- src/foo/setup.py:7: url = ‘http://example.com/django-foo’,
Starting the Django instance
Everything should magically just work if you run:
python bootstrap.py
bin/buildout
bin/django syncdb
bin/django runserver
In the syncdb phase it asks for the admin account. After that the development server should be running and you can log in to http://127.0.0.1:8000/admin