Django

From FMNWiki
Jump to: navigation, search

Django is a Python-based web framework. If you want general information about it, go to its website. However, using it isn't quite as simple as I thought it might be. There are lots and lots and lots of quirks to deal with, and more items missing than I can shake a stick at. So here is my own tutorial, which will eventually migrate to a Django-based page.

Contents

Installation

I'm making the bold assumption that this will be installed on a Unix-based system with Python 2.6 already installed, and Apache2 as your web server. Consult your distribution's documentation to get that taken care of. I'm also making the assumption that you have at the very least a passing familiarity with Python. I'll cover fancy things like decorations here, but you should have a working knowledge of the syntax, and basic knowledge of classes before you dive in to this tutorial.

I recommend installing, for now, the "bleeding-edge" version. Run the command

svn co http://code.djangoproject.com/svn/django/trunk/ django-trunk

in an appropriate directory. Then run

cd django-trunk
python setup.py install

Though updates will be slightly more difficult this way, I prefer to keep a working copy and the svn copy separate.

Setup

In the directory where your web-facing files will be housed (In the example, I'll use /srv/www/[1]), run

django-admin.py startproject mysite
cd mysite
ls mysite

You'll see four files:

__init__.py
manage.py
settings.py
urls.py

Using your favorite editor, open settings.py. Find the lines that begin similar to the following and change their settings like so:

DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'django_db'

and

MEDIA_ROOT = '/srv/www/static/'
MEDIA_URL = '/static/'

We're going to use sqlite3 for the database for the moment. Using MySQL with Django is a bit more complicated, and unnecessary for something tiny. We'll leave the other settings alone for the time being.

Finally--for this part--run the command (from /srv/www/)

python manage.py syncdb

You'll be asked to create a superuser account, so provide a username and password for this account when prompted.

Time to update Apache to serve these files. Make sure Apache is installed with mod_python (see your distro's documentation for instructions); restart Apache if necessary.

Create a file yourwebsite.com in /etc/apache2/sites-available/[1] (you'll have to sudo or be root to do so) and set its contents to this:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE testproject.settings
    PythonPath "['/srv/www'] + sys.path"
    PythonDebug On
    DocumentRoot /srv/www
    <LocationMatch "/static/">
        SetHandler none
        Options -indexes
    </LocationMatch>
    <LocationMatch "/media/">
        SetHandler none
    </LocationMatch>
    <LocationMatch "\.(jpg|gif|png)$">
        SetHandler none
    </LocationMatch>
</VirtualHost>

then run the command

sudo a2ensite example.com
sudo /etc/init.d/apache2 reload

Finally, visit http://www.example.com in your browser, and you should see a page that looks like this!

image not yet available

Poll App

Okay, so it's been done to death, and it makes up the official tutorial, but it's a great place to start. Once I've gone over that, hopefully having made it a bit clearer than they did, I'm going to keep going, adding features. We'll wind up with a site most webmasters would be quite proud of (I hope).

Setup

In /srv/www/, run the command

python manage.py startapp polls
ls polls

You should see four files:

__init__.py
models.py
tests.py
views.py

Edit polls/models.py to the following listing:

from django.db import models

class Poll( models.Model):
    question = models.CharField( max_length = 200)
    pub_date = models.DateTimeField( 'date published')

class Choice( models.Model):
    poll = models.ForeignKey( Poll)
    choice = models.CharField( max_length = 200)
    votes = models.IntegerField()

Django uses a "model" class as the basis for the database structure that will be created. The models.py file defines the database structure. When considering your database structure, think of it this way: each Poll will have one or more Choice objects associated with it. And every Choice will be associated with one Poll. The poll = models.ForeignKey( Poll) statement tells Django to set that relationship when the database tables are created. The other fields should be relatively self-explanatory. Note: max_length is a required setting/attribute for CharField. For a full list of built-in fields, see here.

We can't go straightaway to using this application; there's a bit more work to be done.

Back in settings.py, add 'mysite.polls' to the installed apps section. It should now look something like

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'mysite.polls',
)

Now run the command (from /srv/www/)

python manage.py syncdb

Two tables will be created in the sqlite3 database: polls_poll and polls_choice. If you wish to see the SQL that was used to create them, run

python manage.py sql polls

The official tutorial makes extensive use of the shell; I'm not going to cover that here. Let's start with the built-in admin interface.

Admin

Edit urls.py. Pay close attention to this file listing. Uncomment the lines in bold--make sure you get all three!

from django.conf.urls.defaults import *

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

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

    # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
    # to INSTALLED_APPS to enable admin documentation:
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    (r'^admin/', include(admin.site.urls)),
)

After restarting Apache, you can log in to your website at http://www.example.com/admin/ with the superuser account created earlier, but you can't edit your polls yet.

Create the file polls/admin.py and set it to the following listing:

from mysite.polls.models import Poll, Choice
from django.contrib import admin

admin.site.register( Poll)
admin.site.register( Choice)

First Poll

Restart Apache and log in (restarting here may or may not be necessary; I just do it for good measure now and again). There should now be a section titled "Polls" with links labeled "Polls" and "Choices" underneath. On the right will be "Add" and "Change" links. Let's use this to set up a poll.

Click the "Add" link to the right of "Polls". Set "Question" to "What will be the primary use of your personal robot?" (or another question of your choice). Set "Date" and "Time" to "Today" and "Now" respectively, clicking on the links for ease. Click the "Save" button.

Now you'll see what may eventually become a list of polls. There's only one item, the poll you just created, but wait! It's listed as "Poll object"! You may ask, "How do I tell it apart from other polls?" We'll get to that in a bit.

Toward the top of the screen, you should see Something like "Home › Polls › Polls". Click on "Home" or the first instance of "Polls". Then click the "Add" link to the right of "Choices". Select "Poll object" from the drop down box next to "Poll", set "Choice" to "personal bodyguard" and "Votes" to "0". Click "Save and add another". Repeat for a couple more choices like "housekeeping/errands/chores" and "taking over the world". On your last choice, just click "Save".

You'll notice again that a list of choices is displayed, all are listed as "Choice object". This is becoming a problem, isn't it? Time to fix that.

Cleanup

Back in models.py, within the Poll class, we need a function definition to clean these up. Add the following code:

def __unicode__( self):
    return self.question

And in the Choice class:

def __unicode__( self):
    return self.choice

Now check how it appears in your browser: the of the question and choices text should be there instead of "Poll object" and "Choice object", respectively. You may have to clear your browser's cache and/or refresh the page to see the change. Also, note that if you add another choice, instead of picking "Poll object" from the drop down list, you pick the question with which your choice will be associated--a much more intuitive method than guessing!

Final Tweaks to Back End

It would, however, be even simpler and more intuitive if the choices were added at the same time as the question, or on the same form. We can do that, too! This will require doing a bit more work, but it may be easier than you expect, especially if you're used to writing web-based database applications in PHP or ASP!

Edit polls/admin.py again. Remove the statements

admin.site.register( Poll)
admin.site.register( Choice)

And add this code:

class ChoiceInline( admin.StackedInline):
    model = Choice

class PollAdmin( admin.ModelAdmin):
    inlines = [ ChoiceInline]

admin.site.register( Poll, PollAdmin)

If you return to the admin website, you'll notice that the option to edit Choices seems to be gone--but click on the "Change" link next to "Polls"--all the choices are now here! Along with extra blanks for you to add more. But it's kind of bulky--change that "StackedInline" to "TabularInline" and see how it looks. Much better!


  1. a b Change directory as appropriate for your distribution or preference
Personal tools