If you dont have a python env setup yet, follow the instructions in python_env.md
.
Once your python env is setup:
pip install Django==1.8.2
django-admin.py startproject <name>
This creates the following file structure
new_django
├── manage.py
└── new_django
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
Run python manage.py runserver
. You should see
Starting development server at http://127.0.0.1:8000/.
The dev, production or staging env differ from each other. Mainly they differ in 2 aspects
- required packages (production might need a different web server)
- settings (db connections, external services API keys)
Required packages
pip
can install packages from a requirements.txt
.
Create requirements.txt
in the root directory (new_django... the outer one) and add Django to it
Django==1.8.2
pip install -r requirements.txt
will verify and install all the dependencies.
Now that we have a requirements.txt
we need to split it up so we can have requirements for each envirnoment
$ mkdir requirements
$ touch requirements/{development.txt,production.txt}
$ mv requirements.txt requirements/base.txt
Let ".txt" files inherit from "base.txt"
$ cd requirements
$ echo "-r base.txt" | tee -a development.txt production.txt
$ cd ..
Now you can add env specific requirement into their respective files and run pip
$ pip install -r requirements/development.txt
Your directory structure after this step will look like:
new_django
├── manage.py
├── new_django
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── requirements
├── base.txt
├── development.txt
├── production.txt
Settings
Time to split up the settings.py
.
$ mkdir new_django/settings
This folder will contain:
__init__.py
file to make this folder a Python packagebase.py
will contain all the settings that are common in all environments. The other setting files inherit from this one.development.py
is for local development.production.py
will be used in the production environment. Let’s create these files, all inside thenew_django/settings
folder:
$ cd new_django/settings
$ touch __init__.py development.py production.py
And edit each of them to make them inherit from the base.py
file:
# -*- coding: utf-8 -*-
from .base import *
And finally, we have to move and rename the settings.py
file created by Django, to be our base.py
file inside the settings folder. Working inside the settings folder, you have to type:
$ mv ../settings.py base.py
The folder structure after this step should be:
new_django
├── manage.py
├── new_django
│ ├── __init__.py
│ ├── settings
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── development.py
│ │ ├── production.py
│ ├── urls.py
│ └── wsgi.py
└── requirements
├── base.txt
├── development.txt
├── production.txt
Since we have moved the default setting module, we need to tell django where to find the new setting module through a ENV variable DJANGO_SETTINGS_MODULE
. We can set this in the virtual env that we have created. We need to create a virtual env for each django env we want to support. In this example one for development (already present) and one for production.
With virtualenvwrapper, there is a way to configure different hooks that are sourced before or after activating the virtual environment, and before or after deactivating it. This means that we can define a set of statements that will be run at different stages of the virtual environment lifecycle. These hooks are saved inside the bin folder inside the virtual environment folder, and their names are preactivate, postactivate, predeactivate and postdeactivate.
In our case, we will set a postactivate script that will set the DJANGO_SETTINGS_MODULE
variable just after activating the virtual environment, and a predeactivate that will clean it up before deactivating it. Assuming you have already created the dev virtual env (else run mkvirtualenv new_django_dev
)
$ workon new_django_dev
$ cd $VIRTUAL_ENV/bin
The last command will take you to the virtual environment folder, where the different hooks reside. Edit the postactivate file by adding:
export DJANGO_SETTINGS_MODULE="new_django.settings.development"
and edit the predeactivate file by adding:
unset DJANGO_SETTINGS_MODULE
Do the same with the production environment, with the only change:
export DJANGO_SETTINGS_MODULE="taskbuster.settings.production"
It’s time to check! Go back to the root folder and activate your development environment. Next, run:
python manage.py runserver
and in the output displayed you should see a line indicating that you are using the new_django.development
settings file, something like:
Django version 1.8, using settings 'new_django.settings.development'
Now that we have different virtual env working, we can move the config DEBUG
from base.py
. DEBUG
must be set to Flase
in production
. Add DEBUG = True
in development.py
and DEBUG = False
in production.py
. Remove DEBUG = True
from base.py
.
If you open the file new_django/settings/base.py
you will see a variable named SECRET_KEY
. This variable should be kept secret, and therefore out of version control.
One option would be to add the base.py file into the .gitignore file, that is, remove it from the version control. However, during project development this file suffers many changes, and it’s quite useful to have it in version control, specially if you want to share it with your coworkers. Therefore, a better approach is to remove the secret key variable and import it from somewhere else. And this somewhere else is the one that should remain out of version control.
The approach we will follow here is to put the secret key inside our virtual environment configuration, and get the key from the environment by importing it in the base.py file.
To include the secret key inside the virtual environment we will also work with the virtualenvwrapper’s postactivate and a predeactivate hooks.
Activate your new_django_dev
environment and go to its bin folder using the shortcut
$ cd $VIRTUAL_ENV/bin
If you type ls you will see that it contains the files we just described. Edit the postactivate file and add the secret key line
export SECRET_KEY="your_secret_django_key"
Note: don’t put any spaces around the = sign. Next edit the predeactivate file and add the line:
unset SECRET_KEY
This way, if you type:
$ workon new_django_dev
$ echo $SECRET_KEY
your_secret_django_key
$ deactivate
$ echo $SECRET_KEY
-
Where the last line indicates that there is no output. This means that the variable SECRET_KEY is only visible when working in this virtual environment, as we wanted.
Repeat the same process for the new_django_production
virtual environment.
And finally, edit the base.py file, remove the SECRET_KEY and add the following lines:
from django.core.exceptions import ImproperlyConfigured
def get_env_variable(var_name):
try:
return os.environ[var_name]
except KeyError:
error_msg = "Set the %s environment variable" % var_name
raise ImproperlyConfigured(error_msg)
SECRET_KEY = get_env_variable('SECRET_KEY')
The function get_env_variable
tries to get the variable var_name
from the environment, and if it doesn’t find it, it raises an ImproperlyConfigured error. This way, when you try to run your app and the SECRET_KEY variable is not found, we will be able to see a message indicating why our project fails.
Let’s check that it all works as expected. Save the base.py, deactivate both environments and activate them again, in different terminal tabs.
Run the development server in the new_django_dev
environment
$ python manage.py runserver
Follow instructions here: http://www.marinamele.com/taskbuster-django-tutorial/install-and-configure-posgresql-for-django