(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 settings.py, but
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
django, site, and test are spoken for already. To be safe, if
your directory is named mydir, run import mydir at a Python
prompt; it should fail. Once you have a good package (directory) name;
just make an empty file called __init__.py:
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:
The project_template directory contains a few other things too,
which 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
The management commands look for settings in settings.py by
Request parameters and AJAX
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.py:
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
character, \w+ matches a sequence of 1 or more such characters, and
(?P<op>\w+) gives that sequence the name op. This is all ordinary
Python re stuff.
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 (\d).
request.GET is a dict with the GET parameters (a and b),
again always strings.
And getattr(operator, 'add') is the same as operator.add. Here's
an alternative implementation of that part:
Okay, so you made a typo and got an error page. (If you didn't, go add
an 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.
When there's an error, Django goes looking for a variable
handler500 in the ROOT_URLCONF module. Oops, we don't have one. We
can just import it, though (along with handler404, which handles
Those are just views; you can provide your own too. Also, most
people just import *, but that makes PyFlakes not work. btw, 404
and 500 are standard HTTP status codes.
When you're developing (but not in production!) it's helpful to see
the details of the error. Django provides a really nice error page for
server errors if you're in DEBUG mode. 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.
Serving static pages
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:
document_root and path. Here are two ways you can use it:
(Don't forget to pass request to the other view function; I almost
The 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 '/' being
just a synonym for '/index.html' (or 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 static/index.html: