123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- =============
- 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::
- 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::
- from django.http import HttpResponse, HttpResponseNotFound
- 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::
- from django.http import HttpResponse
- 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
- from django.shortcuts import render
- from polls.models import Poll
- def detail(request, poll_id):
- try:
- p = Poll.objects.get(pk=poll_id)
- except Poll.DoesNotExist:
- raise Http404("Poll does not exist")
- return render(request, 'polls/detail.html', {'poll': p})
- In order to show customized HTML when Django returns a 404, you can create an
- HTML template named ``404.html`` and place it in the top level of your
- template tree. This template will then be served when :setting:`DEBUG` is set
- to ``False``.
- When :setting:`DEBUG` is ``True``, you can provide a message to ``Http404`` and
- it will appear in the standard 404 debug template. Use these messages for
- debugging purposes; they generally aren't suitable for use in a production 404
- template.
- .. _customizing-error-views:
- Customizing error views
- =======================
- The default error views in Django should suffice for most Web applications,
- but can easily be overridden if you need any custom behavior. Simply specify
- the handlers as seen below in your URLconf (setting them anywhere else will
- have no effect).
- The :func:`~django.views.defaults.page_not_found` view is overridden by
- :data:`~django.conf.urls.handler404`::
- handler404 = 'mysite.views.my_custom_page_not_found_view'
- The :func:`~django.views.defaults.server_error` view is overridden by
- :data:`~django.conf.urls.handler500`::
- handler500 = 'mysite.views.my_custom_error_view'
- The :func:`~django.views.defaults.permission_denied` view is overridden by
- :data:`~django.conf.urls.handler403`::
- handler403 = 'mysite.views.my_custom_permission_denied_view'
- The :func:`~django.views.defaults.bad_request` view is overridden by
- :data:`~django.conf.urls.handler400`::
- handler400 = 'mysite.views.my_custom_bad_request_view'
|