Yet Another Django Cookiecutter Template
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
hooks
{{cookiecutter.repo_name}}
.gitignore
README.md
cookiecutter.json

README.md

Cookiecutter template for django projects

This is just another cookiecutter template for django projects, matching my job requirements. There are many out there which are great but I needed one following my consolidated workflow.

Running this you will have:

  • a development ready django project with all the packages installed and the database created and ready to go.
  • a bin command which will set up the remote machine for you (using ansible) and will display a maintenance page
  • some production commands to manage the deploy and related stuff.

Environment

Cookiecutter is uset to create a working directory already configured.

Ansible is used to set up the local and remote machines

Fabric is used to manage the deploy and other related tasks.

Local

  • mysql db
  • django development server

Remote

  • mysql db
  • nginx server
  • uwsgi

Features

Constraints

  • mysql everywhere and already installed in the local machine
  • environment variables for configuration

Python Packages

  • Django==2.1.7
  • django-getenv==1.3.1
  • MySQL-python==1.2.5
  • Fabric==1.12.0
  • Pillow==5.4.1
  • django-constance==2.3.1
  • django-ckeditor==5.6.1
  • django-treenav==1.2.0
  • django-cleanup==3.0.1
  • django-pipeline==1.6.14
  • django-simple-captcha==0.5.10
  • django-taggit==0.23.0
  • easy-thumbnails==2.5
  • ansible==2.2.0.0
  • python-dotenv==0.10.1

Optional:

  • django-disqus==0.5
  • django-filer==1.4.3
  • django-grappelli==2.12.2
  • django-suit==0.2.26
  • django-baton==1.3.2

Local dev

  • django-debug-toolbar==1.11

Production

  • uWSGI==2.0.17

Frontend

Vendor

jQuery as js framework, bootstrap as css framework, momentjs to deal with datetime objects.

  • jQuery 1.11.3
  • moment.js
  • bootstrap v4.2.1
  • FontAwesome 4.7.0

Getting started

Install cookiecutter

$ pip install cookiecutter

Run cookiecutter against this repo

$ cookiecutter https://github.com/abidibo/cookiecutter-django

Answer the following questions:

  • project_name: name of the project. Default "My New Project"
  • project_description: project description. Default "My New Project description"
  • repo_name: name of the repository. Default "[project_name | lower | replace(' ', '-')]"
  • core_name: name of the main application. Default "[repo_name | replace('-', '_')]"
  • admin: django admin app package. Possible values: django-baton, django-suit, django-grappelli, default. Default "django-baton"
  • use_filer: whether or not to install django-filer [y|n]. Default "n"
  • use_disqus: whether or not to install django-disqus [y|n]. Default "n"
  • language_code: language code. Default "en-us"
  • timezone: timezone. Default "Europe/Rome"
  • author: project author. Default "abidibo"
  • email: project author email. Default "abidibo@gmail.com"
  • remote_user: user for deployment to the production server. Default "[repo_name]"
  • domain: production domain. Default "www.example.com"
  • remote_root_mysql_pwd: password for the remote mysql root user. Default "". You can set it later inside the provisioning/playbooks/roles/database/templates/.my.cnf file
  • db_user: user for the remote database. Default "[remote_user]"
  • db_user_pwd: user password for the remote database. Default ""
  • webapp_dir: absolute path to the remote deploy directory

Then provide your sudo password in order to provision your local environment.

If all works great now you should have:

  • a new folder (I'll call it root) containing all your bootstrapped project
  • all the necessary packages installed
  • a fresh virtualenv with all the dependencies already installed (folder .virtualenv in the root)
  • a new database ready to go with, all migrations applied
  • a new git repository initialized
  • a README file explaining how to clone and get started with the project

Now:

$ cd [repo_name]
$ python [repo_name]/manage.py createsuperuser
$ bin/runserver

And visit http://localhost:8000

Notes

  • setup local environment manually
    maybe you don't want ansible to setup the local environment for you (for example if you are on a mac some commands will fail), so just interrupt the execution of cookiecutter (CTRL-C) when you're prompted for the sudo password. You can then check the provisioning files, change them and then launch bin/ansible_local manually

  • change the SECRET_KEY:

    $ dotenv set SECRET_KEY <secret_key_here>

    you can change the remote SECRET KEY adding a line

    SECRET_KEY='<value here>'

  • you can also not specify the remote params during the installation. You will have a working local environment ready to go. But in this case you'll have to set them manually to configure the remote setup script which uses ansible. In this case check the followinf files:

    • provisioning/ansible_remote_inventory
    • provisioning/ansible_remote_variables
    • [repo_name]/fabfile.py

Remote setup

Remote setup is done with ansible, using the root user. Run

$ bin/ansible_remote

and provide the root password when prompted.

If all goes well now you should have your remote machine ready for deploy. Visit your domain and you should see a maintenance page already there.

Troubleshooting

SSH connection error

If you see this error

fatal: [remote] => Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host.

means you missed adding an entry for one or more hosts in the ~/.ssh/known_hosts file, it's enough to try an ssh connection in order to add the domain to your list, then relauch bin/ansible_remote

DB task error

If an error occurs in the create db user task:

msg: (1396, "Operation CREATE USER failed for ...

maybe you're trying to create a user which already existed and was delete. In this case just run this sql in the mysql database:

FLUSH PRIVILEGES;

see this answer on stack overflow

Deploy and Stuff

In the deployment process, the last revision of the git repository is deployed to the remote server. So be sure to have committed all your changes:

$ git add --all
$ git commit -a -m "first commit"

Be sure the provided remote user has ssh access to the remote host, then deploy should be as easy as:

$ cd [repo_name]
$ fab production deploy

launched inside the root/repo_name folder. This command does the following things:

  • create an archive of the last repository revision
  • upload it to the server
  • untar it in a folder "app-revision_id" inside the releases folder
  • copy the .env file inside this folder
  • upgrade the virtualenv
  • collectstatic
  • migrations
  • move the current release in the previous release (releases/previous)
  • link the releases/current folder to the new release folder
  • restart uwsgi and reload nginx
  • open a shell in the remote

When performing the first deploy you can create a superuser account using the shell which the script leaves open at the end.

###Other useful fab commands

rollback

$ fab production rollback

If the deploy revision is broken, or introduces unexpected errors, with this command it is possible to rollback to the previous revision. Launching it another time will swap between the two revisions.

restart_uwsgi

$ fab production restart_uwsgi

Restarts the uwsgi service

reload_server

$ fab production reload_server

Reloads the web server

restart_server

$ fab production restart_server

Restarts the web server

restart

$ fab production restart

Restarts the uwsgi service and the web server

dump_db_snapshot

$ fab production dump_db_snapshot

Downloads the production current db snapshot in the backup folders. The dumped file has the remote current revision name.

Requires the remote db user password.

load_db_snapshot

$ fab production load_db_snapshot

Loads the current remote db snapshot in the local db.

Requires the remote db user password.