mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7124 bcc190cf-cafb-0310-a4f2-bffc1f526a37
		
			
				
	
	
		
			612 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			612 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| ============================
 | |
| Request and response objects
 | |
| ============================
 | |
| 
 | |
| Quick overview
 | |
| ==============
 | |
| 
 | |
| 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.
 | |
| 
 | |
| This document explains the APIs for ``HttpRequest`` and ``HttpResponse``
 | |
| objects.
 | |
| 
 | |
| HttpRequest objects
 | |
| ===================
 | |
| 
 | |
| Attributes
 | |
| ----------
 | |
| 
 | |
| All attributes except ``session`` should be considered read-only.
 | |
| 
 | |
| ``path``
 | |
|     A string representing the full path to the requested page, not including
 | |
|     the domain.
 | |
| 
 | |
|     Example: ``"/music/bands/the_beatles/"``
 | |
| 
 | |
| ``method``
 | |
|     A string representing the HTTP method used in the request. This is
 | |
|     guaranteed to be uppercase. Example::
 | |
| 
 | |
|         if request.method == 'GET':
 | |
|             do_something()
 | |
|         elif request.method == 'POST':
 | |
|             do_something_else()
 | |
| 
 | |
| ``encoding``
 | |
|     **New in Django development version**
 | |
| 
 | |
|     A string representing the current encoding used to decode form submission
 | |
|     data (or ``None``, which means the ``DEFAULT_CHARSET`` setting is used).
 | |
|     You can write to this attribute to change the encoding used when accessing
 | |
|     the form data. Any subsequent attribute accesses (such as reading from
 | |
|     ``GET`` or ``POST``) will use the new ``encoding`` value.  Useful if you
 | |
|     know the form data is not in the ``DEFAULT_CHARSET`` encoding.
 | |
| 
 | |
| ``GET``
 | |
|     A dictionary-like object containing all given HTTP GET parameters. See the
 | |
|     ``QueryDict`` documentation below.
 | |
| 
 | |
| ``POST``
 | |
|     A dictionary-like object containing all given HTTP POST parameters. See the
 | |
|     ``QueryDict`` documentation below.
 | |
| 
 | |
|     It's possible that a request can come in via POST with an empty ``POST``
 | |
|     dictionary -- if, say, a form is requested via the POST HTTP method but
 | |
|     does not include form data. Therefore, you shouldn't use ``if request.POST``
 | |
|     to check for use of the POST method; instead, use ``if request.method ==
 | |
|     "POST"`` (see above).
 | |
| 
 | |
|     Note: ``POST`` does *not* include file-upload information. See ``FILES``.
 | |
| 
 | |
| ``REQUEST``
 | |
|     For convenience, a dictionary-like object that searches ``POST`` first,
 | |
|     then ``GET``. Inspired by PHP's ``$_REQUEST``.
 | |
| 
 | |
|     For example, if ``GET = {"name": "john"}`` and ``POST = {"age": '34'}``,
 | |
|     ``REQUEST["name"]`` would be ``"john"``, and ``REQUEST["age"]`` would be
 | |
|     ``"34"``.
 | |
| 
 | |
|     It's strongly suggested that you use ``GET`` and ``POST`` instead of
 | |
|     ``REQUEST``, because the former are more explicit.
 | |
| 
 | |
| ``COOKIES``
 | |
|     A standard Python dictionary containing all cookies. Keys and values are
 | |
|     strings.
 | |
| 
 | |
| ``FILES``
 | |
|     A dictionary-like object containing all uploaded files. Each key in
 | |
|     ``FILES`` is the ``name`` from the ``<input type="file" name="" />``. Each
 | |
|     value in ``FILES`` is a standard Python dictionary with the following three
 | |
|     keys:
 | |
| 
 | |
|         * ``filename`` -- The name of the uploaded file, as a Python string.
 | |
|         * ``content-type`` -- The content type of the uploaded file.
 | |
|         * ``content`` -- The raw content of the uploaded file.
 | |
| 
 | |
|     Note that ``FILES`` will only contain data if the request method was POST
 | |
|     and the ``<form>`` that posted to the request had
 | |
|     ``enctype="multipart/form-data"``. Otherwise, ``FILES`` will be a blank
 | |
|     dictionary-like object.
 | |
| 
 | |
| ``META``
 | |
|     A standard Python dictionary containing all available HTTP headers.
 | |
|     Available headers depend on the client and server, but here are some
 | |
|     examples:
 | |
| 
 | |
|         * ``CONTENT_LENGTH``
 | |
|         * ``CONTENT_TYPE``
 | |
|         * ``HTTP_ACCEPT_ENCODING``
 | |
|         * ``HTTP_ACCEPT_LANGUAGE``
 | |
|         * ``HTTP_HOST`` -- The HTTP Host header sent by the client.
 | |
|         * ``HTTP_REFERER`` -- The referring page, if any.
 | |
|         * ``HTTP_USER_AGENT`` -- The client's user-agent string.
 | |
|         * ``QUERY_STRING`` -- The query string, as a single (unparsed) string.
 | |
|         * ``REMOTE_ADDR`` -- The IP address of the client.
 | |
|         * ``REMOTE_HOST`` -- The hostname of the client.
 | |
|         * ``REQUEST_METHOD`` -- A string such as ``"GET"`` or ``"POST"``.
 | |
|         * ``SERVER_NAME`` -- The hostname of the server.
 | |
|         * ``SERVER_PORT`` -- The port of the server.
 | |
| 
 | |
| ``user``
 | |
|     A ``django.contrib.auth.models.User`` object representing the currently
 | |
|     logged-in user. If the user isn't currently logged in, ``user`` will be set
 | |
|     to an instance of ``django.contrib.auth.models.AnonymousUser``. You
 | |
|     can tell them apart with ``is_authenticated()``, like so::
 | |
| 
 | |
|         if request.user.is_authenticated():
 | |
|             # Do something for logged-in users.
 | |
|         else:
 | |
|             # Do something for anonymous users.
 | |
| 
 | |
|     ``user`` is only available if your Django installation has the
 | |
|     ``AuthenticationMiddleware`` activated. For more, see
 | |
|     `Authentication in Web requests`_.
 | |
| 
 | |
|     .. _Authentication in Web requests: ../authentication/#authentication-in-web-requests
 | |
| 
 | |
| ``session``
 | |
|     A readable-and-writable, dictionary-like object that represents the current
 | |
|     session. This is only available if your Django installation has session
 | |
|     support activated. See the `session documentation`_ for full details.
 | |
| 
 | |
|     .. _`session documentation`: ../sessions/
 | |
| 
 | |
| ``raw_post_data``
 | |
|     The raw HTTP POST data. This is only useful for advanced processing. Use
 | |
|     ``POST`` instead.
 | |
| 
 | |
| Methods
 | |
| -------
 | |
| 
 | |
| ``__getitem__(key)``
 | |
|    Returns the GET/POST value for the given key, checking POST first, then
 | |
|    GET. Raises ``KeyError`` if the key doesn't exist.
 | |
| 
 | |
|    This lets you use dictionary-accessing syntax on an ``HttpRequest``
 | |
|    instance. Example: ``request["foo"]`` would return ``True`` if either
 | |
|    ``request.POST`` or ``request.GET`` had a ``"foo"`` key.
 | |
| 
 | |
| ``has_key()``
 | |
|    Returns ``True`` or ``False``, designating whether ``request.GET`` or
 | |
|    ``request.POST`` has the given key.
 | |
| 
 | |
| ``get_host()``
 | |
|    **New in Django development version**
 | |
| 
 | |
|    Returns the originating host of the request using information from the
 | |
|    ``HTTP_X_FORWARDED_HOST`` and ``HTTP_HOST`` headers (in that order). If
 | |
|    they don't provide a value, the method uses a combination of
 | |
|    ``SERVER_NAME`` and ``SERVER_PORT`` as detailed in `PEP 333`_.
 | |
| 
 | |
|    .. _PEP 333: http://www.python.org/dev/peps/pep-0333/
 | |
| 
 | |
|    Example: ``"127.0.0.1:8000"``
 | |
| 
 | |
| ``get_full_path()``
 | |
|    Returns the ``path``, plus an appended query string, if applicable.
 | |
| 
 | |
|    Example: ``"/music/bands/the_beatles/?print=true"``
 | |
| 
 | |
| ``build_absolute_uri(location)``
 | |
|    **New in Django development version**
 | |
| 
 | |
|    Returns the absolute URI form of ``location``. If no location is provided,
 | |
|    the location will be set to ``request.get_full_path()``.
 | |
| 
 | |
|    If the location is already an absolute URI, it will not be altered.
 | |
|    Otherwise the absolute URI is built using the server variables available in
 | |
|    this request.
 | |
| 
 | |
|    Example: ``"http://example.com/music/bands/the_beatles/?print=true"``
 | |
| 
 | |
| ``is_secure()``
 | |
|    Returns ``True`` if the request is secure; that is, if it was made with
 | |
|    HTTPS.
 | |
| 
 | |
| QueryDict objects
 | |
| -----------------
 | |
| 
 | |
| 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 all the standard dictionary methods, because it's a
 | |
| subclass of dictionary. Exceptions are outlined here:
 | |
| 
 | |
|     * ``__getitem__(key)`` -- Returns the value for the given key. If the key
 | |
|       has more than one value, ``__getitem__()`` returns the last value.
 | |
|       Raises ``django.utils.datastructure.MultiValueDictKeyError`` if the key
 | |
|       does not exist. (This is a subclass of Python's standard ``KeyError``,
 | |
|       so you can stick to catching ``KeyError``.)
 | |
| 
 | |
|     * ``__setitem__(key, value)`` -- Sets the given key to ``[value]``
 | |
|       (a Python list whose single element is ``value``). Note that this, as
 | |
|       other dictionary functions that have side effects, can only be called on
 | |
|       a mutable ``QueryDict`` (one that was created via ``copy()``).
 | |
| 
 | |
|     * ``__contains__(key)`` -- Returns ``True`` if the given key is set. This
 | |
|       lets you do, e.g., ``if "foo" in request.GET``.
 | |
| 
 | |
|     * ``get(key, default)`` -- Uses the same logic as ``__getitem__()`` above,
 | |
|       with a hook for returning a default value if the key doesn't exist.
 | |
| 
 | |
|     * ``has_key(key)``
 | |
| 
 | |
|     * ``setdefault(key, default)`` -- Just like the standard dictionary
 | |
|       ``setdefault()`` method, except it uses ``__setitem__`` internally.
 | |
| 
 | |
|     * ``update(other_dict)`` -- Takes either a ``QueryDict`` or standard
 | |
|       dictionary. Just like the standard dictionary ``update()`` method, except
 | |
|       it *appends* to the current dictionary items rather than replacing them.
 | |
|       For example::
 | |
| 
 | |
|           >>> q = QueryDict('a=1')
 | |
|           >>> q = q.copy() # to make it mutable
 | |
|           >>> q.update({'a': '2'})
 | |
|           >>> q.getlist('a')
 | |
|           ['1', '2']
 | |
|           >>> q['a'] # returns the last
 | |
|           ['2']
 | |
| 
 | |
|     * ``items()`` -- Just like the standard dictionary ``items()`` method,
 | |
|       except this uses the same last-value logic as ``__getitem()__``. For
 | |
|       example::
 | |
| 
 | |
|            >>> q = QueryDict('a=1&a=2&a=3')
 | |
|            >>> q.items()
 | |
|            [('a', '3')]
 | |
| 
 | |
|     * ``values()`` -- Just like the standard dictionary ``values()`` method,
 | |
|       except this uses the same last-value logic as ``__getitem()__``. For
 | |
|       example::
 | |
| 
 | |
|            >>> q = QueryDict('a=1&a=2&a=3')
 | |
|            >>> q.values()
 | |
|            ['3']
 | |
| 
 | |
| In addition, ``QueryDict`` has the following methods:
 | |
| 
 | |
|     * ``copy()`` -- Returns a copy of the object, using ``copy.deepcopy()``
 | |
|       from the Python standard library. The copy will be mutable -- that is,
 | |
|       you can change its values.
 | |
| 
 | |
|     * ``getlist(key)`` -- 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.
 | |
| 
 | |
|     * ``setlist(key, list_)`` -- Sets the given key to ``list_`` (unlike
 | |
|       ``__setitem__()``).
 | |
| 
 | |
|     * ``appendlist(key, item)`` -- Appends an item to the internal list
 | |
|       associated with key.
 | |
| 
 | |
|     * ``setlistdefault(key, default_list)`` -- Just like ``setdefault``, except
 | |
|       it takes a list of values instead of a single value.
 | |
| 
 | |
|     * ``lists()`` -- Like ``items()``, except it includes all values, as a list,
 | |
|       for each member of the dictionary. For example::
 | |
| 
 | |
|            >>> q = QueryDict('a=1&a=2&a=3')
 | |
|            >>> q.lists()
 | |
|            [('a', ['1', '2', '3'])]
 | |
| 
 | |
|     * ``urlencode()`` -- Returns a string of the data in query-string format.
 | |
|       Example: ``"a=2&b=3&b=5"``.
 | |
| 
 | |
| Examples
 | |
| --------
 | |
| 
 | |
| Here's an example HTML form and how Django would treat the input::
 | |
| 
 | |
|     <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 notes
 | |
| --------------------
 | |
| 
 | |
| 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.
 | |
| 
 | |
| HttpResponse objects
 | |
| ====================
 | |
| 
 | |
| 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 in the ``django.http`` module.
 | |
| 
 | |
| Usage
 | |
| -----
 | |
| 
 | |
| Passing strings
 | |
| ~~~~~~~~~~~~~~~
 | |
| 
 | |
| Typical usage is 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
 | |
| file-like 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 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."
 | |
| 
 | |
| Note that ``del`` doesn't raise ``KeyError`` if the header doesn't exist.
 | |
| 
 | |
| Passing iterators
 | |
| ~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Finally, 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 the ``HttpResponse`` instance as a file-like
 | |
|       object. Doing so will raise ``Exception``.
 | |
| 
 | |
| Methods
 | |
| -------
 | |
| 
 | |
| ``__init__(content='', mimetype=None, status=200, content_type=DEFAULT_CONTENT_TYPE)``
 | |
|     Instantiates an ``HttpResponse`` object with the given page content (a
 | |
|     string) and MIME type. The ``DEFAULT_CONTENT_TYPE`` is ``'text/html'``.
 | |
| 
 | |
|     ``content`` can be an iterator or a string. If it's an iterator, it should
 | |
|     return strings, and those strings will be joined together to form the
 | |
|     content of the response.
 | |
| 
 | |
|     ``status`` is the `HTTP Status code`_ for the response.
 | |
| 
 | |
|     **(New in Django development version)** ``content_type`` is an alias for
 | |
|     ``mimetype``. Historically, the parameter was only called ``mimetype``,
 | |
|     but since this is actually the value included in the HTTP ``Content-Type``
 | |
|     header, it can also include the character set encoding, which makes it
 | |
|     more than just a MIME type specification. If ``mimetype`` is specified
 | |
|     (not None), that value is used. Otherwise, ``content_type`` is used. If
 | |
|     neither is given, the ``DEFAULT_CONTENT_TYPE`` setting is used.
 | |
| 
 | |
| ``__setitem__(header, value)``
 | |
|     Sets the given header name to the given value. Both ``header`` and
 | |
|     ``value`` should be strings.
 | |
| 
 | |
| ``__delitem__(header)``
 | |
|     Deletes the header with the given name. Fails silently if the header
 | |
|     doesn't exist. Case-sensitive.
 | |
| 
 | |
| ``__getitem__(header)``
 | |
|     Returns the value for the given header name. Case-sensitive.
 | |
| 
 | |
| ``has_header(header)``
 | |
|     Returns ``True`` or ``False`` based on a case-insensitive check for a
 | |
|     header with the given name.
 | |
| 
 | |
| ``set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None)``
 | |
|     Sets a cookie. The parameters are the same as in the `cookie Morsel`_
 | |
|     object in the Python standard library.
 | |
| 
 | |
|         * ``max_age`` should be a number of seconds, or ``None`` (default) if
 | |
|           the cookie should last only as long as the client's browser session.
 | |
|         * ``expires`` should be a string in the format
 | |
|           ``"Wdy, DD-Mon-YY HH:MM:SS GMT"``.
 | |
|         * Use ``domain`` if you want to set a cross-domain cookie. For example,
 | |
|           ``domain=".lawrence.com"`` will set a cookie that is readable by
 | |
|           the domains www.lawrence.com, blogs.lawrence.com and
 | |
|           calendars.lawrence.com. Otherwise, a cookie will only be readable by
 | |
|           the domain that set it.
 | |
| 
 | |
|     .. _`cookie Morsel`: http://www.python.org/doc/current/lib/morsel-objects.html
 | |
| 
 | |
| ``delete_cookie(key, path='/', domain=None)``
 | |
|     Deletes the cookie with the given key. Fails silently if the key doesn't
 | |
|     exist.
 | |
| 
 | |
|     Due to the way cookies work, ``path`` and ``domain`` should be the same
 | |
|     values you used in ``set_cookie()`` -- otherwise the cookie may not be deleted.
 | |
| 
 | |
| ``content``
 | |
|     Returns the content as a Python string, encoding it from a Unicode object
 | |
|     if necessary. Note this is a property, not a method, so use ``r.content``
 | |
|     instead of ``r.content()``.
 | |
| 
 | |
| ``write(content)``, ``flush()`` and ``tell()``
 | |
|     These methods make an ``HttpResponse`` instance a file-like object.
 | |
| 
 | |
| .. _HTTP Status code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10
 | |
| 
 | |
| HttpResponse subclasses
 | |
| -----------------------
 | |
| 
 | |
| Django includes a number of ``HttpResponse`` subclasses that handle different
 | |
| types of HTTP responses. Like ``HttpResponse``, these subclasses live in
 | |
| ``django.http``.
 | |
| 
 | |
| ``HttpResponseRedirect``
 | |
|     The constructor takes a single argument -- the path to redirect to. This
 | |
|     can be a fully qualified URL (e.g. ``'http://www.yahoo.com/search/'``) or an
 | |
|     absolute URL with no domain (e.g. ``'/search/'``). Note that this returns
 | |
|     an HTTP status code 302.
 | |
| 
 | |
| ``HttpResponsePermanentRedirect``
 | |
|     Like ``HttpResponseRedirect``, but it returns a permanent redirect (HTTP
 | |
|     status code 301) instead of a "found" redirect (status code 302).
 | |
| 
 | |
| ``HttpResponseNotModified``
 | |
|     The constructor doesn't take any arguments. Use this to designate that a
 | |
|     page hasn't been modified since the user's last request (status code 304).
 | |
| 
 | |
| ``HttpResponseBadRequest``
 | |
|     **New in Django development version.**
 | |
|     Acts just like ``HttpResponse`` but uses a 400 status code.
 | |
| 
 | |
| ``HttpResponseNotFound``
 | |
|     Acts just like ``HttpResponse`` but uses a 404 status code.
 | |
| 
 | |
| ``HttpResponseForbidden``
 | |
|     Acts just like ``HttpResponse`` but uses a 403 status code.
 | |
| 
 | |
| ``HttpResponseNotAllowed``
 | |
|     Like ``HttpResponse``, but uses a 405 status code. Takes a single,
 | |
|     required argument: a list of permitted methods (e.g. ``['GET', 'POST']``).
 | |
| 
 | |
| ``HttpResponseGone``
 | |
|     Acts just like ``HttpResponse`` but uses a 410 status code.
 | |
| 
 | |
| ``HttpResponseServerError``
 | |
|     Acts just like ``HttpResponse`` but uses a 500 status code.
 | |
| 
 | |
| Returning errors
 | |
| ================
 | |
| 
 | |
| Returning HTTP error codes in Django is easy. We've already mentioned the
 | |
| ``HttpResponseNotFound``, ``HttpResponseForbidden``,
 | |
| ``HttpResponseServerError``, etc., 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 404 errors are by far the most common HTTP error, there's an easier way
 | |
| to handle those errors.
 | |
| 
 | |
| The Http404 exception
 | |
| ---------------------
 | |
| 
 | |
| 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.
 | |
| 
 | |
| Example usage::
 | |
| 
 | |
|     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 located in the top level of your template tree.
 | |
| 
 | |
| Customizing error views
 | |
| -----------------------
 | |
| 
 | |
| The 404 (page not found) view
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| 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::
 | |
| 
 | |
|     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.
 | |
| 
 | |
| 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:
 | |
|       you must create a ``404.html`` template in the root of your
 | |
|       template directory. The default 404 view will use that template
 | |
|       for all 404 errors. The default 404 view will pass one variable
 | |
|       to the template: ``request_path``, which is the URL that resulted
 | |
|       in the 404.
 | |
| 
 | |
|     * The 404 view is passed a ``RequestContext`` and will have access to
 | |
|       variables supplied by your ``TEMPLATE_CONTEXT_PROCESSORS`` setting (e.g.,
 | |
|       ``MEDIA_URL``).
 | |
| 
 | |
|     * If ``DEBUG`` is set to ``True`` (in your settings module), then your 404
 | |
|       view will never be used, and the traceback will be displayed instead.
 | |
| 
 | |
| The 500 (server error) view
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| 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. The default 500
 | |
| view passes no variables to this template and is rendered with an empty
 | |
| ``Context`` to lessen the chance of additional 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::
 | |
| 
 | |
|     handler500 = 'mysite.views.my_custom_error_view'
 | |
| 
 | |
| Behind the scenes, Django determines the error view by looking for ``handler500``.
 | |
| By default, URLconfs contain the following line::
 | |
| 
 | |
|     from django.conf.urls.defaults import *
 | |
| 
 | |
| That takes care of setting ``handler500`` in the current module. As you can see
 | |
| in ``django/conf/urls/defaults.py``, ``handler500`` is set to
 | |
| ``'django.views.defaults.server_error'`` by default.
 |