Django

A quick-as-I-can overview

Authors: Forest Bond
Adrian Holovaty
Jacob Kaplan-Moss
Date: 2007-07-17

License

The introduction portion of this presentation was largely plagiarised from The Django Book, which was written by Adrian Holovaty and Jacob Kaplan-Moss:

http://www.djangobook.com

The Django Book is licensed under the GNU Free Documentation License. As such this presentation may also be freely distributed by the same terms.

License (cont'd)

Copyright 2006 by Adrian Holovaty and Jacob Kaplan-Moss Copyright 2007 by Forest Bond

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.

The license may be obtained at the following URL:

http://www.gnu.org/licenses/fdl.txt

The Mission

"Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design."

A high-level Web framework is software that eases the pain of building dynamic Web sites. It abstracts common problems of Web development and provides shortcuts for frequent programming tasks.

...a high-level Python web framework...

The framework should address these common concerns:

...that encourages rapid development...

Regardless of how many powerful features it has, a Web framework is worthless if it doesn’t save you time.

Django's productivity is thanks largely to Python's own perks:

Django leverages the advantages provided by Python to speed up development of web applications.

...and clean, pragmatic design.

Above all, Django tries to:

The Not-so-clean Approach

<html>
<head><title>Friends of mine</title></head>
<body>
<h1>Friends of mine</h1>
<ul>
<?php
$connection = @mysql_connect("localhost", "my_username", "my_pass");
mysql_select_db("my_database");
$people = mysql_query("SELECT name, age FROM friends");
while ( $person = mysql_fetch_array($people, MYSQL_ASSOC) ) {
?>
<li>
<?php echo $person['name'] ?> is <?php echo $person['age'] ?> years old.
</li>
<?php } ?>
</ul>
</body>
</html>

The Not-so-clean Approach (cont'd)

What are the problems with this sort of approach?

But Django can help!

Framework Architecture

Django is a Model-View-Controller (MVC) framework, interpreted somewhat loosely.

The major components:

Remember, Django components are loosely coupled, so each piece can be used seperately or replaced with a third-party equivalent.

Framework Architecture: Core

The core provides:

Web applications built on Django must fit into this core framework to handle HTTP requests.

Projects and Applications

How are Django websites organized?

Application Structure

What's in an application?

django-admin.py

Django provides a simple command-line tool that, among other things, makes it easy to create project and application skeletons.

For instance, to begin a new project:

$ django-admin.py startproject example
$ cd example && ls
__init__.py  manage.py  settings.py  urls.py

manage.py

manage.py is a utility that is included with the default project skeleton.

Getting Started

Django makes it easy to get up-and-running with a built in development server.

(show the development server)

Views

What are views?

A Simple View

import random
from django.http import HttpResponse

def random_number(request):
    x = random.randint(0, 999)
    html = '<html><body><p>Your lucky number is: %u</p></body></html>' % x
    return HttpResponse(html)

URLconf's

A Simple URLconf

from django.conf.urls.defaults import *

urlpatterns = patterns('',
  (r'^random_number/$', 'randomness.views.random_number'),
)

How Do URLconf's work?

Django's URL dispatcher is responsible for reading the URLconf and doing something useful with it:

More On URLconf's

A few more things about URLconf's:

First Website Settings

settings.py:

ROOT_URLCONF = 'example1.urls'

For most Django websites, the settings file will be signficantly larger. This example, however, is so small that the only required setting is ROOT_URLCONF.

First Website Code

urls.py:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
  (r'^random_number/$', 'randomness.views.random_number'),
)

views.py:

import random
from django.http import HttpResponse

def random_number(request):
    x = random.randint(0, 999)
    html = '<html><body><p>Your lucky number is: %u</p></body></html>' % x
    return HttpResponse(html)

The Django ORM

In the Django world, models are the authoritative source of all information related to an application's database architecture and representation.

Models bring together:

More On Models

The model for models:

Some Simple Models

from django.db import models

class Author(models.Model):
    firstname = models.CharField(maxlength = 256)
    lastname = models.CharField(maxlength = 256)

class Book(models.Model):
    title = models.CharField(maxlength = 256)
    author = models.ForeignKey(Author)

Initializing the Database

The database is automatically initialized by running "manage.py syncdb":

(show off the Python shell)

Fleshing Out the Models

Author:

class Author(models.Model):
    firstname = models.CharField(maxlength = 256, blank = False)
    lastname = models.CharField(maxlength = 256, blank = False)

    class Meta:
        unique_together = (
          ('firstname', 'lastname'),
        )

    class Admin:
        pass

    def __str__(self):
        return '%s %s' % (self.firstname, self.lastname)

Fleshing Out the Models (cont'd)

Book:

class Book(models.Model):
    title = models.CharField(maxlength = 256, blank = False)
    author = models.ForeignKey(Author)

    class Meta:
        unique_together = (
          ('title', 'author'),
        )

    class Admin:
        pass

    def __str__(self):
        return '%s by %s' % (self.title, str(self.author))

What's That Admin Mumbo Jumbo?

Introducing ...

the Django Admin site!

Fine, Now Make The Freakin' Website Already!

Ok, we have models, now we just need some views, a URLconf, and some templates.

We will have to learn about templates real quick...

The Template System

The Django template engine is similar in some ways to a few others (e.g. Smarty):

A Simple Template

<html>
  <head><title>{{ book }}</title></head>
  <body>
    <h1>{{ book }}</h1>
    <p>This is one of my books:</p>
    <table>
      <tr><th>Title:</th><td>{{ book.title }}</td></tr>
      <tr><th>Author:</th><td>{{ book.author }}</td></tr>
    </table>
  </body>
</html>

How Templates Work

The basics of Django template rendering:

Finally, We're Ready

Now we can make our books site.

The Views

views.py:

from django.http import HttpResponse, Http404
from django.template import loader, Context

from mybooks.books import models

def book_list(request):
    books = models.Book.objects.all()
    c = Context({ 'books': books })
    t = loader.get_template('book_list.html')
    return HttpResponse(t.render(c))

def book_detail(request, id):
    try:
        book = models.Book.objects.get(id = id)
    except models.Book.DoesNotExist:
        raise Http404

    c = Context({ 'book': book })
    t = loader.get_template('book_detail.html')
    return HttpResponse(t.render(c))

The URLconf

urls.py:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
  (r'^books/$', 'mybooks.books.views.book_list'),
  (r'^books/(?P<id>[0-9]+)/$', 'mybooks.books.views.book_detail'),
  (r'^admin/', include('django.contrib.admin.urls')),
)

The Templates

base.html:

<html>
  <head>
    <title>{% block title %}Title{% endblock %}</title>
  </head>
  <body>{% block body %}Body{% endblock %}</body>
</html>

The Templates (cont'd)

book_list.html:

{% extends "base.html" %}
{% block title %}My Books{% endblock %}
{% block body %}
  {% if books %}
    <p>These are some books in my book collection:</p>
    <ul>
    {% for book in books %}
      <li><a href="{{ book.id }}">{{ book }}</a></li>
    {% endfor %}
    </ul>
  {% else %}
    <p>I don't have any books in my book collection!</p>
  {% endif %}
{% endblock %}

The Templates (cont'd)

book_detail.html:

{% extends "base.html" %}
{% block title %}{{ book }}{% endblock %}
{% block body %}
<p>This is one of my books:</p>
<table>
  <tr>
    <th>Title:</th>
    <td>{{ book.title }}</td>
  </tr>
  <tr>
    <th>Author:</th>
    <td>{{ book.author }}</td>
  </tr>
</table>
{% endblock %}

There's Only So Much Time

These were just the basics, upon which Django builds much more impressive features that really maximize your productivity:

The End