Django uses request and response objects to pass state through the system.
When a page is requested, Django creates an HttpRequest
object that contains metadata about the request. Then Django loads the appropriate view, passing the HttpRequest
as the first argument to the view function. Each view is responsible for returning an HttpResponse
object.
We've used these objects often throughout the book; this appendix explains the complete APIs for HttpRequest
and HttpResponse
objects.
HttpRequest
represents a single HTTP request from some user-agent.
Much of the important information about the request is available as attributes on the HttpRequest
instance (see Table H-1). All attributes except session
should be considered read-only.
Attribute | Description |
---|---|
|
A string representing the full path to the requested page, not including the domain -- for example, |
|
A string representing the HTTP method used in the request. This is guaranteed to be uppercase. For example:
|
|
A dictionary-like object containing all given HTTP GET parameters. See the upcoming |
|
A dictionary-like object containing all given HTTP POST parameters. See the upcoming It's possible that a request can come in via POST with an empty Note: |
|
For convenience, a dictionary-like object that searches For example, if It's strongly suggested that you use |
|
A standard Python dictionary containing all cookies. Keys and values are strings. See Chapter 12 for more on using cookies. |
|
A dictionary-like object containing all uploaded files. Each key in
Note that |
|
A standard Python dictionary containing all available HTTP headers. Available headers depend on the client and server, but here are some examples:
Any HTTP headers are available in
|
|
A
For the complete details of authentication and users, see Chapter 12. |
|
A readable and writable, dictionary-like object that represents the current session. This is available only if your Django installation has session support activated. See Chapter 12. |
|
The raw HTTP POST data. This is useful for advanced processing. |
Request objects also have a few useful methods, as shown in Table H-2.
Table H-2. HttpRequest MethodsMethod | Description |
---|---|
|
Returns the GET/POST value for the given key, checking POST first, and then GET. Raises This lets you use dictionary-accessing syntax on an For example, |
|
Returns |
|
Returns the |
|
Returns |
In an HttpRequest
object, the GET
and POST
attributes are instances of django.http.QueryDict
. QueryDict
is a dictionary-like class customized to deal with multiple values for the same key. This is necessary because some HTML form elements, notably <select multiple="multiple">
, pass multiple values for the same key.
QueryDict
instances are immutable, unless you create a copy()
of them. That means you can't change attributes of request.POST
and request.GET
directly.
QueryDict
implements the all standard dictionary methods, because it's a subclass of dictionary. Exceptions are outlined in Table H-3.
Method | Differences from Standard dict Implementation |
---|---|
|
Works just like a dictionary. However, if the key has more than one value, |
|
Sets the given key to |
|
If the key has more than one value, |
|
Takes either a
|
|
Just like the standard dictionary
|
|
Just like the standard dictionary |
In addition, QueryDict
has the methods shown in Table H-4.
Method | Description |
---|---|
|
Returns a copy of the object, using |
|
Returns the data with the requested key, as a Python list. Returns an empty list if the key doesn't exist. It's guaranteed to return a list of some sort. |
|
Sets the given key to |
|
Appends an item to the internal list associated with |
|
Just like |
|
Like
|
|
Returns a string of the data in query-string format (e.g., |
For example, given this HTML form:
<form action="/foo/bar/" method="post">
<input type="text" name="your_name" />
<select multiple="multiple" name="bands">
<option value="beatles">The Beatles</option>
<option value="who">The Who</option>
<option value="zombies">The Zombies</option>
</select>
<input type="submit" />
</form>
if the user enters "John Smith"
in the your_name
field and selects both "The Beatles" and "The Zombies" in the multiple select box, here's what Django's request object would have:
>>> request.GET
{}
>>> request.POST
{'your_name': ['John Smith'], 'bands': ['beatles', 'zombies']}
>>> request.POST['your_name']
'John Smith'
>>> request.POST['bands']
'zombies'
>>> request.POST.getlist('bands')
['beatles', 'zombies']
>>> request.POST.get('your_name', 'Adrian')
'John Smith'
>>> request.POST.get('nonexistent_field', 'Nowhere Man')
'Nowhere Man'
Implementation Note:
The GET
, POST
, COOKIES
, FILES
, META
, REQUEST
, raw_post_data
, and user
attributes are all lazily loaded. That means Django doesn't spend resources calculating the values of those attributes until your code requests them.
In contrast to HttpRequest
objects, which are created automatically by Django, HttpResponse
objects are your responsibility. Each view you write is responsible for instantiating, populating, and returning an HttpResponse
.
The HttpResponse
class lives at django.http.HttpResponse
.
Typically, you'll construct an HttpResponse
to pass the contents of the page, as a string, to the HttpResponse
constructor:
>>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.", mimetype="text/plain")
But if you want to add content incrementally, you can use response
as a filelike object:
>>> response = HttpResponse()
>>> response.write("<p>Here's the text of the Web page.</p>")
>>> response.write("<p>Here's another paragraph.</p>")
You can pass HttpResponse
an iterator rather than passing it hard-coded strings. If you use this technique, follow these guidelines:
- The iterator should return strings.
- If an
HttpResponse
has been initialized with an iterator as its content, you can't use theHttpResponse
instance as a filelike object. Doing so will raiseException
.
Finally, note that HttpResponse
implements a write()
method, which makes is suitable for use anywhere that Python expects a filelike object. See Chapter 11 for some examples of using this technique.
You can add and delete headers using dictionary syntax:
>>> response = HttpResponse()
>>> response['X-DJANGO'] = "It's the best."
>>> del response['X-PHP']
>>> response['X-DJANGO']
"It's the best."
You can also use has_header(header)
to check for the existence of a header.
Avoid setting Cookie
headers by hand; instead, see Chapter 12 for instructions on how cookies work in Django.
Django includes a number of HttpResponse
subclasses that handle different types of HTTP responses (see Table H-5). Like HttpResponse
, these subclasses live in django.http
.
Class | Description |
---|---|
|
The constructor takes a single argument: the path to redirect to. This can be a fully qualified URL (e.g., |
|
Like |
|
The constructor doesn't take any arguments. Use this to designate that a page hasn't been modified since the user's last request. |
|
Acts just like |
|
Acts just like |
|
Acts just like |
|
Like |
|
Acts just like |
|
Acts just like |
You can, of course, define your own HttpResponse
subclass to support different types of responses not supported out of the box.
Returning HTTP error codes in Django is easy. We've already mentioned the HttpResponseNotFound
, HttpResponseForbidden
, HttpResponseServerError
, and other subclasses. Just return an instance of one of those subclasses instead of a normal HttpResponse
in order to signify an error, for example:
def my_view(request):
# ...
if foo:
return HttpResponseNotFound('<h1>Page not found</h1>')
else:
return HttpResponse('<h1>Page was found</h1>')
Because a 404 error is by far the most common HTTP error, there's an easier way to handle it.
When you return an error such as HttpResponseNotFound
, you're responsible for defining the HTML of the resulting error page:
return HttpResponseNotFound('<h1>Page not found</h1>')
For convenience, and because it's a good idea to have a consistent 404 error page across your site, Django provides an Http404
exception. If you raise Http404
at any point in a view function, Django will catch it and return the standard error page for your application, along with an HTTP error code 404.
Here's an example:
from django.http import Http404
def detail(request, poll_id):
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404
return render_to_response('polls/detail.html', {'poll': p})
In order to use the Http404
exception to its fullest, you should create a template that is displayed when a 404 error is raised. This template should be called 404.html
, and it should be located in the top level of your template tree.
When you raise an Http404
exception, Django loads a special view devoted to handling 404 errors. By default, it's the view django.views.defaults.page_not_found
, which loads and renders the template 404.html
.
This means you need to define a 404.html
template in your root template directory. This template will be used for all 404 errors.
This page_not_found
view should suffice for 99% of Web applications, but if you want to override the 404 view, you can specify handler404
in your URLconf, like so:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
...
)
handler404 = 'mysite.views.my_custom_404_view'
Behind the scenes, Django determines the 404 view by looking for handler404
. By default, URLconfs contain the following line:
from django.conf.urls.defaults import *
That takes care of setting handler404
in the current module. As you can see in django/conf/urls/defaults.py
, handler404
is set to 'django.views.defaults.page_not_found'
by default.
There are three things to note about 404 views:
- The 404 view is also called if Django doesn't find a match after checking every regular expression in the URLconf.
- If you don't define your own 404 view -- and simply use the default, which is recommended -- you still have one obligation: to create a
404.html
template in the root of your template directory. The default 404 view will use that template for all 404 errors.- If
DEBUG
is set toTrue
(in your settings module), then your 404 view will never be used, and the traceback will be displayed instead.
Similarly, Django executes special-case behavior in the case of runtime errors in view code. If a view results in an exception, Django will, by default, call the view django.views.defaults.server_error
, which loads and renders the template 500.html
.
This means you need to define a 500.html
template in your root template directory. This template will be used for all server errors.
This server_error
view should suffice for 99% of Web applications, but if you want to override the view, you can specify handler500
in your URLconf, like so:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
...
)
handler500 = 'mysite.views.my_custom_error_view'