César D. Velandia

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

Sources

  1. Effective Django