generic django project
This is my starting point for a new Django site, mixed and stirred from several public sources and spiced with my own enhancements.
- server OS: Debian/Ubuntu based Linux
- local OS: MacOS X (only some local settings are OSX specific)
- web server: Nginx/gunicorn or Nginx/fcgi
- Python version: 2.7
- Django version: 1.6
- version control: Git
- deployment tool: Fabric
- local development database: SQLite3
- server database: MySQL or PostgreSQL
- database migration: South
- process control (optional): daemontools or supervisord
Django’s startproject doesn’t do enough. I’m a programmer, thus lazy, and try to reduce redundant work like repeating the same setup steps over and over. (DRY)
Just copying/cloning this generic project to a new site isn’t ideal either, since general changes don’t affect all dependent sites, but I got no idea how to do that.
I’m trying to keep this current and to implement what I learn from my actual projects and best practice advise. But since I mostly do other things than starting new django projects, I’m always far behind.
- Probably security holes - use at your own risk.
- I could also support runit, but I didn't want to replace init
- South still doesn't work for me, must overcome problems with several releases and multiple projects accessing the same Django app outside of virtualenvs
- Learn more from Two Scoops of Django, http://djangopatterns.com and https://github.com/callowayproject/django-app-skeleton
- Include Sphinx template and setup.py
- Optionally use Redis for sessions and cache, see http://unfoldthat.com/2011/09/14/try-redis-instead.html
- Make django-admin.py startproject --template=https://github.com/fiee/generic_django_project/zipball/master --extension=py,rst,html,txt,ini,sh MY_PROJECT work
- Finally learn testing
- Copy generic_django_project
- Rename "django_project" (this would be the project root as created by django-admin.py startproject)
- Replace all occurrences of lowercase "project_name" with your project name. This is also the webserver and database server username! The "project_name" directory is the one that would be created by manage.py startapp.
- Check the settings in manage.py, fabfile.py, gunicorn-settings.py, settings/base.py_, settings/local.py_ and supervisor.ini or service-run.sh
- Set up an email account for your project’s error messages and configure it in settings/base.py_
- If you use Nginx, change the internal port in nginx.conf (fastcgi_pass 127.0.0.1:8001;); I use "8 + last 3 numbers of UID" (UIDs start at 1000 on Debian): id -u project_name
- git init, always commit all changes
- manage syncdb (initialize south)
- fab webserver setup (once)
- fab webserver deploy (publish new release - always last committed version!)
Following 12-factor design, we now set our passwords and other secret settings as environment variables to avoid to have them in version control. I suggest to go the dotenv route:
Put your settings into a .env file in the django_project directory, to use with django-dotenv-rw. Don’t forget to tell git to ignore .env files!
Alternatively add the settings to the end of your virtualenvs activate script:
export DJANGO_SETTINGS_MODULE=project_name.settings export DATABASE_PASSWORD=secret123 export EMAIL_PASSWORD=secret123
Create your .env file at /var/www/project_name (or use virtualenvs’ activate script), see above.
I suggest to use makeuser.sh to create system and database accounts. Otherwise:
create user and sudo-enable it (I suggest via a group like wheel, but you can also add the user to sudoers):
adduser project_name adduser project_name wheel
create database user and database (schema)
mysql -u root -p # at first setup only: we installed MySQL without user interaction, so there’s no root password. Set it! use mysql; update user set password=password('...') where user='root'; # create user and database for our project: create user 'project_name'@'localhost' identified by '...'; create database project_name character set 'utf8'; grant all privileges on project_name.* to 'project_name'@'localhost'; flush privileges; quit;
If you use FeinCMS’ Page, consider first, which extensions you’ll need – see the docs and the FAQ – afterwards you would need to change the database table page_page by hand, since the changes aren’t detected by South!
Links / Sources
- "Two Scoops of Django"_
- Setup with Nginx: http://djangoadvent.com/1.2/deploying-django-site-using-fastcgi/
- Nginx configuration: http://wiki.nginx.org/NginxConfiguration
- Gunicorn configuration: http://gunicorn.org/configure.html
- logrotate: e.g. http://www.linux-praxis.de/lpic1/manpages/logrotate.html
- daemontools: http://cr.yp.to/daemontools.html
- supervisord: http://supervisord.org