Feed Sign in with OpenID OpenID

Simon Willison’s Weblog

How Django processes a request

I’ve decided to kick-start some architecture documentation for Django by describing how the core request handling mechanism in Django works. I’m talking about the part of Django that takes a request from a browser and turns it in to a response—I won’t be discussing the template system, object-relational mapper or automated admin interface, which are all separate components; in fact, you don’t need to use any of those to build a Django application.

When Django receives a request, the first thing it does is create an HttpRequest object (or subclass there-of) to represent that request. How this is done differs depending on the host environment, with different code depending on if Django is running under mod_python or WSGI (which enables hosting with CGI, Twisted and more). This HttpRequest object is the principle abstraction that enables Django to work under different hosting mechanisms.

Once the object has been created, Django performs URL resolution. This is a process by which the URL specified in the request is used to select a view function to handle the creation of a response. A trivial Django application is simply one or more view functions and a configuration file that maps those functions to URLs.

Having resolved the URL to a view, the view function is called with the request object as the first argument. Other keyword arguments may be passed as well depending on the URL configuration; see the documentation for details.

The view function is where the bulk of the work happens: it is here that database queries are made, templates loaded, HTML is generated and an HttpResponse object encapsulating the result is created. The view function returns this object, which is then passed back to the environment-specific code (mod_python or WSGI) which passes it back to the browser as an HTTP response.

This is all pretty straightforward stuff—but I skipped a couple of important details: exceptions and middleware. The view function doesn’t have to return an HttpResponse; it can raise an exception instead, the most common varieties being Http404 (for file-not-found) or Http500 (for server error). In development servers these exceptions will be formatted and sent back to the browser, while in production mode they will be silently logged and a “friendly” error message displayed.

Middleware is even more interesting. Django provides three hooks in the above sequence where middleware classes can intervene, with the middleware classes to be used defined in the site’s configuration file. This results in three types of middleware: request, view and response (although one middleware class can apply for more than one hook).

Request middleware runs after the HttpRequest object has been created but before the URL resolver runs, allowing it to modify the request in some way or to return a response of its own before the rest of the application has a chance to run.

View middleware is executed after the URL resolver has been used to identify the view but before the view itself runs. It is passed the view as a callback, allowing it to perform operations before and after the view has been executed. Alternatively, it can avoid running the view function at all.

Response middleware is run right at the end, after a response has been created but before it is passed back to the client. It has the ability to make final modifications to the HttpResponse object; for example, it could remove unnecessary whitespace from HTML or apply gzip compression.

The bulk of the above code can be found in the __call__ method of the ModPythonHandler class and the get_response method of the BaseHandler class. Example middleware classes can be found in the middleware directory. As Django is not yet at a 1.0 release, the above is all subject to potential refactoring future change.

This is How Django processes a request by Simon Willison, posted on 15th August 2005.

Tagged

View blog reactions

Next: Django and Rails London meetup

Previous: Exciting developments with Django

9 comments

  1. In the last sentence of the second paragraph, I assume you mean to refer to the HttpRequest object rather than the HttpResponse object.

    Gordon - 16th August 2005 01:02 - #

  2. Curious Simon, how does Django perform under a reasonable load scenario in your opinion? Reason I ask, I've found some of the Zope powered sites to feel a little slow at times. Of course, I don't know if that is just underpowered servers, poor architecture or that Zope itself isn't the fastest man out of the blocks. Al.

    Alistair - 16th August 2005 02:14 - #

  3. "Curious Simon".. ouch. ;)

    Alistair, check LJ World or KU Sports, both of which are under load and powered by django.

    Jeremy Dunck - 16th August 2005 04:04 - #

  4. [rant]

    Please, please please don't call it refactoring! Refactoring is a change in implementation which does not change behaviour, typically at a single class level. From the horses mouth:

    "Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior."

    (I tried posting the above quote as a blockquote but kept getting the error "Tag blockquote may not contain raw character data").

    If a refactoring change results in your documentation being out of date then it either isn't a refactoring or your documentation is too fine grained!

    It's a little bugbear of mine, but I get really annoyed when people talk about 3 day refactorings - refactorings typically take around 10 minutes and are about improving code quality, not about changing architecutre.

    [/rant]

    Sam Newman - 16th August 2005 11:10 - #

  5. On the subject of load Alistar, also consider the work put into caching - which as well as having multiple levels of granularity, also has three different backends. A sure sign that they've had to cope with load!

    Sam Newman - 16th August 2005 11:19 - #

  6. "XHTML must be well formed."

    i.e.

    [blockquote][p]Content[/p][/blockquote]

    Chris Neale - 16th August 2005 14:20 - #

  7. Ah crud - thanks Chris. I've got so used to Textile doing that stuff for me!

    Sam Newman - 16th August 2005 18:14 - #

  8. Gordon: fixed, thanks. Alistair: As Jeremy pointed out, Django has had a fair bit of experience under load (ChicagoCrime.org has survived a slashdotting). Sam: you're absolutely right, thanks for the kick.

    Simon Willison - 16th August 2005 19:06 - #

  9. And now I feel like the terminology police! Being a buzzword pedant was always a thankless task...

    sam newman - 16th August 2005 22:34 - #

Comments are closed.

Previously hosted at http://simon.incutio.com/archive/2005/08/15/request

A django site