Django: Presented by Sam Stuck

Sam Stuck is an independant IT consultant who occasionally finds the time to program websites. His official presentation can be found here. Sam split the meeting into two sections, the presentation section and the demonstration section. Below are some brief notes from the meeting.

Overview

Django is a web framework for constructing dynamic websites. Hint: the “D” is silent. Back in the day, most websites were served with static HTML that had to be manually updated with each change. Today, most websites are dynamic and/or database driven, which automatically updates the content of the site and makes for easier site maintenance.

Django uses a three part “Model View Controller” scheme to generate web pages.

Because Django is written in Python, it can run anywhere Python can, including Linux, Windows, and even the iPhone.

Django has about five years of development, so it is quite stable. Additionally, Django has a active development community, and will often help trouble-shoot code if you get stuck (provided you've read the documentation).

Django is scalable, it is reported to handle the “slashdot effect” quite well.

The current Django release is .96, which is getting a little dated. The SVN trunk is quite stable, and is the preferred “release”. Django will be going 1.0 in September 2008.

Django was originally developed for a news website as a way to get sites built on a deadline.

Django is licensed with the BSD license.

The name Django comes from Django Reinhardt a French gypsy jazz guitarist from the 1940's and 50's.

Examples

Sam mentioned several websites that used Django.

Code

Sam then went on to outline how the code works. For more details, see Sam's presentation.

Django automatically uses validation to help filter out SQL injection. The template system defaults to escaping all variables in a template, minimizing the risk of cross site scripting.

Serving Django

Serving Django is pretty straight forward, just install Apache2 and mod_python. Then add an entry into httpd.conf to include project settings into Python path. This will serve the project through Apache. You can also define a media path for serving images and CSS for the templates.

vim httpd.conf
<Location "/">
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE talug.settings
#    PythonDebug On
    PythonDebug Off
    PythonPath "['/home/grey/Web'] + sys.path"
</Location>

<Location "/admin/media">
    SetHandler None
</Location>

Resources

Demonstration

Below are some brief notes and screenshots of the demonstration. The demo was to build a blog from scratch in Django. The end result can be downloaded here.

For the installation, we followed the official Django documentation.

The first step was to use subversion to check out the Django Newforms Admin branch.

svn co http://code.djangoproject.com/svn/django/branches/newforms-admin/ django-nfa

Then we created symbolic links for Django.

ln -s `pwd`/django-nfa/django SITE-PACKAGES-DIR/django
ln -s `pwd`/django-nfa/django/bin/django-admin.py /usr/local/bin

Then we had to start a project.

django-admin.py startproject talug

This creates a folder with the name of your project and associated Python files/scripts and settings/URLs for the project.

Next we created an application.

django-admin.py startapp blog

Then we configured the settings.

vim settings.py

After we were done editing, the file looked like this:

# Django settings for talug project.

#DEBUG = True
DEBUG = False
TEMPLATE_DEBUG = DEBUG

ADMINS = (
    # ('Your Name', 'your_email@domain.com'),
)

MANAGERS = ADMINS

DATABASE_ENGINE = 'sqlite3'           # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
DATABASE_NAME = '/home/grey/Web/talug/db/talug.db'             # Or path to database file if using sqlite3.
DATABASE_USER = ''             # Not used with sqlite3.
DATABASE_PASSWORD = ''         # Not used with sqlite3.
DATABASE_HOST = ''             # Set to empty string for localhost. Not used with sqlite3.
DATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3.

# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# If running in a Windows environment this must be set to the same as your
# system time zone.
TIME_ZONE = 'America/New_York'

# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'

SITE_ID = 1

# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True

# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = ''

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/"
MEDIA_URL = ''

# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
# trailing slash.
# Examples: "http://foo.com/media/", "/media/".
ADMIN_MEDIA_PREFIX = '/admin/media/'

# Make this unique, and don't share it with anybody.
SECRET_KEY = '7cwwg+u0oe=^pvq=hz*t6jc_wp#g24*l+r+lw&=x4r7=7(39fs'

# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.load_template_source',
    'django.template.loaders.app_directories.load_template_source',
#     'django.template.loaders.eggs.load_template_source',
)

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.doc.XViewMiddleware',
)

ROOT_URLCONF = 'talug.urls'

TEMPLATE_DIRS = (
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
    '/home/grey/Web/talug/templates',
)

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
    'talug.blog',
)

Some comments that were made:

Note When using a SQLite database with Apache, the folder containing the file and the file itself should be read-writeable by the webserver user.

Next we configured how Django handles URLs.

vim urls.py

And we just need to uncomment a few lines:

from django.conf.urls.defaults import *

# Uncomment this for admin:
from django.contrib import admin

urlpatterns = patterns('',
    # Example:
    (r'^blog/', include('talug.blog.urls')),

    # Uncomment this for admin docs:
    #(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment this for admin:
    ('^admin/(.*)', admin.site.root),
)

Then we set up the blog:

cd blog
vim models.py

Where we created two Models: BlogPost and Tag.

from django.db import models
from django.contrib import admin
from django.db.models import permalink

# Create your models here.

class Tag(models.Model):
    name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

class BlogPost(models.Model):
    title = models.CharField(max_length=50)
    content = models.TextField()
    tag = models.ManyToManyField(Tag)

    def __unicode__(self):
        return self.title

    def get_absolute_url(self):
        return '%s/' % self.id

class TagAdmin(admin.ModelAdmin):
    pass

class BlogPostAdmin(admin.ModelAdmin):
    pass

admin.site.register(Tag, TagAdmin)
admin.site.register(BlogPost, BlogPostAdmin)

Next we initiated the database.

cd ..
mkdir db
./manage.py syncdb

When you create a database for the first time, it asks if you want to define a superuser.

To explore our database, we installed sqlitebrowser.

sudo apt-get install sqlitebrowser
sqlitebrowser db/talug.db

To test the Object-Relational Mapping with the database API, we started the Django Python interactive shell.

./manage.py shell

After a bit more work, when we were ready to start testing, we just needed to serve it. Django makes it easy with a built in webserver designed for testing. This works better than Apache because things are updated in real time.

./manage.py runserver

When we first started it, we got an error because no templates were defined. This provided an example of the debug output (see the picture below).

Below are a series of screenshots of the development. If you want more info, check out the archive of the files.

Debug Info

Debug Info

Admin Interface

Admin Interface

Blog Interface

Blog Interface

Simple Template

Simple Template

Edited Template

Edited Template

Links Added

Links Added

More Blog Entries Show Up

Blogs

Clicking On Blogs From Main Page

Blogs

Clicking On Blogs From Main Page

Blogs

Next Meeting Topics

Based on typical summer attendances, and our lack of a speaker for next month, we are going to be taking July off. We will be picking things back up in August once school starts again. Have a good summer!