From Code Self Study Wiki
Jump to: navigation, search

These are notes about Django.

Django Resources

To Research


To research:


To research:

Create a New Project

Don't forget Virtualenv. startproject mysite

Sample layout from Two Scoops of Django book:


The Server

Start the server with: $ python runserver


Edit mysite/

Two Scoops of Django book recommends a settings directory instead of just a file:


The file could alternatively be named

Database Choice


  • engine
  • name
  • user
  • password
  • host

See this page.

PostgreSQL and MySQL require you to create the database first. SQLite doesn't require you to create the database first.


Set this to the correct timeone. E.g., America/Los_Angeles.


Run python syncdb to setup the database with the default apps.

Create models in your new app: python startapp polls

Add the new app to the file:

    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',

Check what tables will be created with python sql polls. Check for errors with python validate. Create the tables with python syncdb. Play with the modules in the shell with python shell and:

>>> from polls.models import Poll, Choice # or whatever models were created


In Django 1.7+, sites aren't enabled by default. The docs have instructions.

Static Files

During development, Django's server will handle the static files.

Create a static directory in your app directory. Files will be located at places like polls/static/polls/style.css and accessible in the browser at /polls/style.css.

Then load it in the polls/templates/index.html template:

{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}" />

The file can be given information:

# The URL path where Django will serve the files from.
# This is only for the URL -- the directory doesn't have to exist.
STATIC_URL = '/static/'
# This lists places where Django will look outside of apps for static files to collect
    os.path.join(BASE_DIR, "static_src"),
# This is where the auto-generated static files will be kept
STATIC_ROOT = os.path.join(BASE_DIR, "static_output")

More info:

For minification, see Django-Pipeline.


This is the sample model from the Django docs:[1][2]

from django.db import models
class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    # this custom function keeps track of whether a poll is recent or not
    def was_published_recently(self):
        return self.pub_date >= - datetime.timedelta(days=1)
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently?'
    # add a function like this to each model
    def __unicode__(self):
        return self.question
class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    # add a function like this to each model
    def __unicode__(self):
        return self.choice_text

Model Examples



Django Migrations

New versions of Django (1.7+) have built in migrations. Three useful commands are:

  • ./ makemigrations <app_name> -- creates a migration file
  • ./ migrate -- applies migrations
  • ./ sqlmigrate <app_name> <migration_name> -- shows the SQL that will be executed (docs)

See the docs on how to upgrade from South.


For Django 1.6 and earlier use South:

Install South:

$ pip install south

For new projects, add south to installed apps and install the db table:

$ ./ syncdb

Initial command to create first migration file:

$ ./ schemamigration myapp --initial

Then migrate it:

$ ./ migrate myapp

Now, when you change the model, you create the migration file and run the migration like this:

$ ./ schemamigration myapp --auto $ ./ migrate myapp

Convert to south:

$ ./ convert_to_south myapp

Admin Dashboard


Enable the Dashboard

To activate the admin dashboard:

  1. Edit and uncomment django.contrib.admin.
  2. Create database tables with python syncdb.
  3. Edit the file and uncomment the three lines for admin URLs.

Admin will now be found at localhost:8000/admin/.

Add an App to the Dashboard

  1. Create an file in the directory of your app.
  2. Add this to the file, assuming that the model is "Poll":
from django.contrib import admin
from polls.models import Poll

Reorder the fields on the polls, e.g., to put the date field above the question field, like this:

from django.contrib import admin
from polls.models import Poll
class PollAdmin(admin.ModelAdmin):
    fields = ['pub_date', 'question'], PollAdmin)

Add fieldsets:

from django.contrib import admin
from polls.models import Poll
class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), # An automatic class for collapsing fieldsets by default
    ], PollAdmin)

There are two ways to add the choices. First, like the polls:

from polls.models import Choice

Better way to add the choices:

from django.contrib import admin
from polls.models import Choice, Poll
# You can either have them stacked or inline -- choose one or the other
# class ChoiceInline(admin.TabularInline):
class ChoiceInline(admin.StackedInline):
    model = Choice
    extra = 3 # by default, have input fields for three choices
class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    inlines = [ChoiceInline]
    # adds a way to filter the list by pub_date
    list_filter = ['pub_date']
    # adds search
    search_fields = ['question']
    # drill down functionality
    date_hierarchy = 'pub_date'
    # The following line adds more fields to the admin list display. There is one custom method: was_published_recently.
    list_display = ('question', 'pub_date', 'was_published_recently'), PollAdmin)


Note: for alternatives, check out Mako Templates and Jinja (via Coffin?).

Template Naming

There is an interesting naming convention here. Basically, all templates are put into one of three categories:

  1. Extendable templates -- anything that gets extended with {% extends %}. Prefix these templates with double underscores. This can also include some layout templates like __l_single_col.html, __l_right_sidebar.html. You can put them in a layouts directory if there are many of them.
  2. Includable templates -- anything that gets included with {% include %}. Prefix each includable template name with a single underscore.
  3. Page templates -- these are the ones that get called by views.

His example for __base.html is:

{% load staticfiles i18n %}
<!DOCTYPE html>
        {% block meta_tags %}{% endblock %}
            {% block title %}{% trans "Django Gazette" %}{% endblock %}
        {% block stylesheets %}
            <link rel="stylesheet" href="{% static "gazette/bootstrap/css/bootstrap.min.css" %}" type="text/css" />
            <link rel="stylesheet" href="{% static "gazette/css/base.css" %}" type="text/css" />
        {% endblock %}
        {% block javascript %}
            <script src="{% static "gazette/js/jquery-1.7.2.min.js" %}" type="text/javascript"></script>
            <script src="{% static "gazette/bootstrap/js/bootstrap.min.js" %}" type="text/javascript"></script>
        {% endblock %}
        {% block extra_head %}{% endblock %}
        <header class="navbar navbar-fixed-top">
            {% include "gazette/_navigation.html" %}
        <div id="main" role="main">
            <div class="container">
                {% block content %}
                {% endblock %}

His example for __l_right_sidebar.html is:

{% extends "gazette/__base.html" %}
{% block content %}
    <div class="row">
        <div class="span8">
            {% block main_col %}{% endblock %}
        <div class="span4">
            {% block side_col %}{% endblock %}
{% endblock %}

Then an article_detail.html page template might look like this:

{% extends "gazette/__l_right_sidebar.html" %}
{% block title %}{{ article.title }} | {{ block.super }}{% endblock %}
{% block main_col %}
    {% include "gazette/_article_full.html" %}
{% endblock %}
{% block side_col %}
    {% include "gazette/_tag_list.html" with tags=article.tags.all %}
    {% include "gazette/_category_list.html" with categories=article.categories.all %}
{% endblock %}

Add the location of your templates directory to


Admin Templates

Find the location of the Django files:

python -c "
import sys
sys.path = sys.path[1:]
import django

Alternatively, start the Django shell and find the location with:

from django.contrib import admin

Copy django/contrib/admin/templates/admin/base_site.html and .../index.html to your templates/admin directory. You can override any admin template this way.

General Templating

Put a template at polls/templates/polls/index.html. See also the docs.

The example below is from the Django tutorial. The polls:detail comes from the namespacing in mysite/ You can change the URLs sitewide from that URLs file, instead of hardcoding them in the templates.

{% if latest_poll_list %}
    {% for poll in latest_poll_list %}
        <li><a href="{% url 'polls:detail' %}">{{ poll.question }}</a></li>
    {% endfor %}
{% else %}
    <p>No polls are available.</p>
{% endif %}

Put this in the view:

from django.http import HttpResponse
from django.template import Context, loader
from polls.models import Poll
def index(request):
    latest_poll_list = Poll.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = Context({
        'latest_poll_list': latest_poll_list,
    return HttpResponse(template.render(context))

The tutorial also mentions using render as a shortcut:

from django.shortcuts import render
from polls.models import Poll
def index(request):
    latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
    context = {'latest_poll_list': latest_poll_list}
    return render(request, 'polls/index.html', context)

Using either of the above methods, the index template should render now.

Including Templates

You can include templates, like a widget in a sidebar. This one passes a variable to the other template:

{% include "featured_items.html" with items=1 %}

Template Tags and Filters

For custom filters:

  1. Create a templatetags directory within the templates directory.
  2. Create a filter file (like
from django import template
register = template.Library()
def redact_it(input_string, to_redact):
    to_redact_length = len(to_redact)
    num_of_xs = to_redact_length * "X"
    return input_string.replace(to_redact, num_of_xs)

Then load the custom filter and use it:

{% load redact %}
{{ greeting | redact_it:"some text" }}

Looping Over Dicts

If you have a dictionary like this:

deck = {
    'Hearts': ['A', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K'],
    'Clubs': ['A', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K'],
    'Spades': ['A', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K'],
    'Diamonds': ['A', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K']

You can loop over it like this:

{% for suit, cards in deck.iteritems %}
<li>{{ suit }}
        {% for card in cards %}
        <li>{{ card }} of {{ suit }}</li>
        {% endfor %}
{% endfor %}


Three steps:

Add some code to polls/

from django.http import HttpResponse
def index(request):
    return HttpResponse("This is the poll index.")
def detail(request, poll_id):
    return HttpResponse("This is poll %s." % poll_id)
def results(request, poll_id):
    return HttpResponse("This is the results page for poll %s." % poll_id)
def vote(request, poll_id):
    return HttpResponse("This is the voting page for poll %s." % poll_id)

Create polls/ and add some paths:

from django.conf.urls import patterns, url
from polls import views
urlpatterns = patterns('',
    # /polls/
    url(r'^$', views.index, name='index'),
    # /polls/1/
    url(r'^(?P<poll_id>\d+)/$', views.detail, name='detail'),
    # /polls/1/results/
    url(r'^(?P<poll_id>\d+)/results/$', views.results, name='results'),
    # /polls/1/vote/
    url(r'^(?P<poll_id>\d+)/vote/$',, name='vote'),

Then the mysite/ needs to know about the new URL rules:

urlpatterns = patterns('',
    url(r'^polls/', include('polls.urls', namespace="polls")), # namespace the apps
    url(r'^admin/', include(,

Connecting Views to Models

Put this in the polls view:

from django.http import HttpResponse
from polls.models import Poll
def index(request):
    # get the last 5 polls
    latest_poll_list = Poll.objects.order_by('-pub_date')[:5]
    output = ', '.join([p.question for p in latest_poll_list])
    return HttpResponse(output)

Still needs a template at polls/templates. See the template section.

HTTP Errors

404 Errors

Put a 404.html file in the root of the templates directory.

See these shortcuts:

# be sure to import the shortcut
from django.shortcuts import render, get_object_or_404
# ...
def detail(request, poll_id):
    poll = get_object_or_404(Poll, pk=poll_id)
    return render(request, 'polls/detail.html', {'poll': poll})

500 Errors

Put a 500.html file in the root of the templates directory if you want a custom error page.

Class-Based Generic Views

There are also generic views available, like ListView and DetailView.

An alternate way to do it would be to put this in polls/

from django.conf.urls import patterns, url
from django.views.generic import DetailView, ListView
from polls.models import Poll
urlpatterns = patterns('',
    url(r'^(?P<poll_id>\d+)/vote/$', '', name='vote'),

DetailView is going to look for a template at <app name>/<model name>_detail.html (e.g., polls/poll_detail.html) and ListView will look for <app name>/<model name>_list.html. The example above overrides the defaults.

Using the above example, polls/ can have the index, detail, and results functions deleted.

More on class-based views:


Block and redirect unauthenticated users on a view level:


Sample form from the Django tutorial. This goes in polls/details.html.

See also Crispy Forms and Django Bootstrap.

<h1>{{ poll.question }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' %}" method="post">
{% csrf_token %}
{% for choice in poll.choice_set.all %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ }}" />
    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />

It would then be handled something like this in polls/

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from polls.models import Choice, Poll
# ...
def vote(request, poll_id):
    p = get_object_or_404(Poll, pk=poll_id)
        selected_choice = p.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the poll voting form.
        return render(request, 'polls/detail.html', {
            'poll': p,
            'error_message': "You didn't select a choice.",
        selected_choice.votes += 1
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('polls:results', args=(,)))

Then in the view:

def results(request, poll_id):
    poll = get_object_or_404(Poll, pk=poll_id)
    return render(request, 'polls/results.html', {'poll': poll})

and the polls/results.html template:

<h1>{{ poll.question }}</h1>
{% for choice in poll.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
<a href="{% url 'polls:detail' %}">Vote again?</a>

Multiple Models in Django Form



Tests go in the file in the app. Example from the beginner tutorial:

import datetime
from django.utils import timezone
from django.test import TestCase
from polls.models import Poll
class PollMethodTests(TestCase):
    def test_was_published_recently_with_future_poll(self):
        was_published_recently() should return False for polls whose pub_date is in the future
        future_poll = Poll( + datetime.timedelta(days=30))
        self.assertEqual(future_poll.was_published_recently(), False)

See also Python Testing and these links:




You can make a directory called lib and put a file there. Then call it in your view like this:

from myapp.helpers import say_hi


Rails style scaffolding:

Django Channels

See Django Channels.

Building APIs

Django Rest Hooks

Django REST Framework

  • TODO

Tasty Pie

User Registration


Read about Website Security.

  • See the PASSWORD_HASHERS setting. It support bcrypt: pip install bcrypt.
  • CSRF tokens must be used for POST requests. It has to use the render method and not render_to_response.



See the Django deployment with Heroku page.


  1. Django Tutorial
  2. Django Models