June 15, 2008.
(This is part two in Ken's series, Wielding Django. - Will)
Last time, we built up a minimal Django app just to show the core ideas. In this article, we'll flesh out some of that minimalism and make our first (if still trivial) web application.
For just a few parameters, calling
settings.configure() with each is
fine. But as we start to use more of Django, we'll want to set more
parameters, which can get unwieldy. So Django lets you put those
settings in a separate file. Most people call it
you can call it whatever you want.
Starting with the project directory you used last time, put this in
It's also about time you made this app be a proper Python
module. First, make sure that the name isn't taken; tempting ones like
test are spoken for already. To be safe, if
your directory is named
import mydir at a Python
prompt; it should fail. Once you have a good package (directory) name;
just make an empty file called
Before you go typing in that code from last time to start the server
again, note that Django has a flexible framework for handling all
sorts of managerial tasks. Most people tap into it using a file called
manage.py, which you should copy into your project directory:
The core of that file is just:
project_template directory contains a few other things too,
django-admin.py createproject dumps in every new
project. You don't need them; we're building up just what we need.
Then you can run:
By default, the server only gets connections from the local machine. If you want to show it off to someone else, run instead:
(or whatever port you want), then its URL will be http://your-machine:8000/.
The management commands look for settings in
Let's get back to the app. A static page is rather boring; let's go
straight to AJAX. Here's a new app,
math_app, start the server, and go to
The basic structure should be familiar:
urlpatterns configures how URLs
map to views, and a view (
compute) constructs a response from a
request. But a few things are changed:
The regex now matches a parameter:
\w matches an alphanumeric
\w+ matches a sequence of 1 or more such characters, and
(?P<op>\w+) gives that sequence the name
op. This is all ordinary
Django passes parameters extracted from the regex to the view:
compute gets an extra keyword argument:
op. It's always a string,
even if the regex pattern matches numbers (
request.GET is a
dict with the GET parameters (
again always strings.
getattr(operator, 'add') is the same as
an alternative implementation of that part:
Okay, so you made a typo and got an error page. (If you didn't, go add
assert False to the view function to make it fail.) It's not very
helpful right now, for two reasons. We'll fix both real quick.
ROOT_URLCONFmodule. Oops, we don't have one. We can just import it, though (along with
handler404, which handles page-not-found errors):
DEBUGmode. Just add this to
Now make that typo again, and hit the error page. Click on the code lines and "Local vars" headers to expand them. Enjoy! Now let's get back to work.
Okay, so seeing a number come back from a server is kinda boring. If
we want user interface, we need some HTML. You could of course just
make another view function that returned an HttpResponse with a all
the HTML passed in a big string (just pass
mimetype='text/html' as a
parameter, so the browser doesn't think it's text). But it's a pain to
maintain that. Fortunately, Django provides a better way: the
django.views.static.serve built-in view. It takes two parameters:
path. Here are two ways you can use it:
(Don't forget to pass
request to the other view function; I almost
dict as the third parameter of
url is a way to pass extra
parameters to the view. Also, you'll notice that you can specify
views by a string; Django just imports them and uses them. You can use
both tricks for your own views as well.
Notice an important difference between this approach and what you're
probably used to from PHP or most other web development: there's no
necessary correspondence between URLs and files. You are in complete
control of that mapping. For example, you might be used to '
just a synonym for '
index.php or whatever). But
on your Django server,
/index.html gives you an error (try it!),
because you didn't explicitly state that mapping.
Anyway, let's make a user interface. Make a
static directory in your
app and put this HTML in
I used Google's AJAX API hosting to get Dojo; thanks to Will for pointing out that useful service.
That's really ugly, of course, but it shows the idea. Join us next time as we start making a real app, using some simple techniques that may be new to even experienced Django people.