UPDATE 03/14: I've written a new post regarding project layout with Django >=1.5. You can read it here
I’m always trying to tidy up my project layout so that they are easy to maintain as well as recoverable (in the inevitable case that I accidentally delete something). There are plenty of articles on the web discussing different layouts for small to medium sized Django projects. I’ve learned a lot from those and I’d like to add my own 2c when it comes to deploying a new project.
The following is my general layout. The root folder
foo.com is generated via
django_root is the guts of my project:
Things To Note
- Most importantly - everything that is important is stored within
django_rootand therefore tucked away in version control (GitHub).
- Virtualenvwrapper: The root folder
foo.comis generated via
virtualenvwrapper, which makes switching projects sensible and easy via
- Project Root vs. Site Root & Git: My project root
django_rootis checked into Git, the site root isn’t: everything that is specific to your project should be under
django_root, everything that is generic to your site should be under
- Cloud Backup: I use Dropbox 100Gb so I keep the project root in Dropbox (under
./Drobox/Development/sites/foo.com) while keeping the actual site root outside of Dropbox (to save Dropbox space). I then symlink from one to the other. This gives an extra layer of protection from accidentally deleting everything (which I’ve previously done twice).
- Dedicated Application Subfolder: I use an
appsfolder within the project root to hold all my custom applications. I find this a cleaner than having them sit in the root of the project folder. For bigger projects, I split these apps into further subfolders (
- General (Non-Application-Specific) Files & Modules: I have a
commonfolder which is added to the python path and contains modules which don’t belong in an application;
sitemaps.py, general utility template tags, standalone utility modules, general context processors or middleware, error views etc.
- General Libraries: I use the
libsfolder to hold modules that aren’t django applications, arn’t particularly related to django (like in the
commonfolder) but are being used internally by one or more applications in some form. Ideally, any library you write should be wrapped up as a module in pypi so that it can be installed with pip, but this is a good alternative for small custom libraries.
- Server/Dev Configuration: The
conffolder holds all files related to the server configuration of the project. The files contained within are symlinked to the appropriate locations on the dev/production server. Having them here means you will always have them under source control (make sure not to include passwords)!
- Fixtures: The
fixturesfolder can be useful if there are certain sets of data you want to make sure you don’t lose. When developing, I am constantly wiping the test DB, so recreating specific fixtures is a pain. Use
dumpdataregularly. If you don’t care about the actual contents of your fixtures, you can use something like
django-dillato generate spam values quickly.
- Project Media: There are two
mediafolders; one in the site root that will be used by django when uploading files etc, and another in the project root; I use the one in the project root to hold media that I create during development
- Photoshop & General Resources: I usually check all photoshop files I use during development into Git as I will probably delete them or lose them them otherwise.
- Pip, Pip-Tools & Requirements File: Pip is great, but
pip-toolsis even better. It makes installing updating and dumping dependancies even easier. Dumping your requirements with vanilla pip is done via
pip freeze > requirements.txtand with
pip-dump > requirements.txt. This makes it very easy to move from one server to the other.
- Settings: I try to be as versbose as possible in the
default.pyholds settings relevant to the base django install,
custom.pyholds settings for all my installed apps - be them home made or modules installed via pip -,
database.pycontains connection settings and passwords, and isn’t checked into Git.
private.pyholds private keys, sentry DSNs etc. and also isn’t checked into Git. Then there are specific settings files for both production and development etc. These are called by the application server and import everything else.