123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- =============
- Writing views
- =============
- A view function, or *view* for short, is simply a Python function that takes a
- Web request and returns a Web response. This response can be the HTML contents
- of a Web page, or a redirect, or a 404 error, or an XML document, or an image .
- . . or anything, really. The view itself contains whatever arbitrary logic is
- necessary to return that response. This code can live anywhere you want, as long
- as it's on your Python path. There's no other requirement--no "magic," so to
- speak. For the sake of putting the code *somewhere*, the convention is to
- put views in a file called ``views.py``, placed in your project or
- application directory.
- A simple view
- =============
- Here's a view that returns the current date and time, as an HTML document:
- .. code-block:: python
- from django.http import HttpResponse
- import datetime
- def current_datetime(request):
- now = datetime.datetime.now()
- html = "<html><body>It is now %s.</body></html>" % now
- return HttpResponse(html)
- Let's step through this code one line at a time:
- * First, we import the class :class:`~django.http.HttpResponse` from the
- :mod:`django.http` module, along with Python's ``datetime`` library.
- * Next, we define a function called ``current_datetime``. This is the view
- function. Each view function takes an :class:`~django.http.HttpRequest`
- object as its first parameter, which is typically named ``request``.
- Note that the name of the view function doesn't matter; it doesn't have to
- be named in a certain way in order for Django to recognize it. We're
- calling it ``current_datetime`` here, because that name clearly indicates
- what it does.
- * The view returns an :class:`~django.http.HttpResponse` object that
- contains the generated response. Each view function is responsible for
- returning an :class:`~django.http.HttpResponse` object. (There are
- exceptions, but we'll get to those later.)
- .. admonition:: Django's Time Zone
- Django includes a :setting:`TIME_ZONE` setting that defaults to
- ``America/Chicago``. This probably isn't where you live, so you might want
- to change it in your settings file.
- Mapping URLs to views
- =====================
- So, to recap, this view function returns an HTML page that includes the current
- date and time. To display this view at a particular URL, you'll need to create a
- *URLconf*; see :doc:`/topics/http/urls` for instructions.
- Returning errors
- ================
- Returning HTTP error codes in Django is easy. There are subclasses of
- :class:`~django.http.HttpResponse` for a number of common HTTP status codes
- other than 200 (which means *"OK"*). You can find the full list of available
- subclasses in the :ref:`request/response <ref-httpresponse-subclasses>`
- documentation. Just return an instance of one of those subclasses instead of
- a normal :class:`~django.http.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>')
- There isn't a specialized subclass for every possible HTTP response code,
- since many of them aren't going to be that common. However, as documented in
- the :class:`~django.http.HttpResponse` documentation, you can also pass the
- HTTP status code into the constructor for :class:`~django.http.HttpResponse`
- to create a return class for any status code you like. For example::
- def my_view(request):
- # ...
- # Return a "created" (201) response code.
- return HttpResponse(status=201)
- Because 404 errors are by far the most common HTTP error, there's an easier way
- to handle those errors.
- The Http404 exception
- ---------------------
- .. class:: django.http.Http404()
- When you return an error such as :class:`~django.http.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. The default 404 view
- will pass one variable to the template: ``request_path``, which is the URL
- that resulted in the error.
- The ``page_not_found`` view should suffice for 99% of Web applications, but if
- you want to override it, 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`` in your root URLconf, and falling back to
- ``django.views.defaults.page_not_found`` if you did not define one.
- Four 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 404 view is passed a :class:`~django.template.RequestContext` and
- will have access to variables supplied by your
- :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting (e.g., ``MEDIA_URL``).
- * If :setting:`DEBUG` is set to ``True`` (in your settings module), then
- your 404 view will never be used, and your URLconf will be displayed
- instead, with some debug information.
- 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 500 view by looking for
- ``handler500`` in your root URLconf, and falling back to
- ``django.views.defaults.server_error`` if you did not define one.
- Two things to note about 500 views:
- * If you don't define your own 500 view — and simply use the default,
- which is recommended — you still have one obligation: you must create a
- ``500.html`` template in the root of your template directory.
- * If :setting:`DEBUG` is set to ``True`` (in your settings module), then
- your 500 view will never be used, and the traceback will be displayed
- instead, with some debug information.
|