Django
Activate an environment
Pre-install django in this env
conda create -n tutorial django=1.8
activate tutorial
mkdir tutorial
cd tutorial
Create requirements.txt
And install via pip (if needed):
touch requirements.txt
django==1.8 > requirements.txt
pip install -r requirements.txt
Init django
Create scaffold for django (note . to use current folder)
django-admin.py startproject addressbook .
C:.
│   manage.py
│   requirements.txt
│
└───addressbook
        settings.py
        urls.py
        wsgi.py
        __init__.py
Create next app inside project
Invoke manage function to create app structure
python manage.py startapp contacts
C:.
│   manage.py
│   requirements.txt
│
├───addressbook
│       settings.py
│       settings.pyc
│       urls.py
│       wsgi.py
│       __init__.py
│       __init__.pyc
│
└───contacts
    │   admin.py
    │   models.py
    │   tests.py
    │   views.py
    │   __init__.py
    │
    └───migrations
            __init__.py
Set up database details in addressbook/settings.py
Template varies between django 1.5 and 1.8. See docs
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'addresses.db'),
    }
}
Create a basic contact model
Modify contacts/models.py
from django.db import models
class Contact(models.Model):
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)
    email = models.EmailField()
    def __str__(self):
        return self.first_name + " " + self.last_name
And sync DB
python manage.py syncdb
This will create addresses.db in your root folder
Register contacts as installed app
Modify settings.py to match:
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'contacts',
)
Sync again
python manage.py syncdb
For Django 1.8 :
Migrations are required to apply changes to the database, such as creating tables:
python manage.py makemigrations
python manage.py migrate
Verify the model has been migrated using the shell with  python manage.py shell
>>> from models.contact import Contact
>>>	Contact.objects.create(first_name='cdv', last_name='cdv', email='cdv@cdv.com')
>>> Contact.objects.all()
<Contact: cdv cdv>
>>> Contact.objects.find(first_name__startswith='c')
<Contact: cdv cdv>
Queries return a QuerySet object (lazy loader) that allows function chanining
Write your tests
Modify the existing file contacts/tests.py to match:
from django.test import TestCase
from contacts.models import Contact
class ContactTests(TestCase):
    def test_str(self):
        c = Contact(first_name='Kevin', last_name='Bacon')
        self.assertEqual(str(c), 'Kevin Bacon')
Then run the test with
python manage.py test
Creating test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.017s
OK
Destroying test database for alias 'default'...
Create a ListView and Template, wire them
Modify contacts/views.py to match:
from django.views.generic import ListView
from contacts.models import Contact
class ContactListView(ListView):
    model = Contact
    template_name = 'contact_list.html'
Alter urls.py to look like:
from django.conf.urls import include, url
from django.contrib import admin
import contacts.views
urlpatterns = [
    url(r'^$', contacts.views.ContactListView.as_view(),
        name='contacts-list'),
    url(r'^admin/', include(admin.site.urls)),
]
Create a template at contacts\templates\contact_list.html
<h1>Contacts</h1>
<ul>
	{% for contact in object_list %}
		<li>{{ contact }}</li>
	{% endfor %}
</ul>
Test with
python manage.py runserver
Add a contact form
Modify views.py to match
from django.views.generic import ListView, CreateView
from django.core.urlresolvers import reverse
from contacts.models import Contact
class ContactListView(ListView):
    model = Contact
    template_name = 'contact_list.html'
class CreateContactView(CreateView):
    model = Contact
    fields = ['first_name', 'last_name', 'email']
    template_name = 'edit_contact.html'
    def get_success_url(self):
        return reverse('contacts-list')
Create templates\contact_list.html. The csrf (cross-site request forgery token) is part of the Django specification.
<h1>
	Add contact
</h1>
<form action="{% url 'contacts-new' %}" method="POST">
	{% csrf_token %}
	<ul>
		{{ form.as_ul }}
	</ul>
	<input type="submit" value="Save" />
</form>
Add it to the urls.py file
from django.conf.urls import include, url
from django.contrib import admin
import contacts.views
urlpatterns = [
    url(r'^$', contacts.views.ContactListView.as_view(),
        name='contacts-list'),
    url(r'^new$', contacts.views.CreateContactView.as_view(),
        name='contacts-new'),
    url(r'^admin/', include(admin.site.urls)),
]
Run again and browse to http://localhost:8000/new
python manage.py runserver