diff options
Diffstat (limited to 'parts/django/docs/topics/http')
-rw-r--r-- | parts/django/docs/topics/http/_images/middleware.png | bin | 56301 -> 0 bytes | |||
-rw-r--r-- | parts/django/docs/topics/http/file-uploads.txt | 394 | ||||
-rw-r--r-- | parts/django/docs/topics/http/generic-views.txt | 5 | ||||
-rw-r--r-- | parts/django/docs/topics/http/index.txt | 15 | ||||
-rw-r--r-- | parts/django/docs/topics/http/middleware.txt | 179 | ||||
-rw-r--r-- | parts/django/docs/topics/http/sessions.txt | 529 | ||||
-rw-r--r-- | parts/django/docs/topics/http/shortcuts.txt | 229 | ||||
-rw-r--r-- | parts/django/docs/topics/http/urls.txt | 890 | ||||
-rw-r--r-- | parts/django/docs/topics/http/views.txt | 202 |
9 files changed, 0 insertions, 2443 deletions
diff --git a/parts/django/docs/topics/http/_images/middleware.png b/parts/django/docs/topics/http/_images/middleware.png Binary files differdeleted file mode 100644 index 505c70a..0000000 --- a/parts/django/docs/topics/http/_images/middleware.png +++ /dev/null diff --git a/parts/django/docs/topics/http/file-uploads.txt b/parts/django/docs/topics/http/file-uploads.txt deleted file mode 100644 index a06a1ca..0000000 --- a/parts/django/docs/topics/http/file-uploads.txt +++ /dev/null @@ -1,394 +0,0 @@ -============ -File Uploads -============ - -.. currentmodule:: django.core.files - -.. versionadded:: 1.0 - -When Django handles a file upload, the file data ends up placed in -:attr:`request.FILES <django.http.HttpRequest.FILES>` (for more on the -``request`` object see the documentation for :doc:`request and response objects -</ref/request-response>`). This document explains how files are stored on disk -and in memory, and how to customize the default behavior. - -Basic file uploads -================== - -Consider a simple form containing a :class:`~django.forms.FileField`:: - - from django import forms - - class UploadFileForm(forms.Form): - title = forms.CharField(max_length=50) - file = forms.FileField() - -A view handling this form will receive the file data in -:attr:`request.FILES <django.http.HttpRequest.FILES>`, which is a dictionary -containing a key for each :class:`~django.forms.FileField` (or -:class:`~django.forms.ImageField`, or other :class:`~django.forms.FileField` -subclass) in the form. So the data from the above form would -be accessible as ``request.FILES['file']``. - -Note that :attr:`request.FILES <django.http.HttpRequest.FILES>` will only -contain data if the request method was ``POST`` and the ``<form>`` that posted -the request has the attribute ``enctype="multipart/form-data"``. Otherwise, -``request.FILES`` will be empty. - -Most of the time, you'll simply pass the file data from ``request`` into the -form as described in :ref:`binding-uploaded-files`. This would look -something like:: - - from django.http import HttpResponseRedirect - from django.shortcuts import render_to_response - - # Imaginary function to handle an uploaded file. - from somewhere import handle_uploaded_file - - def upload_file(request): - if request.method == 'POST': - form = UploadFileForm(request.POST, request.FILES) - if form.is_valid(): - handle_uploaded_file(request.FILES['file']) - return HttpResponseRedirect('/success/url/') - else: - form = UploadFileForm() - return render_to_response('upload.html', {'form': form}) - -Notice that we have to pass :attr:`request.FILES <django.http.HttpRequest.FILES>` -into the form's constructor; this is how file data gets bound into a form. - -Handling uploaded files ------------------------ - -The final piece of the puzzle is handling the actual file data from -:attr:`request.FILES <django.http.HttpRequest.FILES>`. Each entry in this -dictionary is an ``UploadedFile`` object -- a simple wrapper around an uploaded -file. You'll usually use one of these methods to access the uploaded content: - - ``UploadedFile.read()`` - Read the entire uploaded data from the file. Be careful with this - method: if the uploaded file is huge it can overwhelm your system if you - try to read it into memory. You'll probably want to use ``chunks()`` - instead; see below. - - ``UploadedFile.multiple_chunks()`` - Returns ``True`` if the uploaded file is big enough to require - reading in multiple chunks. By default this will be any file - larger than 2.5 megabytes, but that's configurable; see below. - - ``UploadedFile.chunks()`` - A generator returning chunks of the file. If ``multiple_chunks()`` is - ``True``, you should use this method in a loop instead of ``read()``. - - In practice, it's often easiest simply to use ``chunks()`` all the time; - see the example below. - - ``UploadedFile.name`` - The name of the uploaded file (e.g. ``my_file.txt``). - - ``UploadedFile.size`` - The size, in bytes, of the uploaded file. - -There are a few other methods and attributes available on ``UploadedFile`` -objects; see `UploadedFile objects`_ for a complete reference. - -Putting it all together, here's a common way you might handle an uploaded file:: - - def handle_uploaded_file(f): - destination = open('some/file/name.txt', 'wb+') - for chunk in f.chunks(): - destination.write(chunk) - destination.close() - -Looping over ``UploadedFile.chunks()`` instead of using ``read()`` ensures that -large files don't overwhelm your system's memory. - -Where uploaded data is stored ------------------------------ - -Before you save uploaded files, the data needs to be stored somewhere. - -By default, if an uploaded file is smaller than 2.5 megabytes, Django will hold -the entire contents of the upload in memory. This means that saving the file -involves only a read from memory and a write to disk and thus is very fast. - -However, if an uploaded file is too large, Django will write the uploaded file -to a temporary file stored in your system's temporary directory. On a Unix-like -platform this means you can expect Django to generate a file called something -like ``/tmp/tmpzfp6I6.upload``. If an upload is large enough, you can watch this -file grow in size as Django streams the data onto disk. - -These specifics -- 2.5 megabytes; ``/tmp``; etc. -- are simply "reasonable -defaults". Read on for details on how you can customize or completely replace -upload behavior. - -Changing upload handler behavior --------------------------------- - -Three settings control Django's file upload behavior: - - :setting:`FILE_UPLOAD_MAX_MEMORY_SIZE` - The maximum size, in bytes, for files that will be uploaded into memory. - Files larger than :setting:`FILE_UPLOAD_MAX_MEMORY_SIZE` will be - streamed to disk. - - Defaults to 2.5 megabytes. - - :setting:`FILE_UPLOAD_TEMP_DIR` - The directory where uploaded files larger than - :setting:`FILE_UPLOAD_MAX_MEMORY_SIZE` will be stored. - - Defaults to your system's standard temporary directory (i.e. ``/tmp`` on - most Unix-like systems). - - :setting:`FILE_UPLOAD_PERMISSIONS` - The numeric mode (i.e. ``0644``) to set newly uploaded files to. For - more information about what these modes mean, see the `documentation for - os.chmod`_ - - If this isn't given or is ``None``, you'll get operating-system - dependent behavior. On most platforms, temporary files will have a mode - of ``0600``, and files saved from memory will be saved using the - system's standard umask. - - .. warning:: - - If you're not familiar with file modes, please note that the leading - ``0`` is very important: it indicates an octal number, which is the - way that modes must be specified. If you try to use ``644``, you'll - get totally incorrect behavior. - - **Always prefix the mode with a 0.** - - :setting:`FILE_UPLOAD_HANDLERS` - The actual handlers for uploaded files. Changing this setting allows - complete customization -- even replacement -- of Django's upload - process. See `upload handlers`_, below, for details. - - Defaults to:: - - ("django.core.files.uploadhandler.MemoryFileUploadHandler", - "django.core.files.uploadhandler.TemporaryFileUploadHandler",) - - Which means "try to upload to memory first, then fall back to temporary - files." - -.. _documentation for os.chmod: http://docs.python.org/library/os.html#os.chmod - -``UploadedFile`` objects -======================== - -.. class:: UploadedFile - -In addition to those inherited from :class:`File`, all ``UploadedFile`` objects -define the following methods/attributes: - - ``UploadedFile.content_type`` - The content-type header uploaded with the file (e.g. ``text/plain`` or - ``application/pdf``). Like any data supplied by the user, you shouldn't - trust that the uploaded file is actually this type. You'll still need to - validate that the file contains the content that the content-type header - claims -- "trust but verify." - - ``UploadedFile.charset`` - For ``text/*`` content-types, the character set (i.e. ``utf8``) supplied - by the browser. Again, "trust but verify" is the best policy here. - - ``UploadedFile.temporary_file_path()`` - Only files uploaded onto disk will have this method; it returns the full - path to the temporary uploaded file. - -.. note:: - - Like regular Python files, you can read the file line-by-line simply by - iterating over the uploaded file: - - .. code-block:: python - - for line in uploadedfile: - do_something_with(line) - - However, *unlike* standard Python files, :class:`UploadedFile` only - understands ``\n`` (also known as "Unix-style") line endings. If you know - that you need to handle uploaded files with different line endings, you'll - need to do so in your view. - -Upload Handlers -=============== - -When a user uploads a file, Django passes off the file data to an *upload -handler* -- a small class that handles file data as it gets uploaded. Upload -handlers are initially defined in the ``FILE_UPLOAD_HANDLERS`` setting, which -defaults to:: - - ("django.core.files.uploadhandler.MemoryFileUploadHandler", - "django.core.files.uploadhandler.TemporaryFileUploadHandler",) - -Together the ``MemoryFileUploadHandler`` and ``TemporaryFileUploadHandler`` -provide Django's default file upload behavior of reading small files into memory -and large ones onto disk. - -You can write custom handlers that customize how Django handles files. You -could, for example, use custom handlers to enforce user-level quotas, compress -data on the fly, render progress bars, and even send data to another storage -location directly without storing it locally. - -Modifying upload handlers on the fly ------------------------------------- - -Sometimes particular views require different upload behavior. In these cases, -you can override upload handlers on a per-request basis by modifying -``request.upload_handlers``. By default, this list will contain the upload -handlers given by ``FILE_UPLOAD_HANDLERS``, but you can modify the list as you -would any other list. - -For instance, suppose you've written a ``ProgressBarUploadHandler`` that -provides feedback on upload progress to some sort of AJAX widget. You'd add this -handler to your upload handlers like this:: - - request.upload_handlers.insert(0, ProgressBarUploadHandler()) - -You'd probably want to use ``list.insert()`` in this case (instead of -``append()``) because a progress bar handler would need to run *before* any -other handlers. Remember, the upload handlers are processed in order. - -If you want to replace the upload handlers completely, you can just assign a new -list:: - - request.upload_handlers = [ProgressBarUploadHandler()] - -.. note:: - - You can only modify upload handlers *before* accessing - ``request.POST`` or ``request.FILES`` -- it doesn't make sense to - change upload handlers after upload handling has already - started. If you try to modify ``request.upload_handlers`` after - reading from ``request.POST`` or ``request.FILES`` Django will - throw an error. - - Thus, you should always modify uploading handlers as early in your view as - possible. - - Also, ``request.POST`` is accessed by - :class:`~django.middleware.csrf.CsrfViewMiddleware` which is enabled by - default. This means you will probably need to use - :func:`~django.views.decorators.csrf.csrf_exempt` on your view to allow you - to change the upload handlers. Assuming you do need CSRF protection, you - will then need to use :func:`~django.views.decorators.csrf.csrf_protect` on - the function that actually processes the request. Note that this means that - the handlers may start receiving the file upload before the CSRF checks have - been done. Example code: - - .. code-block:: python - - from django.views.decorators.csrf import csrf_exempt, csrf_protect - - @csrf_exempt - def upload_file_view(request): - request.upload_handlers.insert(0, ProgressBarUploadHandler()) - return _upload_file_view(request) - - @csrf_protect - def _upload_file_view(request): - ... # Process request - - -Writing custom upload handlers ------------------------------- - -All file upload handlers should be subclasses of -``django.core.files.uploadhandler.FileUploadHandler``. You can define upload -handlers wherever you wish. - -Required methods -~~~~~~~~~~~~~~~~ - -Custom file upload handlers **must** define the following methods: - - ``FileUploadHandler.receive_data_chunk(self, raw_data, start)`` - Receives a "chunk" of data from the file upload. - - ``raw_data`` is a byte string containing the uploaded data. - - ``start`` is the position in the file where this ``raw_data`` chunk - begins. - - The data you return will get fed into the subsequent upload handlers' - ``receive_data_chunk`` methods. In this way, one handler can be a - "filter" for other handlers. - - Return ``None`` from ``receive_data_chunk`` to sort-circuit remaining - upload handlers from getting this chunk.. This is useful if you're - storing the uploaded data yourself and don't want future handlers to - store a copy of the data. - - If you raise a ``StopUpload`` or a ``SkipFile`` exception, the upload - will abort or the file will be completely skipped. - - ``FileUploadHandler.file_complete(self, file_size)`` - Called when a file has finished uploading. - - The handler should return an ``UploadedFile`` object that will be stored - in ``request.FILES``. Handlers may also return ``None`` to indicate that - the ``UploadedFile`` object should come from subsequent upload handlers. - -Optional methods -~~~~~~~~~~~~~~~~ - -Custom upload handlers may also define any of the following optional methods or -attributes: - - ``FileUploadHandler.chunk_size`` - Size, in bytes, of the "chunks" Django should store into memory and feed - into the handler. That is, this attribute controls the size of chunks - fed into ``FileUploadHandler.receive_data_chunk``. - - For maximum performance the chunk sizes should be divisible by ``4`` and - should not exceed 2 GB (2\ :sup:`31` bytes) in size. When there are - multiple chunk sizes provided by multiple handlers, Django will use the - smallest chunk size defined by any handler. - - The default is 64*2\ :sup:`10` bytes, or 64 KB. - - ``FileUploadHandler.new_file(self, field_name, file_name, content_type, content_length, charset)`` - Callback signaling that a new file upload is starting. This is called - before any data has been fed to any upload handlers. - - ``field_name`` is a string name of the file ``<input>`` field. - - ``file_name`` is the unicode filename that was provided by the browser. - - ``content_type`` is the MIME type provided by the browser -- E.g. - ``'image/jpeg'``. - - ``content_length`` is the length of the image given by the browser. - Sometimes this won't be provided and will be ``None``. - - ``charset`` is the character set (i.e. ``utf8``) given by the browser. - Like ``content_length``, this sometimes won't be provided. - - This method may raise a ``StopFutureHandlers`` exception to prevent - future handlers from handling this file. - - ``FileUploadHandler.upload_complete(self)`` - Callback signaling that the entire upload (all files) has completed. - - ``FileUploadHandler.handle_raw_input(self, input_data, META, content_length, boundary, encoding)`` - Allows the handler to completely override the parsing of the raw - HTTP input. - - ``input_data`` is a file-like object that supports ``read()``-ing. - - ``META`` is the same object as ``request.META``. - - ``content_length`` is the length of the data in ``input_data``. Don't - read more than ``content_length`` bytes from ``input_data``. - - ``boundary`` is the MIME boundary for this request. - - ``encoding`` is the encoding of the request. - - Return ``None`` if you want upload handling to continue, or a tuple of - ``(POST, FILES)`` if you want to return the new data structures suitable - for the request directly. diff --git a/parts/django/docs/topics/http/generic-views.txt b/parts/django/docs/topics/http/generic-views.txt deleted file mode 100644 index 15f895e..0000000 --- a/parts/django/docs/topics/http/generic-views.txt +++ /dev/null @@ -1,5 +0,0 @@ -============= -Generic views -============= - -See :doc:`/ref/generic-views`. diff --git a/parts/django/docs/topics/http/index.txt b/parts/django/docs/topics/http/index.txt deleted file mode 100644 index 5ef776d..0000000 --- a/parts/django/docs/topics/http/index.txt +++ /dev/null @@ -1,15 +0,0 @@ -Handling HTTP requests -====================== - -Information on handling HTTP requests in Django: - -.. toctree:: - :maxdepth: 1 - - urls - views - file-uploads - shortcuts - generic-views - middleware - sessions diff --git a/parts/django/docs/topics/http/middleware.txt b/parts/django/docs/topics/http/middleware.txt deleted file mode 100644 index d376c6b..0000000 --- a/parts/django/docs/topics/http/middleware.txt +++ /dev/null @@ -1,179 +0,0 @@ -========== -Middleware -========== - -Middleware is a framework of hooks into Django's request/response processing. -It's a light, low-level "plugin" system for globally altering Django's input -and/or output. - -Each middleware component is responsible for doing some specific function. For -example, Django includes a middleware component, ``XViewMiddleware``, that adds -an ``"X-View"`` HTTP header to every response to a ``HEAD`` request. - -This document explains how middleware works, how you activate middleware, and -how to write your own middleware. Django ships with some built-in middleware -you can use right out of the box; they're documented in the :doc:`built-in -middleware reference </ref/middleware>`. - -Activating middleware -===================== - -To activate a middleware component, add it to the :setting:`MIDDLEWARE_CLASSES` -list in your Django settings. In :setting:`MIDDLEWARE_CLASSES`, each middleware -component is represented by a string: the full Python path to the middleware's -class name. For example, here's the default :setting:`MIDDLEWARE_CLASSES` -created by :djadmin:`django-admin.py startproject <startproject>`:: - - MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - ) - -During the request phases (:meth:`process_request` and :meth:`process_view` -middleware), Django applies middleware in the order it's defined in -:setting:`MIDDLEWARE_CLASSES`, top-down. During the response phases -(:meth:`process_response` and :meth:`process_exception` middleware), the -classes are applied in reverse order, from the bottom up. You can think of it -like an onion: each middleware class is a "layer" that wraps the view: - -.. image:: _images/middleware.png - :width: 502 - :height: 417 - :alt: Middleware application order. - -A Django installation doesn't require any middleware -- e.g., -:setting:`MIDDLEWARE_CLASSES` can be empty, if you'd like -- but it's strongly -suggested that you at least use -:class:`~django.middleware.common.CommonMiddleware`. - -Writing your own middleware -=========================== - -Writing your own middleware is easy. Each middleware component is a single -Python class that defines one or more of the following methods: - -.. _request-middleware: - -``process_request`` -------------------- - -.. method:: process_request(self, request) - -``request`` is an :class:`~django.http.HttpRequest` object. This method is -called on each request, before Django decides which view to execute. - -``process_request()`` should return either ``None`` or an -:class:`~django.http.HttpResponse` object. If it returns ``None``, Django will -continue processing this request, executing any other middleware and, then, the -appropriate view. If it returns an :class:`~django.http.HttpResponse` object, -Django won't bother calling ANY other request, view or exception middleware, or -the appropriate view; it'll return that :class:`~django.http.HttpResponse`. -Response middleware is always called on every response. - -.. _view-middleware: - -``process_view`` ----------------- - -.. method:: process_view(self, request, view_func, view_args, view_kwargs) - -``request`` is an :class:`~django.http.HttpRequest` object. ``view_func`` is -the Python function that Django is about to use. (It's the actual function -object, not the name of the function as a string.) ``view_args`` is a list of -positional arguments that will be passed to the view, and ``view_kwargs`` is a -dictionary of keyword arguments that will be passed to the view. Neither -``view_args`` nor ``view_kwargs`` include the first view argument -(``request``). - -``process_view()`` is called just before Django calls the view. It should -return either ``None`` or an :class:`~django.http.HttpResponse` object. If it -returns ``None``, Django will continue processing this request, executing any -other ``process_view()`` middleware and, then, the appropriate view. If it -returns an :class:`~django.http.HttpResponse` object, Django won't bother -calling ANY other request, view or exception middleware, or the appropriate -view; it'll return that :class:`~django.http.HttpResponse`. Response -middleware is always called on every response. - -.. _response-middleware: - -``process_response`` --------------------- - -.. method:: process_response(self, request, response) - -``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is the -:class:`~django.http.HttpResponse` object returned by a Django view. - -``process_response()`` must return an :class:`~django.http.HttpResponse` -object. It could alter the given ``response``, or it could create and return a -brand-new :class:`~django.http.HttpResponse`. - -Unlike the ``process_request()`` and ``process_view()`` methods, the -``process_response()`` method is always called, even if the ``process_request()`` -and ``process_view()`` methods of the same middleware class were skipped because -an earlier middleware method returned an :class:`~django.http.HttpResponse` -(this means that your ``process_response()`` method cannot rely on setup done in -``process_request()``, for example). In addition, during the response phase the -classes are applied in reverse order, from the bottom up. This means classes -defined at the end of :setting:`MIDDLEWARE_CLASSES` will be run first. - -.. _exception-middleware: - -``process_exception`` ---------------------- - -.. method:: process_exception(self, request, exception) - -``request`` is an :class:`~django.http.HttpRequest` object. ``exception`` is an -``Exception`` object raised by the view function. - -Django calls ``process_exception()`` when a view raises an exception. -``process_exception()`` should return either ``None`` or an -:class:`~django.http.HttpResponse` object. If it returns an -:class:`~django.http.HttpResponse` object, the response will be returned to -the browser. Otherwise, default exception handling kicks in. - -Again, middleware are run in reverse order during the response phase, which -includes ``process_exception``. If an exception middleware return a response, -the middleware classes above that middleware will not be called at all. - -``__init__`` ------------- - -Most middleware classes won't need an initializer since middleware classes are -essentially placeholders for the ``process_*`` methods. If you do need some -global state you may use ``__init__`` to set up. However, keep in mind a couple -of caveats: - - * Django initializes your middleware without any arguments, so you can't - define ``__init__`` as requiring any arguments. - - * Unlike the ``process_*`` methods which get called once per request, - ``__init__`` gets called only *once*, when the Web server starts up. - -Marking middleware as unused -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -It's sometimes useful to determine at run-time whether a piece of middleware -should be used. In these cases, your middleware's ``__init__`` method may raise -``django.core.exceptions.MiddlewareNotUsed``. Django will then remove that -piece of middleware from the middleware process. - -Guidelines ----------- - - * Middleware classes don't have to subclass anything. - - * The middleware class can live anywhere on your Python path. All Django - cares about is that the :setting:`MIDDLEWARE_CLASSES` setting includes - the path to it. - - * Feel free to look at :doc:`Django's available middleware - </ref/middleware>` for examples. - - * If you write a middleware component that you think would be useful to - other people, contribute to the community! :doc:`Let us know - </internals/contributing>`, and we'll consider adding it to Django. diff --git a/parts/django/docs/topics/http/sessions.txt b/parts/django/docs/topics/http/sessions.txt deleted file mode 100644 index 8a0f0d4..0000000 --- a/parts/django/docs/topics/http/sessions.txt +++ /dev/null @@ -1,529 +0,0 @@ -=================== -How to use sessions -=================== - -.. module:: django.contrib.sessions - :synopsis: Provides session management for Django projects. - -Django provides full support for anonymous sessions. The session framework lets -you store and retrieve arbitrary data on a per-site-visitor basis. It stores -data on the server side and abstracts the sending and receiving of cookies. -Cookies contain a session ID -- not the data itself. - -Enabling sessions -================= - -Sessions are implemented via a piece of :doc:`middleware </ref/middleware>`. - -To enable session functionality, do the following: - - * Edit the ``MIDDLEWARE_CLASSES`` setting and make sure - ``MIDDLEWARE_CLASSES`` contains ``'django.contrib.sessions.middleware.SessionMiddleware'``. - The default ``settings.py`` created by ``django-admin.py startproject`` has - ``SessionMiddleware`` activated. - -If you don't want to use sessions, you might as well remove the -``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES`` and ``'django.contrib.sessions'`` -from your ``INSTALLED_APPS``. It'll save you a small bit of overhead. - -Configuring the session engine -============================== - -.. versionadded:: 1.0 - -By default, Django stores sessions in your database (using the model -``django.contrib.sessions.models.Session``). Though this is convenient, in -some setups it's faster to store session data elsewhere, so Django can be -configured to store session data on your filesystem or in your cache. - -Using database-backed sessions ------------------------------- - -If you want to use a database-backed session, you need to add -``'django.contrib.sessions'`` to your ``INSTALLED_APPS`` setting. - -Once you have configured your installation, run ``manage.py syncdb`` -to install the single database table that stores session data. - -Using cached sessions ---------------------- - -For better performance, you may want to use a cache-based session backend. - -.. versionchanged:: 1.1 - Django 1.0 did not include the ``cached_db`` session backend. - -To store session data using Django's cache system, you'll first need to make -sure you've configured your cache; see the :doc:`cache documentation -</topics/cache>` for details. - -.. warning:: - - You should only use cache-based sessions if you're using the Memcached - cache backend. The local-memory cache backend doesn't retain data long - enough to be a good choice, and it'll be faster to use file or database - sessions directly instead of sending everything through the file or - database cache backends. - -Once your cache is configured, you've got two choices for how to store data in -the cache: - - * Set :setting:`SESSION_ENGINE` to - ``"django.contrib.sessions.backends.cache"`` for a simple caching session - store. Session data will be stored directly your cache. However, session - data may not be persistent: cached data can be evicted if the cache fills - up or if the cache server is restarted. - - * For persistent, cached data, set :setting:`SESSION_ENGINE` to - ``"django.contrib.sessions.backends.cached_db"``. This uses a - write-through cache -- every write to the cache will also be written to - the database. Session reads only use the database if the data is not - already in the cache. - -Both session stores are quite fast, but the simple cache is faster because it -disregards persistence. In most cases, the ``cached_db`` backend will be fast -enough, but if you need that last bit of performance, and are willing to let -session data be expunged from time to time, the ``cache`` backend is for you. - -If you use the ``cached_db`` session backend, you also need to follow the -configuration instructions for the `using database-backed sessions`_. - -Using file-based sessions -------------------------- - -To use file-based sessions, set the ``SESSION_ENGINE`` setting to -``"django.contrib.sessions.backends.file"``. - -You might also want to set the ``SESSION_FILE_PATH`` setting (which defaults -to output from ``tempfile.gettempdir()``, most likely ``/tmp``) to control -where Django stores session files. Be sure to check that your Web server has -permissions to read and write to this location. - - -Using sessions in views -======================= - -When ``SessionMiddleware`` is activated, each ``HttpRequest`` object -- the -first argument to any Django view function -- will have a ``session`` -attribute, which is a dictionary-like object. You can read it and write to it. - -A session object has the following standard dictionary methods: - - * ``__getitem__(key)`` - - Example: ``fav_color = request.session['fav_color']`` - - * ``__setitem__(key, value)`` - - Example: ``request.session['fav_color'] = 'blue'`` - - * ``__delitem__(key)`` - - Example: ``del request.session['fav_color']``. This raises ``KeyError`` - if the given ``key`` isn't already in the session. - - * ``__contains__(key)`` - - Example: ``'fav_color' in request.session`` - - * ``get(key, default=None)`` - - Example: ``fav_color = request.session.get('fav_color', 'red')`` - - * ``keys()`` - - * ``items()`` - - * ``setdefault()`` - - * ``clear()`` - -.. versionadded:: 1.0 - ``setdefault()`` and ``clear()`` are new in this version. - -It also has these methods: - - * ``flush()`` - - .. versionadded:: 1.0 - - Delete the current session data from the session and regenerate the - session key value that is sent back to the user in the cookie. This is - used if you want to ensure that the previous session data can't be - accessed again from the user's browser (for example, the - :func:`django.contrib.auth.logout()` function calls it). - - * ``set_test_cookie()`` - - Sets a test cookie to determine whether the user's browser supports - cookies. Due to the way cookies work, you won't be able to test this - until the user's next page request. See `Setting test cookies`_ below for - more information. - - * ``test_cookie_worked()`` - - Returns either ``True`` or ``False``, depending on whether the user's - browser accepted the test cookie. Due to the way cookies work, you'll - have to call ``set_test_cookie()`` on a previous, separate page request. - See `Setting test cookies`_ below for more information. - - * ``delete_test_cookie()`` - - Deletes the test cookie. Use this to clean up after yourself. - - * ``set_expiry(value)`` - - .. versionadded:: 1.0 - - Sets the expiration time for the session. You can pass a number of - different values: - - * If ``value`` is an integer, the session will expire after that - many seconds of inactivity. For example, calling - ``request.session.set_expiry(300)`` would make the session expire - in 5 minutes. - - * If ``value`` is a ``datetime`` or ``timedelta`` object, the - session will expire at that specific date/time. - - * If ``value`` is ``0``, the user's session cookie will expire - when the user's Web browser is closed. - - * If ``value`` is ``None``, the session reverts to using the global - session expiry policy. - - Reading a session is not considered activity for expiration - purposes. Session expiration is computed from the last time the - session was *modified*. - - * ``get_expiry_age()`` - - .. versionadded:: 1.0 - - Returns the number of seconds until this session expires. For sessions - with no custom expiration (or those set to expire at browser close), this - will equal ``settings.SESSION_COOKIE_AGE``. - - * ``get_expiry_date()`` - - .. versionadded:: 1.0 - - Returns the date this session will expire. For sessions with no custom - expiration (or those set to expire at browser close), this will equal the - date ``settings.SESSION_COOKIE_AGE`` seconds from now. - - * ``get_expire_at_browser_close()`` - - .. versionadded:: 1.0 - - Returns either ``True`` or ``False``, depending on whether the user's - session cookie will expire when the user's Web browser is closed. - -You can edit ``request.session`` at any point in your view. You can edit it -multiple times. - -Session object guidelines -------------------------- - - * Use normal Python strings as dictionary keys on ``request.session``. This - is more of a convention than a hard-and-fast rule. - - * Session dictionary keys that begin with an underscore are reserved for - internal use by Django. - - * Don't override ``request.session`` with a new object, and don't access or - set its attributes. Use it like a Python dictionary. - -Examples --------- - -This simplistic view sets a ``has_commented`` variable to ``True`` after a user -posts a comment. It doesn't let a user post a comment more than once:: - - def post_comment(request, new_comment): - if request.session.get('has_commented', False): - return HttpResponse("You've already commented.") - c = comments.Comment(comment=new_comment) - c.save() - request.session['has_commented'] = True - return HttpResponse('Thanks for your comment!') - -This simplistic view logs in a "member" of the site:: - - def login(request): - m = Member.objects.get(username=request.POST['username']) - if m.password == request.POST['password']: - request.session['member_id'] = m.id - return HttpResponse("You're logged in.") - else: - return HttpResponse("Your username and password didn't match.") - -...And this one logs a member out, according to ``login()`` above:: - - def logout(request): - try: - del request.session['member_id'] - except KeyError: - pass - return HttpResponse("You're logged out.") - -The standard ``django.contrib.auth.logout()`` function actually does a bit -more than this to prevent inadvertent data leakage. It calls -``request.session.flush()``. We are using this example as a demonstration of -how to work with session objects, not as a full ``logout()`` implementation. - -Setting test cookies -==================== - -As a convenience, Django provides an easy way to test whether the user's -browser accepts cookies. Just call ``request.session.set_test_cookie()`` in a -view, and call ``request.session.test_cookie_worked()`` in a subsequent view -- -not in the same view call. - -This awkward split between ``set_test_cookie()`` and ``test_cookie_worked()`` -is necessary due to the way cookies work. When you set a cookie, you can't -actually tell whether a browser accepted it until the browser's next request. - -It's good practice to use ``delete_test_cookie()`` to clean up after yourself. -Do this after you've verified that the test cookie worked. - -Here's a typical usage example:: - - def login(request): - if request.method == 'POST': - if request.session.test_cookie_worked(): - request.session.delete_test_cookie() - return HttpResponse("You're logged in.") - else: - return HttpResponse("Please enable cookies and try again.") - request.session.set_test_cookie() - return render_to_response('foo/login_form.html') - -Using sessions out of views -=========================== - -.. versionadded:: 1.0 - -An API is available to manipulate session data outside of a view:: - - >>> from django.contrib.sessions.backends.db import SessionStore - >>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead') - >>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10) - >>> s['last_login'] - datetime.datetime(2005, 8, 20, 13, 35, 0) - >>> s.save() - -If you're using the ``django.contrib.sessions.backends.db`` backend, each -session is just a normal Django model. The ``Session`` model is defined in -``django/contrib/sessions/models.py``. Because it's a normal model, you can -access sessions using the normal Django database API:: - - >>> from django.contrib.sessions.models import Session - >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead') - >>> s.expire_date - datetime.datetime(2005, 8, 20, 13, 35, 12) - -Note that you'll need to call ``get_decoded()`` to get the session dictionary. -This is necessary because the dictionary is stored in an encoded format:: - - >>> s.session_data - 'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...' - >>> s.get_decoded() - {'user_id': 42} - -When sessions are saved -======================= - -By default, Django only saves to the session database when the session has been -modified -- that is if any of its dictionary values have been assigned or -deleted:: - - # Session is modified. - request.session['foo'] = 'bar' - - # Session is modified. - del request.session['foo'] - - # Session is modified. - request.session['foo'] = {} - - # Gotcha: Session is NOT modified, because this alters - # request.session['foo'] instead of request.session. - request.session['foo']['bar'] = 'baz' - -In the last case of the above example, we can tell the session object -explicitly that it has been modified by setting the ``modified`` attribute on -the session object:: - - request.session.modified = True - -To change this default behavior, set the ``SESSION_SAVE_EVERY_REQUEST`` setting -to ``True``. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, Django will save -the session to the database on every single request. - -Note that the session cookie is only sent when a session has been created or -modified. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, the session cookie -will be sent on every request. - -Similarly, the ``expires`` part of a session cookie is updated each time the -session cookie is sent. - -Browser-length sessions vs. persistent sessions -=============================================== - -You can control whether the session framework uses browser-length sessions vs. -persistent sessions with the ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` setting. - -By default, ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``False``, which -means session cookies will be stored in users' browsers for as long as -``SESSION_COOKIE_AGE``. Use this if you don't want people to have to log in -every time they open a browser. - -If ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``True``, Django will use -browser-length cookies -- cookies that expire as soon as the user closes his or -her browser. Use this if you want people to have to log in every time they open -a browser. - -.. versionadded:: 1.0 - -This setting is a global default and can be overwritten at a per-session level -by explicitly calling ``request.session.set_expiry()`` as described above in -`using sessions in views`_. - -Clearing the session table -========================== - -If you're using the database backend, note that session data can accumulate in -the ``django_session`` database table and Django does *not* provide automatic -purging. Therefore, it's your job to purge expired sessions on a regular basis. - -To understand this problem, consider what happens when a user uses a session. -When a user logs in, Django adds a row to the ``django_session`` database -table. Django updates this row each time the session data changes. If the user -logs out manually, Django deletes the row. But if the user does *not* log out, -the row never gets deleted. - -Django provides a sample clean-up script: ``django-admin.py cleanup``. -That script deletes any session in the session table whose ``expire_date`` is -in the past -- but your application may have different requirements. - -Settings -======== - -A few :doc:`Django settings </ref/settings>` give you control over session behavior: - -SESSION_ENGINE --------------- - -.. versionadded:: 1.0 - -.. versionchanged:: 1.1 - The ``cached_db`` backend was added - -Default: ``django.contrib.sessions.backends.db`` - -Controls where Django stores session data. Valid values are: - - * ``'django.contrib.sessions.backends.db'`` - * ``'django.contrib.sessions.backends.file'`` - * ``'django.contrib.sessions.backends.cache'`` - * ``'django.contrib.sessions.backends.cached_db'`` - -See `configuring the session engine`_ for more details. - -SESSION_FILE_PATH ------------------ - -.. versionadded:: 1.0 - -Default: ``/tmp/`` - -If you're using file-based session storage, this sets the directory in -which Django will store session data. - -SESSION_COOKIE_AGE ------------------- - -Default: ``1209600`` (2 weeks, in seconds) - -The age of session cookies, in seconds. - -SESSION_COOKIE_DOMAIN ---------------------- - -Default: ``None`` - -The domain to use for session cookies. Set this to a string such as -``".lawrence.com"`` (note the leading dot!) for cross-domain cookies, or use -``None`` for a standard domain cookie. - -SESSION_COOKIE_NAME -------------------- - -Default: ``'sessionid'`` - -The name of the cookie to use for sessions. This can be whatever you want. - -SESSION_COOKIE_PATH -------------------- - -.. versionadded:: 1.0 - -Default: ``'/'`` - -The path set on the session cookie. This should either match the URL path of -your Django installation or be parent of that path. - -This is useful if you have multiple Django instances running under the same -hostname. They can use different cookie paths, and each instance will only see -its own session cookie. - -SESSION_COOKIE_SECURE ---------------------- - -Default: ``False`` - -Whether to use a secure cookie for the session cookie. If this is set to -``True``, the cookie will be marked as "secure," which means browsers may -ensure that the cookie is only sent under an HTTPS connection. - -SESSION_EXPIRE_AT_BROWSER_CLOSE -------------------------------- - -Default: ``False`` - -Whether to expire the session when the user closes his or her browser. See -"Browser-length sessions vs. persistent sessions" above. - -SESSION_SAVE_EVERY_REQUEST --------------------------- - -Default: ``False`` - -Whether to save the session data on every request. If this is ``False`` -(default), then the session data will only be saved if it has been modified -- -that is, if any of its dictionary values have been assigned or deleted. - -.. _Django settings: ../settings/ - -Technical details -================= - - * The session dictionary should accept any pickleable Python object. See - `the pickle module`_ for more information. - - * Session data is stored in a database table named ``django_session`` . - - * Django only sends a cookie if it needs to. If you don't set any session - data, it won't send a session cookie. - -.. _`the pickle module`: http://docs.python.org/library/pickle.html - -Session IDs in URLs -=================== - -The Django sessions framework is entirely, and solely, cookie-based. It does -not fall back to putting session IDs in URLs as a last resort, as PHP does. -This is an intentional design decision. Not only does that behavior make URLs -ugly, it makes your site vulnerable to session-ID theft via the "Referer" -header. diff --git a/parts/django/docs/topics/http/shortcuts.txt b/parts/django/docs/topics/http/shortcuts.txt deleted file mode 100644 index 315460e..0000000 --- a/parts/django/docs/topics/http/shortcuts.txt +++ /dev/null @@ -1,229 +0,0 @@ -========================= -Django shortcut functions -========================= - -.. module:: django.shortcuts - :synopsis: - Convience shortcuts that spam multiple levels of Django's MVC stack. - -.. index:: shortcuts - -The package ``django.shortcuts`` collects helper functions and classes that -"span" multiple levels of MVC. In other words, these functions/classes -introduce controlled coupling for convenience's sake. - -``render_to_response`` -====================== - -.. function:: render_to_response(template[, dictionary][, context_instance][, mimetype]) - - Renders a given template with a given context dictionary and returns an - :class:`~django.http.HttpResponse` object with that rendered text. - -Required arguments ------------------- - -``template`` - The full name of a template to use or sequence of template names. If a - sequence is given, the first template that exists will be used. See the - :ref:`template loader documentation <ref-templates-api-the-python-api>` - for more information on how templates are found. - -Optional arguments ------------------- - -``dictionary`` - A dictionary of values to add to the template context. By default, this - is an empty dictionary. If a value in the dictionary is callable, the - view will call it just before rendering the template. - -``context_instance`` - The context instance to render the template with. By default, the template - will be rendered with a :class:`~django.template.Context` instance (filled - with values from ``dictionary``). If you need to use :ref:`context - processors <subclassing-context-requestcontext>`, render the template with - a :class:`~django.template.RequestContext` instance instead. Your code - might look something like this:: - - return render_to_response('my_template.html', - my_data_dictionary, - context_instance=RequestContext(request)) - -``mimetype`` - The MIME type to use for the resulting document. Defaults to the value of - the :setting:`DEFAULT_CONTENT_TYPE` setting. - -Example -------- - -The following example renders the template ``myapp/index.html`` with the -MIME type ``application/xhtml+xml``:: - - from django.shortcuts import render_to_response - - def my_view(request): - # View code here... - return render_to_response('myapp/index.html', {"foo": "bar"}, - mimetype="application/xhtml+xml") - -This example is equivalent to:: - - from django.http import HttpResponse - from django.template import Context, loader - - def my_view(request): - # View code here... - t = loader.get_template('myapp/template.html') - c = Context({'foo': 'bar'}) - return HttpResponse(t.render(c), - mimetype="application/xhtml+xml") - -``redirect`` -============ - -.. function:: redirect(to[, permanent=False], *args, **kwargs) - - .. versionadded:: 1.1 - - Returns an :class:`~django.http.HttpResponseRedirect` to the appropriate URL - for the arguments passed. - - The arguments could be: - - * A model: the model's `get_absolute_url()` function will be called. - - * A view name, possibly with arguments: `urlresolvers.reverse()` will - be used to reverse-resolve the name. - - * A URL, which will be used as-is for the redirect location. - - By default issues a temporary redirect; pass ``permanent=True`` to issue a - permanent redirect - -Examples --------- - -You can use the :func:`redirect` function in a number of ways. - - 1. By passing some object; that object's - :meth:`~django.db.models.Model.get_absolute_url` method will be called - to figure out the redirect URL:: - - def my_view(request): - ... - object = MyModel.objects.get(...) - return redirect(object) - - 2. By passing the name of a view and optionally some positional or - keyword arguments; the URL will be reverse resolved using the - :func:`~django.core.urlresolvers.reverse` method:: - - def my_view(request): - ... - return redirect('some-view-name', foo='bar') - - 3. By passing a hardcoded URL to redirect to:: - - def my_view(request): - ... - return redirect('/some/url/') - - This also works with full URLs:: - - def my_view(request): - ... - return redirect('http://example.com/') - -By default, :func:`redirect` returns a temporary redirect. All of the above -forms accept a ``permanent`` argument; if set to ``True`` a permanent redirect -will be returned:: - - def my_view(request): - ... - object = MyModel.objects.get(...) - return redirect(object, permanent=True) - -``get_object_or_404`` -===================== - -.. function:: get_object_or_404(klass, *args, **kwargs) - - Calls :meth:`~django.db.models.QuerySet.get()` on a given model manager, - but it raises :class:`~django.http.Http404` instead of the model's - :class:`~django.core.exceptions.DoesNotExist` exception. - -Required arguments ------------------- - -``klass`` - A :class:`~django.db.models.Model`, :class:`~django.db.models.Manager` or - :class:`~django.db.models.QuerySet` instance from which to get the object. - -``**kwargs`` - Lookup parameters, which should be in the format accepted by ``get()`` and - ``filter()``. - -Example -------- - -The following example gets the object with the primary key of 1 from -``MyModel``:: - - from django.shortcuts import get_object_or_404 - - def my_view(request): - my_object = get_object_or_404(MyModel, pk=1) - -This example is equivalent to:: - - from django.http import Http404 - - def my_view(request): - try: - my_object = MyModel.objects.get(pk=1) - except MyModel.DoesNotExist: - raise Http404 - -Note: As with ``get()``, a -:class:`~django.core.exceptions.MultipleObjectsReturned` exception -will be raised if more than one object is found. - -``get_list_or_404`` -=================== - -.. function:: get_list_or_404(klass, *args, **kwargs) - - Returns the result of :meth:`~django.db.models.QuerySet.filter()` on a - given model manager, raising :class:`~django.http.Http404` if the resulting - list is empty. - -Required arguments ------------------- - -``klass`` - A :class:`~django.db.models.Model`, :class:`~django.db.models.Manager` or - :class:`~django.db.models.query.QuerySet` instance from which to get the - list. - -``**kwargs`` - Lookup parameters, which should be in the format accepted by ``get()`` and - ``filter()``. - -Example -------- - -The following example gets all published objects from ``MyModel``:: - - from django.shortcuts import get_list_or_404 - - def my_view(request): - my_objects = get_list_or_404(MyModel, published=True) - -This example is equivalent to:: - - from django.http import Http404 - - def my_view(request): - my_objects = list(MyModel.objects.filter(published=True)) - if not my_objects: - raise Http404 diff --git a/parts/django/docs/topics/http/urls.txt b/parts/django/docs/topics/http/urls.txt deleted file mode 100644 index 2361297..0000000 --- a/parts/django/docs/topics/http/urls.txt +++ /dev/null @@ -1,890 +0,0 @@ -============== -URL dispatcher -============== - -.. module:: django.core.urlresolvers - -A clean, elegant URL scheme is an important detail in a high-quality Web -application. Django lets you design URLs however you want, with no framework -limitations. - -There's no ``.php`` or ``.cgi`` required, and certainly none of that -``0,2097,1-1-1928,00`` nonsense. - -See `Cool URIs don't change`_, by World Wide Web creator Tim Berners-Lee, for -excellent arguments on why URLs should be clean and usable. - -.. _Cool URIs don't change: http://www.w3.org/Provider/Style/URI - -Overview -======== - -To design URLs for an app, you create a Python module informally called a -**URLconf** (URL configuration). This module is pure Python code and -is a simple mapping between URL patterns (as simple regular expressions) to -Python callback functions (your views). - -This mapping can be as short or as long as needed. It can reference other -mappings. And, because it's pure Python code, it can be constructed -dynamically. - -.. _how-django-processes-a-request: - -How Django processes a request -============================== - -When a user requests a page from your Django-powered site, this is the -algorithm the system follows to determine which Python code to execute: - - 1. Django determines the root URLconf module to use. Ordinarily, - this is the value of the :setting:`ROOT_URLCONF` setting, but if the incoming - ``HttpRequest`` object has an attribute called ``urlconf`` (set by - middleware :ref:`request processing <request-middleware>`), its value - will be used in place of the :setting:`ROOT_URLCONF` setting. - - 2. Django loads that Python module and looks for the variable - ``urlpatterns``. This should be a Python list, in the format returned by - the function :func:`django.conf.urls.defaults.patterns`. - - 3. Django runs through each URL pattern, in order, and stops at the first - one that matches the requested URL. - - 4. Once one of the regexes matches, Django imports and calls the given - view, which is a simple Python function. The view gets passed an - :class:`~django.http.HttpRequest` as its first argument and any values - captured in the regex as remaining arguments. - -Example -======= - -Here's a sample URLconf:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('', - (r'^articles/2003/$', 'news.views.special_case_2003'), - (r'^articles/(\d{4})/$', 'news.views.year_archive'), - (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'), - (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'), - ) - -Notes: - - * ``from django.conf.urls.defaults import *`` makes the ``patterns()`` - function available. - - * To capture a value from the URL, just put parenthesis around it. - - * There's no need to add a leading slash, because every URL has that. For - example, it's ``^articles``, not ``^/articles``. - - * The ``'r'`` in front of each regular expression string is optional but - recommended. It tells Python that a string is "raw" -- that nothing in - the string should be escaped. See `Dive Into Python's explanation`_. - -Example requests: - - * A request to ``/articles/2005/03/`` would match the third entry in the - list. Django would call the function - ``news.views.month_archive(request, '2005', '03')``. - - * ``/articles/2005/3/`` would not match any URL patterns, because the - third entry in the list requires two digits for the month. - - * ``/articles/2003/`` would match the first pattern in the list, not the - second one, because the patterns are tested in order, and the first one - is the first test to pass. Feel free to exploit the ordering to insert - special cases like this. - - * ``/articles/2003`` would not match any of these patterns, because each - pattern requires that the URL end with a slash. - - * ``/articles/2003/03/3/`` would match the final pattern. Django would call - the function ``news.views.article_detail(request, '2003', '03', '3')``. - -.. _Dive Into Python's explanation: http://diveintopython.org/regular_expressions/street_addresses.html#re.matching.2.3 - -Named groups -============ - -The above example used simple, *non-named* regular-expression groups (via -parenthesis) to capture bits of the URL and pass them as *positional* arguments -to a view. In more advanced usage, it's possible to use *named* -regular-expression groups to capture URL bits and pass them as *keyword* -arguments to a view. - -In Python regular expressions, the syntax for named regular-expression groups -is ``(?P<name>pattern)``, where ``name`` is the name of the group and -``pattern`` is some pattern to match. - -Here's the above example URLconf, rewritten to use named groups:: - - urlpatterns = patterns('', - (r'^articles/2003/$', 'news.views.special_case_2003'), - (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'), - (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'), - (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'), - ) - -This accomplishes exactly the same thing as the previous example, with one -subtle difference: The captured values are passed to view functions as keyword -arguments rather than positional arguments. For example: - - * A request to ``/articles/2005/03/`` would call the function - ``news.views.month_archive(request, year='2005', month='03')``, instead - of ``news.views.month_archive(request, '2005', '03')``. - - * A request to ``/articles/2003/03/3/`` would call the function - ``news.views.article_detail(request, year='2003', month='03', day='3')``. - -In practice, this means your URLconfs are slightly more explicit and less prone -to argument-order bugs -- and you can reorder the arguments in your views' -function definitions. Of course, these benefits come at the cost of brevity; -some developers find the named-group syntax ugly and too verbose. - -The matching/grouping algorithm -------------------------------- - -Here's the algorithm the URLconf parser follows, with respect to named groups -vs. non-named groups in a regular expression: - -If there are any named arguments, it will use those, ignoring non-named arguments. -Otherwise, it will pass all non-named arguments as positional arguments. - -In both cases, it will pass any extra keyword arguments as keyword arguments. -See "Passing extra options to view functions" below. - -What the URLconf searches against -================================= - -The URLconf searches against the requested URL, as a normal Python string. This -does not include GET or POST parameters, or the domain name. - -For example, in a request to ``http://www.example.com/myapp/``, the URLconf -will look for ``myapp/``. - -In a request to ``http://www.example.com/myapp/?page=3``, the URLconf will look -for ``myapp/``. - -The URLconf doesn't look at the request method. In other words, all request -methods -- ``POST``, ``GET``, ``HEAD``, etc. -- will be routed to the same -function for the same URL. - -Syntax of the urlpatterns variable -================================== - -``urlpatterns`` should be a Python list, in the format returned by the function -:func:`django.conf.urls.defaults.patterns`. Always use ``patterns()`` to create -the ``urlpatterns`` variable. - -Convention is to use ``from django.conf.urls.defaults import *`` at the top of -your URLconf. This gives your module access to these objects: - -.. module:: django.conf.urls.defaults - -patterns --------- - -.. function:: patterns(prefix, pattern_description, ...) - -A function that takes a prefix, and an arbitrary number of URL patterns, and -returns a list of URL patterns in the format Django needs. - -The first argument to ``patterns()`` is a string ``prefix``. See -`The view prefix`_ below. - -The remaining arguments should be tuples in this format:: - - (regular expression, Python callback function [, optional dictionary [, optional name]]) - -...where ``optional dictionary`` and ``optional name`` are optional. (See -`Passing extra options to view functions`_ below.) - -.. note:: - Because `patterns()` is a function call, it accepts a maximum of 255 - arguments (URL patterns, in this case). This is a limit for all Python - function calls. This is rarely a problem in practice, because you'll - typically structure your URL patterns modularly by using `include()` - sections. However, on the off-chance you do hit the 255-argument limit, - realize that `patterns()` returns a Python list, so you can split up the - construction of the list. - - :: - - urlpatterns = patterns('', - ... - ) - urlpatterns += patterns('', - ... - ) - - Python lists have unlimited size, so there's no limit to how many URL - patterns you can construct. The only limit is that you can only create 254 - at a time (the 255th argument is the initial prefix argument). - -url ---- - -.. versionadded:: 1.0 - -.. function:: url(regex, view, kwargs=None, name=None, prefix='') - -You can use the ``url()`` function, instead of a tuple, as an argument to -``patterns()``. This is convenient if you want to specify a name without the -optional extra arguments dictionary. For example:: - - urlpatterns = patterns('', - url(r'^index/$', index_view, name="main-view"), - ... - ) - -This function takes five arguments, most of which are optional:: - - url(regex, view, kwargs=None, name=None, prefix='') - -See `Naming URL patterns`_ for why the ``name`` parameter is useful. - -The ``prefix`` parameter has the same meaning as the first argument to -``patterns()`` and is only relevant when you're passing a string as the -``view`` parameter. - -handler404 ----------- - -.. data:: handler404 - -A callable, or a string representing the full Python import path to the view -that should be called if none of the URL patterns match. - -By default, this is ``'django.views.defaults.page_not_found'``. That default -value should suffice. - -.. versionchanged:: 1.2 - Previous versions of Django only accepted strings representing import paths. - -handler500 ----------- - -.. data:: handler500 - -A callable, or a string representing the full Python import path to the view -that should be called in case of server errors. Server errors happen when you -have runtime errors in view code. - -By default, this is ``'django.views.defaults.server_error'``. That default -value should suffice. - -.. versionchanged:: 1.2 - Previous versions of Django only accepted strings representing import paths. - -include -------- - -.. function:: include(<module or pattern_list>) - -A function that takes a full Python import path to another URLconf module that -should be "included" in this place. - -.. versionadded:: 1.1 - -:func:`include` also accepts as an argument an iterable that returns URL -patterns. - -See `Including other URLconfs`_ below. - -Notes on capturing text in URLs -=============================== - -Each captured argument is sent to the view as a plain Python string, regardless -of what sort of match the regular expression makes. For example, in this -URLconf line:: - - (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'), - -...the ``year`` argument to ``news.views.year_archive()`` will be a string, not -an integer, even though the ``\d{4}`` will only match integer strings. - -A convenient trick is to specify default parameters for your views' arguments. -Here's an example URLconf and view:: - - # URLconf - urlpatterns = patterns('', - (r'^blog/$', 'blog.views.page'), - (r'^blog/page(?P<num>\d+)/$', 'blog.views.page'), - ) - - # View (in blog/views.py) - def page(request, num="1"): - # Output the appropriate page of blog entries, according to num. - -In the above example, both URL patterns point to the same view -- -``blog.views.page`` -- but the first pattern doesn't capture anything from the -URL. If the first pattern matches, the ``page()`` function will use its -default argument for ``num``, ``"1"``. If the second pattern matches, -``page()`` will use whatever ``num`` value was captured by the regex. - -Performance -=========== - -Each regular expression in a ``urlpatterns`` is compiled the first time it's -accessed. This makes the system blazingly fast. - -The view prefix -=============== - -You can specify a common prefix in your ``patterns()`` call, to cut down on -code duplication. - -Here's the example URLconf from the :doc:`Django overview </intro/overview>`:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('', - (r'^articles/(\d{4})/$', 'news.views.year_archive'), - (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'), - (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'), - ) - -In this example, each view has a common prefix -- ``'news.views'``. -Instead of typing that out for each entry in ``urlpatterns``, you can use the -first argument to the ``patterns()`` function to specify a prefix to apply to -each view function. - -With this in mind, the above example can be written more concisely as:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('news.views', - (r'^articles/(\d{4})/$', 'year_archive'), - (r'^articles/(\d{4})/(\d{2})/$', 'month_archive'), - (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'), - ) - -Note that you don't put a trailing dot (``"."``) in the prefix. Django puts -that in automatically. - -Multiple view prefixes ----------------------- - -In practice, you'll probably end up mixing and matching views to the point -where the views in your ``urlpatterns`` won't have a common prefix. However, -you can still take advantage of the view prefix shortcut to remove duplication. -Just add multiple ``patterns()`` objects together, like this: - -Old:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('', - (r'^$', 'django.views.generic.date_based.archive_index'), - (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'django.views.generic.date_based.archive_month'), - (r'^tag/(?P<tag>\w+)/$', 'weblog.views.tag'), - ) - -New:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('django.views.generic.date_based', - (r'^$', 'archive_index'), - (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$','archive_month'), - ) - - urlpatterns += patterns('weblog.views', - (r'^tag/(?P<tag>\w+)/$', 'tag'), - ) - -Including other URLconfs -======================== - -At any point, your ``urlpatterns`` can "include" other URLconf modules. This -essentially "roots" a set of URLs below other ones. - -For example, here's the URLconf for the `Django Web site`_ itself. It includes a -number of other URLconfs:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('', - (r'^weblog/', include('django_website.apps.blog.urls.blog')), - (r'^documentation/', include('django_website.apps.docs.urls.docs')), - (r'^comments/', include('django.contrib.comments.urls')), - ) - -Note that the regular expressions in this example don't have a ``$`` -(end-of-string match character) but do include a trailing slash. Whenever -Django encounters ``include()``, it chops off whatever part of the URL matched -up to that point and sends the remaining string to the included URLconf for -further processing. - -.. versionadded:: 1.1 - -Another possibility is to include additional URL patterns not by specifying the -URLconf Python module defining them as the `include`_ argument but by using -directly the pattern list as returned by `patterns`_ instead. For example:: - - from django.conf.urls.defaults import * - - extra_patterns = patterns('', - url(r'reports/(?P<id>\d+)/$', 'credit.views.report', name='credit-reports'), - url(r'charge/$', 'credit.views.charge', name='credit-charge'), - ) - - urlpatterns = patterns('', - url(r'^$', 'apps.main.views.homepage', name='site-homepage'), - (r'^help/', include('apps.help.urls')), - (r'^credit/', include(extra_patterns)), - ) - -This approach can be seen in use when you deploy an instance of the Django -Admin application. The Django Admin is deployed as instances of a -:class:`~django.contrib.admin.AdminSite`; each -:class:`~django.contrib.admin.AdminSite` instance has an attribute ``urls`` -that returns the url patterns available to that instance. It is this attribute -that you ``include()`` into your projects ``urlpatterns`` when you deploy the -admin instance. - -.. _`Django Web site`: http://www.djangoproject.com/ - -Captured parameters -------------------- - -An included URLconf receives any captured parameters from parent URLconfs, so -the following example is valid:: - - # In settings/urls/main.py - urlpatterns = patterns('', - (r'^(?P<username>\w+)/blog/', include('foo.urls.blog')), - ) - - # In foo/urls/blog.py - urlpatterns = patterns('foo.views', - (r'^$', 'blog.index'), - (r'^archive/$', 'blog.archive'), - ) - -In the above example, the captured ``"username"`` variable is passed to the -included URLconf, as expected. - -.. _topics-http-defining-url-namespaces: - -Defining URL Namespaces ------------------------ - -When you need to deploy multiple instances of a single application, it can be -helpful to be able to differentiate between instances. This is especially -important when using :ref:`named URL patterns <naming-url-patterns>`, since -multiple instances of a single application will share named URLs. Namespaces -provide a way to tell these named URLs apart. - -A URL namespace comes in two parts, both of which are strings: - - * An **application namespace**. This describes the name of the application - that is being deployed. Every instance of a single application will have - the same application namespace. For example, Django's admin application - has the somewhat predictable application namespace of ``admin``. - - * An **instance namespace**. This identifies a specific instance of an - application. Instance namespaces should be unique across your entire - project. However, an instance namespace can be the same as the - application namespace. This is used to specify a default instance of an - application. For example, the default Django Admin instance has an - instance namespace of ``admin``. - -URL Namespaces can be specified in two ways. - -Firstly, you can provide the application and instance namespace as arguments -to ``include()`` when you construct your URL patterns. For example,:: - - (r'^help/', include('apps.help.urls', namespace='foo', app_name='bar')), - -This will include the URLs defined in ``apps.help.urls`` into the application -namespace ``bar``, with the instance namespace ``foo``. - -Secondly, you can include an object that contains embedded namespace data. If -you ``include()`` a ``patterns`` object, that object will be added to the -global namespace. However, you can also ``include()`` an object that contains -a 3-tuple containing:: - - (<patterns object>, <application namespace>, <instance namespace>) - -This will include the nominated URL patterns into the given application and -instance namespace. For example, the ``urls`` attribute of Django's -:class:`~django.contrib.admin.AdminSite` object returns a 3-tuple that contains -all the patterns in an admin site, plus the name of the admin instance, and the -application namespace ``admin``. - -Once you have defined namespaced URLs, you can reverse them. For details on -reversing namespaced urls, see the documentation on :ref:`reversing namespaced -URLs <topics-http-reversing-url-namespaces>`. - -Passing extra options to view functions -======================================= - -URLconfs have a hook that lets you pass extra arguments to your view functions, -as a Python dictionary. - -Any URLconf tuple can have an optional third element, which should be a -dictionary of extra keyword arguments to pass to the view function. - -For example:: - - urlpatterns = patterns('blog.views', - (r'^blog/(?P<year>\d{4})/$', 'year_archive', {'foo': 'bar'}), - ) - -In this example, for a request to ``/blog/2005/``, Django will call the -``blog.views.year_archive()`` view, passing it these keyword arguments:: - - year='2005', foo='bar' - -This technique is used in :doc:`generic views </ref/generic-views>` and in the -:doc:`syndication framework </ref/contrib/syndication>` to pass metadata and -options to views. - -.. admonition:: Dealing with conflicts - - It's possible to have a URL pattern which captures named keyword arguments, - and also passes arguments with the same names in its dictionary of extra - arguments. When this happens, the arguments in the dictionary will be used - instead of the arguments captured in the URL. - -Passing extra options to ``include()`` --------------------------------------- - -Similarly, you can pass extra options to ``include()``. When you pass extra -options to ``include()``, *each* line in the included URLconf will be passed -the extra options. - -For example, these two URLconf sets are functionally identical: - -Set one:: - - # main.py - urlpatterns = patterns('', - (r'^blog/', include('inner'), {'blogid': 3}), - ) - - # inner.py - urlpatterns = patterns('', - (r'^archive/$', 'mysite.views.archive'), - (r'^about/$', 'mysite.views.about'), - ) - -Set two:: - - # main.py - urlpatterns = patterns('', - (r'^blog/', include('inner')), - ) - - # inner.py - urlpatterns = patterns('', - (r'^archive/$', 'mysite.views.archive', {'blogid': 3}), - (r'^about/$', 'mysite.views.about', {'blogid': 3}), - ) - -Note that extra options will *always* be passed to *every* line in the included -URLconf, regardless of whether the line's view actually accepts those options -as valid. For this reason, this technique is only useful if you're certain that -every view in the included URLconf accepts the extra options you're passing. - -Passing callable objects instead of strings -=========================================== - -Some developers find it more natural to pass the actual Python function object -rather than a string containing the path to its module. This alternative is -supported -- you can pass any callable object as the view. - -For example, given this URLconf in "string" notation:: - - urlpatterns = patterns('', - (r'^archive/$', 'mysite.views.archive'), - (r'^about/$', 'mysite.views.about'), - (r'^contact/$', 'mysite.views.contact'), - ) - -You can accomplish the same thing by passing objects rather than strings. Just -be sure to import the objects:: - - from mysite.views import archive, about, contact - - urlpatterns = patterns('', - (r'^archive/$', archive), - (r'^about/$', about), - (r'^contact/$', contact), - ) - -The following example is functionally identical. It's just a bit more compact -because it imports the module that contains the views, rather than importing -each view individually:: - - from mysite import views - - urlpatterns = patterns('', - (r'^archive/$', views.archive), - (r'^about/$', views.about), - (r'^contact/$', views.contact), - ) - -The style you use is up to you. - -Note that if you use this technique -- passing objects rather than strings -- -the view prefix (as explained in "The view prefix" above) will have no effect. - -.. _naming-url-patterns: - -Naming URL patterns -=================== - -.. versionadded:: 1.0 - -It's fairly common to use the same view function in multiple URL patterns in -your URLconf. For example, these two URL patterns both point to the ``archive`` -view:: - - urlpatterns = patterns('', - (r'^archive/(\d{4})/$', archive), - (r'^archive-summary/(\d{4})/$', archive, {'summary': True}), - ) - -This is completely valid, but it leads to problems when you try to do reverse -URL matching (through the ``permalink()`` decorator or the :ttag:`url` template -tag). Continuing this example, if you wanted to retrieve the URL for the -``archive`` view, Django's reverse URL matcher would get confused, because *two* -URLpatterns point at that view. - -To solve this problem, Django supports **named URL patterns**. That is, you can -give a name to a URL pattern in order to distinguish it from other patterns -using the same view and parameters. Then, you can use this name in reverse URL -matching. - -Here's the above example, rewritten to use named URL patterns:: - - urlpatterns = patterns('', - url(r'^archive/(\d{4})/$', archive, name="full-archive"), - url(r'^archive-summary/(\d{4})/$', archive, {'summary': True}, "arch-summary"), - ) - -With these names in place (``full-archive`` and ``arch-summary``), you can -target each pattern individually by using its name: - -.. code-block:: html+django - - {% url arch-summary 1945 %} - {% url full-archive 2007 %} - -Even though both URL patterns refer to the ``archive`` view here, using the -``name`` parameter to ``url()`` allows you to tell them apart in templates. - -The string used for the URL name can contain any characters you like. You are -not restricted to valid Python names. - -.. note:: - - When you name your URL patterns, make sure you use names that are unlikely - to clash with any other application's choice of names. If you call your URL - pattern ``comment``, and another application does the same thing, there's - no guarantee which URL will be inserted into your template when you use - this name. - - Putting a prefix on your URL names, perhaps derived from the application - name, will decrease the chances of collision. We recommend something like - ``myapp-comment`` instead of ``comment``. - -.. _topics-http-reversing-url-namespaces: - -URL namespaces --------------- - -.. versionadded:: 1.1 - -Namespaced URLs are specified using the ``:`` operator. For example, the main -index page of the admin application is referenced using ``admin:index``. This -indicates a namespace of ``admin``, and a named URL of ``index``. - -Namespaces can also be nested. The named URL ``foo:bar:whiz`` would look for -a pattern named ``whiz`` in the namespace ``bar`` that is itself defined within -the top-level namespace ``foo``. - -When given a namespaced URL (e.g. ``myapp:index``) to resolve, Django splits -the fully qualified name into parts, and then tries the following lookup: - - 1. First, Django looks for a matching application namespace (in this - example, ``myapp``). This will yield a list of instances of that - application. - - 2. If there is a *current* application defined, Django finds and returns - the URL resolver for that instance. The *current* application can be - specified as an attribute on the template context - applications that - expect to have multiple deployments should set the ``current_app`` - attribute on any ``Context`` or ``RequestContext`` that is used to - render a template. - - The current application can also be specified manually as an argument - to the :func:`reverse()` function. - - 3. If there is no current application. Django looks for a default - application instance. The default application instance is the instance - that has an instance namespace matching the application namespace (in - this example, an instance of the ``myapp`` called ``myapp``). - - 4. If there is no default application instance, Django will pick the last - deployed instance of the application, whatever its instance name may be. - - 5. If the provided namespace doesn't match an application namespace in - step 1, Django will attempt a direct lookup of the namespace as an - instance namespace. - -If there are nested namespaces, these steps are repeated for each part of the -namespace until only the view name is unresolved. The view name will then be -resolved into a URL in the namespace that has been found. - -To show this resolution strategy in action, consider an example of two instances -of ``myapp``: one called ``foo``, and one called ``bar``. ``myapp`` has a main -index page with a URL named `index`. Using this setup, the following lookups are -possible: - - * If one of the instances is current - say, if we were rendering a utility page - in the instance ``bar`` - ``myapp:index`` will resolve to the index page of - the instance ``bar``. - - * If there is no current instance - say, if we were rendering a page - somewhere else on the site - ``myapp:index`` will resolve to the last - registered instance of ``myapp``. Since there is no default instance, - the last instance of ``myapp`` that is registered will be used. This could - be ``foo`` or ``bar``, depending on the order they are introduced into the - urlpatterns of the project. - - * ``foo:index`` will always resolve to the index page of the instance ``foo``. - -If there was also a default instance - i.e., an instance named `myapp` - the -following would happen: - - * If one of the instances is current - say, if we were rendering a utility page - in the instance ``bar`` - ``myapp:index`` will resolve to the index page of - the instance ``bar``. - - * If there is no current instance - say, if we were rendering a page somewhere - else on the site - ``myapp:index`` will resolve to the index page of the - default instance. - - * ``foo:index`` will again resolve to the index page of the instance ``foo``. - - -Utility methods -=============== - -reverse() ---------- - -If you need to use something similar to the :ttag:`url` template tag in -your code, Django provides the following method (in the -``django.core.urlresolvers`` module): - -.. function:: reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None) - -``viewname`` is either the function name (either a function reference, or the -string version of the name, if you used that form in ``urlpatterns``) or the -`URL pattern name`_. Normally, you won't need to worry about the -``urlconf`` parameter and will only pass in the positional and keyword -arguments to use in the URL matching. For example:: - - from django.core.urlresolvers import reverse - - def myview(request): - return HttpResponseRedirect(reverse('arch-summary', args=[1945])) - -.. _URL pattern name: `Naming URL patterns`_ - -The ``reverse()`` function can reverse a large variety of regular expression -patterns for URLs, but not every possible one. The main restriction at the -moment is that the pattern cannot contain alternative choices using the -vertical bar (``"|"``) character. You can quite happily use such patterns for -matching against incoming URLs and sending them off to views, but you cannot -reverse such patterns. - -.. versionadded:: 1.1 - -The ``current_app`` argument allows you to provide a hint to the resolver -indicating the application to which the currently executing view belongs. -This ``current_app`` argument is used as a hint to resolve application -namespaces into URLs on specific application instances, according to the -:ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>`. - -.. admonition:: Make sure your views are all correct. - - As part of working out which URL names map to which patterns, the - ``reverse()`` function has to import all of your URLconf files and examine - the name of each view. This involves importing each view function. If - there are *any* errors whilst importing any of your view functions, it - will cause ``reverse()`` to raise an error, even if that view function is - not the one you are trying to reverse. - - Make sure that any views you reference in your URLconf files exist and can - be imported correctly. Do not include lines that reference views you - haven't written yet, because those views will not be importable. - -resolve() ---------- - -The :func:`django.core.urlresolvers.resolve` function can be used for resolving -URL paths to the corresponding view functions. It has the following signature: - -.. function:: resolve(path, urlconf=None) - -``path`` is the URL path you want to resolve. As with -:func:`~django.core.urlresolvers.reverse`, you don't need to -worry about the ``urlconf`` parameter. The function returns -the triple (view function, arguments, keyword arguments). - -If the URL does not resolve, the function raises an -:class:`~django.http.Http404` exception. - -For example, it can be used for testing if a view would raise a ``Http404`` -error before redirecting to it:: - - from urlparse import urlparse - from django.core.urlresolvers import resolve - from django.http import HttpResponseRedirect, Http404 - - def myview(request): - next = request.META.get('HTTP_REFERER', None) or '/' - response = HttpResponseRedirect(next) - - # modify the request and response as required, e.g. change locale - # and set corresponding locale cookie - - view, args, kwargs = resolve(urlparse(next)[2]) - kwargs['request'] = request - try: - view(*args, **kwargs) - except Http404: - return HttpResponseRedirect('/') - return response - -permalink() ------------ - -The :func:`django.db.models.permalink` decorator is useful for writing short -methods that return a full URL path. For example, a model's -``get_absolute_url()`` method. See :func:`django.db.models.permalink` for more. - -get_script_prefix() -------------------- - -.. function:: get_script_prefix() - -.. versionadded:: 1.0 - -Normally, you should always use :func:`~django.core.urlresolvers.reverse` or -:func:`~django.db.models.permalink` to define URLs within your application. -However, if your application constructs part of the URL hierarchy itself, you -may occasionally need to generate URLs. In that case, you need to be able to -find the base URL of the Django project within its web server -(normally, :func:`~django.core.urlresolvers.reverse` takes care of this for -you). In that case, you can call ``get_script_prefix()``, which will return the -script prefix portion of the URL for your Django project. If your Django -project is at the root of its webserver, this is always ``"/"``, but it can be -changed, for instance by using ``django.root`` (see :ref:`How to use -Django with Apache and mod_python <howto-deployment-modpython>`).
\ No newline at end of file diff --git a/parts/django/docs/topics/http/views.txt b/parts/django/docs/topics/http/views.txt deleted file mode 100644 index 2818f42..0000000 --- a/parts/django/docs/topics/http/views.txt +++ /dev/null @@ -1,202 +0,0 @@ -============= -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*, let's create a file called -``views.py`` in the ``mysite`` directory, which you created in the previous -chapter. - -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 ``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. - -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 :class:`~django.template.RequestContext` and - will have access to variables supplied by your - :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting (e.g., - :setting:`MEDIA_URL`). - - * If :setting:`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. |