Weblog

On Django's HTTP respect

Because we're perfectionists, we've taken care when designing Django to make sure It Does The Right Thing when it comes to following HTTP standards.

Ryan Tomayko touched on HTTP, and how most Web frameworks don't use it correctly, in his "On HTTP Abuse" piece earlier this year. In the article, he rhetorically asked which frameworks make certain HTTP functionality easy, or do it the "right" way.

Let's take a detailed look at each of his questions and point out precisely what Django does in each case.

For instance, which frameworks...help implement content negotiation properly?

A few parts of Django perform server-driven content negotiation for you automatically. For instance, the GZipMiddleware compresses content for browsers that understand gzip compression.

Django gives developers a simple way to set the Vary header, as mentioned in the RFC linked above, "to express the parameters the server uses to select a representation that is subject to server-driven negotiation." See the "Using Vary headers" documentation. By default, all functionality that comes with Django, such as the session and cache systems, sets the appropriate Vary header(s) automatically.

For more obscure content-negotiation needs, you can access all HTTP headers in any request object. If you can think of any useful negotiation-related functionality we could add to Django, please let us know by posting to django-developers or our ticket system.

...provide facilities for implementing a smart caching strategy for dynamic content? (proper use of If-Modified-Since, Expires, Cache-Control, etc.)

Django's middleware takes care of this. The ConditionalGetMiddleware handles If-None-Match or If-Modified-Since. CacheMiddleware takes care of the Last-Modified, Expires and Cache-Control headers.

...make dealing with media types easy?

It's outside Django's scope to deal with media files at this point.

...make dealing with character encodings easy?

Django's got you covered here. The DEFAULT_CHARSET setting lets you specify the systemwide character encoding of input and output in all Django-powered pages. Things Just Work.

...encourage the use of standard HTTP authentication schemes?

Django's session support doesn't use standard HTTP authentication, because we don't like the usability (or, lack thereof) of HTTP authentication in modern browsers -- particularly the fact that a user can't log out without closing her browser. If there's interest, we can add support for HTTP auth.

...have a sane mechanism for attaching different behavior to different verbs for a single resource?

Yes. We're fanatical about this. This is why each request object has separate GET and POST attributes -- so developers can differentiate between the two. You can use request.META["REQUEST_METHOD"] to get the exact request method, in case you need to support something less common, such as PUT.

...help ensure that URIs stay cool?

An emphatic yes. This is another thing we're fanatical about. Django's URL-dispatching syntax encourages cool URLs -- URLs without file extensions. It also makes it simple to support legacy (e.g. ".php") URLs and redirect them as needed.

...make dealing with transfer encodings (gzip, compress, etc.) easy?

Just turn on GZipMiddleware, and Django automatically will gzip your pages for browsers that support it. We don't have a "compress" middleware, but adding one would be a cinch.

...help you use response status codes properly? (e.g. Nearly all dynamic content returns either a 200 or 500).

Here's another thing we're passionate about. Each response object uses status code 200 by default. The HttpResponse subclasses (e.g. HttpResponseServerError or HttpResponseNotFound) all return the right status code. We encourage you to use the right response types in your applications.

The built-in Django pages, such as error pages and "page not found" error pages, use 500 and 404, respectively.

Posted by Adrian Holovaty on October 24, 2005