diff options
author | Nishanth Amuluru | 2011-01-11 22:41:51 +0530 |
---|---|---|
committer | Nishanth Amuluru | 2011-01-11 22:41:51 +0530 |
commit | b03203c8cb991c16ac8a3d74c8c4078182d0bb48 (patch) | |
tree | 7cf13b2deacbfaaec99edb431b83ddd5ea734a52 /parts/django/docs/topics | |
parent | 0c50203cd9eb94b819883c3110922e873f003138 (diff) | |
download | pytask-b03203c8cb991c16ac8a3d74c8c4078182d0bb48.tar.gz pytask-b03203c8cb991c16ac8a3d74c8c4078182d0bb48.tar.bz2 pytask-b03203c8cb991c16ac8a3d74c8c4078182d0bb48.zip |
removed all the buildout files
Diffstat (limited to 'parts/django/docs/topics')
40 files changed, 0 insertions, 18023 deletions
diff --git a/parts/django/docs/topics/auth.txt b/parts/django/docs/topics/auth.txt deleted file mode 100644 index a58e523..0000000 --- a/parts/django/docs/topics/auth.txt +++ /dev/null @@ -1,1612 +0,0 @@ -============================= -User authentication in Django -============================= - -.. module:: django.contrib.auth - :synopsis: Django's authentication framework. - -Django comes with a user authentication system. It handles user accounts, -groups, permissions and cookie-based user sessions. This document explains how -things work. - -Overview -======== - -The auth system consists of: - - * Users - * Permissions: Binary (yes/no) flags designating whether a user may perform - a certain task. - * Groups: A generic way of applying labels and permissions to more than one - user. - * Messages: A simple way to queue messages for given users. - -.. deprecated:: 1.2 - The Messages component of the auth system will be removed in Django 1.4. - -Installation -============ - -Authentication support is bundled as a Django application in -``django.contrib.auth``. To install it, do the following: - - 1. Put ``'django.contrib.auth'`` and ``'django.contrib.contenttypes'`` in - your :setting:`INSTALLED_APPS` setting. - (The :class:`~django.contrib.auth.models.Permission` model in - :mod:`django.contrib.auth` depends on :mod:`django.contrib.contenttypes`.) - 2. Run the command ``manage.py syncdb``. - -Note that the default :file:`settings.py` file created by -:djadmin:`django-admin.py startproject <startproject>` includes -``'django.contrib.auth'`` and ``'django.contrib.contenttypes'`` in -:setting:`INSTALLED_APPS` for convenience. If your :setting:`INSTALLED_APPS` -already contains these apps, feel free to run :djadmin:`manage.py syncdb -<syncdb>` again; you can run that command as many times as you'd like, and each -time it'll only install what's needed. - -The :djadmin:`syncdb` command creates the necessary database tables, creates -permission objects for all installed apps that need 'em, and prompts you to -create a superuser account the first time you run it. - -Once you've taken those steps, that's it. - -Users -===== - -.. class:: models.User - -API reference -------------- - -Fields -~~~~~~ - -.. class:: models.User - - :class:`~django.contrib.auth.models.User` objects have the following - fields: - - .. attribute:: models.User.username - - Required. 30 characters or fewer. Alphanumeric characters only - (letters, digits and underscores). - - .. versionchanged:: 1.2 - Usernames may now contain ``@``, ``+``, ``.`` and ``-`` characters. - - .. attribute:: models.User.first_name - - Optional. 30 characters or fewer. - - .. attribute:: models.User.last_name - - Optional. 30 characters or fewer. - - .. attribute:: models.User.email - - Optional. E-mail address. - - .. attribute:: models.User.password - - Required. A hash of, and metadata about, the password. (Django doesn't - store the raw password.) Raw passwords can be arbitrarily long and can - contain any character. See the "Passwords" section below. - - .. attribute:: models.User.is_staff - - Boolean. Designates whether this user can access the admin site. - - .. attribute:: models.User.is_active - - Boolean. Designates whether this user account should be considered - active. We recommend that you set this flag to ``False`` instead of - deleting accounts; that way, if your applications have any foreign keys - to users, the foreign keys won't break. - - This doesn't necessarily control whether or not the user can log in. - Authentication backends aren't required to check for the ``is_active`` - flag, so if you want to reject a login based on ``is_active`` being - ``False``, it's up to you to check that in your own login view. - However, the :class:`~django.contrib.auth.forms.AuthenticationForm` - used by the :func:`~django.contrib.auth.views.login` view *does* - perform this check, as do the permission-checking methods such as - :meth:`~models.User.has_perm` and the authentication in the Django - admin. All of those functions/methods will return ``False`` for - inactive users. - - .. attribute:: models.User.is_superuser - - Boolean. Designates that this user has all permissions without - explicitly assigning them. - - .. attribute:: models.User.last_login - - A datetime of the user's last login. Is set to the current date/time by - default. - - .. attribute:: models.User.date_joined - - A datetime designating when the account was created. Is set to the - current date/time by default when the account is created. - -Methods -~~~~~~~ - -.. class:: models.User - - :class:`~django.contrib.auth.models.User` objects have two many-to-many - fields: models.User. ``groups`` and ``user_permissions``. - :class:`~django.contrib.auth.models.User` objects can access their related - objects in the same way as any other :doc:`Django model - </topics/db/models>`: - - .. code-block:: python - - myuser.groups = [group_list] - myuser.groups.add(group, group, ...) - myuser.groups.remove(group, group, ...) - myuser.groups.clear() - myuser.user_permissions = [permission_list] - myuser.user_permissions.add(permission, permission, ...) - myuser.user_permissions.remove(permission, permission, ...) - myuser.user_permissions.clear() - - In addition to those automatic API methods, - :class:`~django.contrib.auth.models.User` objects have the following custom - methods: - - .. method:: models.User.is_anonymous() - - Always returns ``False``. This is a way of differentiating - :class:`~django.contrib.auth.models.User` and - :class:`~django.contrib.auth.models.AnonymousUser` objects. - Generally, you should prefer using - :meth:`~django.contrib.auth.models.User.is_authenticated()` to this - method. - - .. method:: models.User.is_authenticated() - - Always returns ``True``. This is a way to tell if the user has been - authenticated. This does not imply any permissions, and doesn't check - if the user is active - it only indicates that the user has provided a - valid username and password. - - .. method:: models.User.get_full_name() - - Returns the :attr:`~django.contrib.auth.models.User.first_name` plus - the :attr:`~django.contrib.auth.models.User.last_name`, with a space in - between. - - .. method:: models.User.set_password(raw_password) - - Sets the user's password to the given raw string, taking care of the - password hashing. Doesn't save the - :class:`~django.contrib.auth.models.User` object. - - .. method:: models.User.check_password(raw_password) - - Returns ``True`` if the given raw string is the correct password for - the user. (This takes care of the password hashing in making the - comparison.) - - .. method:: models.User.set_unusable_password() - - .. versionadded:: 1.0 - - Marks the user as having no password set. This isn't the same as - having a blank string for a password. - :meth:`~django.contrib.auth.models.User.check_password()` for this user - will never return ``True``. Doesn't save the - :class:`~django.contrib.auth.models.User` object. - - You may need this if authentication for your application takes place - against an existing external source such as an LDAP directory. - - .. method:: models.User.has_usable_password() - - .. versionadded:: 1.0 - - Returns ``False`` if - :meth:`~django.contrib.auth.models.User.set_unusable_password()` has - been called for this user. - - .. method:: models.User.get_group_permissions(obj=None) - - Returns a set of permission strings that the user has, through his/her - groups. - - .. versionadded:: 1.2 - - If ``obj`` is passed in, only returns the group permissions for - this specific object. - - .. method:: models.User.get_all_permissions(obj=None) - - Returns a set of permission strings that the user has, both through - group and user permissions. - - .. versionadded:: 1.2 - - If ``obj`` is passed in, only returns the permissions for this - specific object. - - .. method:: models.User.has_perm(perm, obj=None) - - Returns ``True`` if the user has the specified permission, where perm is - in the format ``"<app label>.<permission codename>"``. (see - `permissions`_ section below). If the user is inactive, this method will - always return ``False``. - - .. versionadded:: 1.2 - - If ``obj`` is passed in, this method won't check for a permission for - the model, but for this specific object. - - .. method:: models.User.has_perms(perm_list, obj=None) - - Returns ``True`` if the user has each of the specified permissions, - where each perm is in the format - ``"<app label>.<permission codename>"``. If the user is inactive, - this method will always return ``False``. - - .. versionadded:: 1.2 - - If ``obj`` is passed in, this method won't check for permissions for - the model, but for the specific object. - - .. method:: models.User.has_module_perms(package_name) - - Returns ``True`` if the user has any permissions in the given package - (the Django app label). If the user is inactive, this method will - always return ``False``. - - .. method:: models.User.get_and_delete_messages() - - Returns a list of :class:`~django.contrib.auth.models.Message` objects - in the user's queue and deletes the messages from the queue. - - .. method:: models.User.email_user(subject, message, from_email=None) - - Sends an e-mail to the user. If - :attr:`~django.contrib.auth.models.User.from_email` is ``None``, Django - uses the :setting:`DEFAULT_FROM_EMAIL`. - - .. method:: models.User.get_profile() - - Returns a site-specific profile for this user. Raises - :exc:`django.contrib.auth.models.SiteProfileNotAvailable` if the - current site doesn't allow profiles. For information on how to define a - site-specific user profile, see the section on `storing additional user - information`_ below. - -.. _storing additional user information: #storing-additional-information-about-users - -Manager functions -~~~~~~~~~~~~~~~~~ - -.. class:: models.UserManager - - The :class:`~django.contrib.auth.models.User` model has a custom manager - that has the following helper functions: - - .. method:: models.UserManager.create_user(username, email, password=None) - - Creates, saves and returns a :class:`~django.contrib.auth.models.User`. - - The :attr:`~django.contrib.auth.models.User.username` and - :attr:`~django.contrib.auth.models.User.password` are set as given. The - domain portion of :attr:`~django.contrib.auth.models.User.email` is - automatically convered to lowercase, and the returned - :class:`~django.contrib.auth.models.User` object will have - :attr:`~models.User.is_active` set to ``True``. - - If no password is provided, - :meth:`~django.contrib.auth.models.User.set_unusable_password()` will - be called. - - See `Creating users`_ for example usage. - - .. method:: models.UserManager.make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789') - - Returns a random password with the given length and given string of - allowed characters. (Note that the default value of ``allowed_chars`` - doesn't contain letters that can cause user confusion, including: - - * ``i``, ``l``, ``I``, and ``1`` (lowercase letter i, lowercase - letter L, uppercase letter i, and the number one) - * ``o``, ``O``, and ``0`` (uppercase letter o, lowercase letter o, - and zero) - -Basic usage ------------ - -.. _topics-auth-creating-users: - -Creating users -~~~~~~~~~~~~~~ - -The most basic way to create users is to use the -:meth:`~django.contrib.auth.models.UserManager.create_user` helper function -that comes with Django:: - - >>> from django.contrib.auth.models import User - >>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword') - - # At this point, user is a User object that has already been saved - # to the database. You can continue to change its attributes - # if you want to change other fields. - >>> user.is_staff = True - >>> user.save() - -You can also create users using the Django admin site. Assuming you've enabled -the admin site and hooked it to the URL ``/admin/``, the "Add user" page is at -``/admin/auth/user/add/``. You should also see a link to "Users" in the "Auth" -section of the main admin index page. The "Add user" admin page is different -than standard admin pages in that it requires you to choose a username and -password before allowing you to edit the rest of the user's fields. - -Also note: if you want your own user account to be able to create users using -the Django admin site, you'll need to give yourself permission to add users -*and* change users (i.e., the "Add user" and "Change user" permissions). If -your account has permission to add users but not to change them, you won't be -able to add users. Why? Because if you have permission to add users, you have -the power to create superusers, which can then, in turn, change other users. So -Django requires add *and* change permissions as a slight security measure. - -Changing passwords -~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.2 - The ``manage.py changepassword`` command was added. - -:djadmin:`manage.py changepassword *username* <changepassword>` offers a method -of changing a User's password from the command line. It prompts you to -change the password of a given user which you must enter twice. If -they both match, the new password will be changed immediately. If you -do not supply a user, the command will attempt to change the password -whose username matches the current user. - -You can also change a password programmatically, using -:meth:`~django.contrib.auth.models.User.set_password()`: - -.. code-block:: python - - >>> from django.contrib.auth.models import User - >>> u = User.objects.get(username__exact='john') - >>> u.set_password('new password') - >>> u.save() - -Don't set the :attr:`~django.contrib.auth.models.User.password` attribute -directly unless you know what you're doing. This is explained in the next -section. - -Passwords ---------- - -The :attr:`~django.contrib.auth.models.User.password` attribute of a -:class:`~django.contrib.auth.models.User` object is a string in this format:: - - hashtype$salt$hash - -That's hashtype, salt and hash, separated by the dollar-sign character. - -Hashtype is either ``sha1`` (default), ``md5`` or ``crypt`` -- the algorithm -used to perform a one-way hash of the password. Salt is a random string used -to salt the raw password to create the hash. Note that the ``crypt`` method is -only supported on platforms that have the standard Python ``crypt`` module -available. - -.. versionadded:: 1.0 - Support for the ``crypt`` module is new in Django 1.0. - -For example:: - - sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4 - -The :meth:`~django.contrib.auth.models.User.set_password` and -:meth:`~django.contrib.auth.models.User.check_password` functions handle the -setting and checking of these values behind the scenes. - -Previous Django versions, such as 0.90, used simple MD5 hashes without password -salts. For backwards compatibility, those are still supported; they'll be -converted automatically to the new style the first time -:meth:`~django.contrib.auth.models.User.check_password()` works correctly for -a given user. - -Anonymous users ---------------- - -.. class:: models.AnonymousUser - - :class:`django.contrib.auth.models.AnonymousUser` is a class that - implements the :class:`django.contrib.auth.models.User` interface, with - these differences: - - * :attr:`~django.contrib.auth.models.User.id` is always ``None``. - * :attr:`~django.contrib.auth.models.User.is_staff` and - :attr:`~django.contrib.auth.models.User.is_superuser` are always - ``False``. - * :attr:`~django.contrib.auth.models.User.is_active` is always ``False``. - * :attr:`~django.contrib.auth.models.User.groups` and - :attr:`~django.contrib.auth.models.User.user_permissions` are always - empty. - * :meth:`~django.contrib.auth.models.User.is_anonymous()` returns ``True`` - instead of ``False``. - * :meth:`~django.contrib.auth.models.User.is_authenticated()` returns - ``False`` instead of ``True``. - * :meth:`~django.contrib.auth.models.User.set_password()`, - :meth:`~django.contrib.auth.models.User.check_password()`, - :meth:`~django.contrib.auth.models.User.save()`, - :meth:`~django.contrib.auth.models.User.delete()`, - :meth:`~django.contrib.auth.models.User.set_groups()` and - :meth:`~django.contrib.auth.models.User.set_permissions()` raise - :exc:`NotImplementedError`. - -In practice, you probably won't need to use -:class:`~django.contrib.auth.models.AnonymousUser` objects on your own, but -they're used by Web requests, as explained in the next section. - -.. _topics-auth-creating-superusers: - -Creating superusers -------------------- - -.. versionadded:: 1.0 - The ``manage.py createsuperuser`` command is new. - -:djadmin:`manage.py syncdb <syncdb>` prompts you to create a superuser the -first time you run it after adding ``'django.contrib.auth'`` to your -:setting:`INSTALLED_APPS`. If you need to create a superuser at a later date, -you can use a command line utility:: - - manage.py createsuperuser --username=joe --email=joe@example.com - -You will be prompted for a password. After you enter one, the user will be -created immediately. If you leave off the :djadminopt:`--username` or the -:djadminopt:`--email` options, it will prompt you for those values. - -If you're using an older release of Django, the old way of creating a superuser -on the command line still works:: - - python /path/to/django/contrib/auth/create_superuser.py - -...where :file:`/path/to` is the path to the Django codebase on your -filesystem. The ``manage.py`` command is preferred because it figures out the -correct path and environment for you. - -.. _auth-profiles: - -Storing additional information about users ------------------------------------------- - -If you'd like to store additional information related to your users, Django -provides a method to specify a site-specific related model -- termed a "user -profile" -- for this purpose. - -To make use of this feature, define a model with fields for the -additional information you'd like to store, or additional methods -you'd like to have available, and also add a -:class:`~django.db.models.Field.OneToOneField` from your model to the -:class:`~django.contrib.auth.models.User` model. This will ensure only -one instance of your model can be created for each -:class:`~django.contrib.auth.models.User`. - -To indicate that this model is the user profile model for a given site, fill in -the setting :setting:`AUTH_PROFILE_MODULE` with a string consisting of the -following items, separated by a dot: - -1. The name of the application (case sensitive) in which the user - profile model is defined (in other words, the - name which was passed to :djadmin:`manage.py startapp <startapp>` to create - the application). - -2. The name of the model (not case sensitive) class. - -For example, if the profile model was a class named ``UserProfile`` and was -defined inside an application named ``accounts``, the appropriate setting would -be:: - - AUTH_PROFILE_MODULE = 'accounts.UserProfile' - -When a user profile model has been defined and specified in this manner, each -:class:`~django.contrib.auth.models.User` object will have a method -- -:class:`~django.contrib.auth.models.User.get_profile()` -- which returns the -instance of the user profile model associated with that -:class:`~django.contrib.auth.models.User`. - -The method :class:`~django.contrib.auth.models.User.get_profile()` -does not create the profile, if it does not exist. You need to -register a handler for the signal -:attr:`django.db.models.signals.post_save` on the User model, and, in -the handler, if created=True, create the associated user profile. - -For more information, see `Chapter 12 of the Django book`_. - -.. _Chapter 12 of the Django book: http://www.djangobook.com/en/1.0/chapter12/#cn222 - -Authentication in Web requests -============================== - -Until now, this document has dealt with the low-level APIs for manipulating -authentication-related objects. On a higher level, Django can hook this -authentication framework into its system of -:class:`request objects <django.http.HttpRequest>`. - -First, install the -:class:`~django.contrib.sessions.middleware.SessionMiddleware` and -:class:`~django.contrib.auth.middleware.AuthenticationMiddleware` -middlewares by adding them to your :setting:`MIDDLEWARE_CLASSES` setting. See -the :doc:`session documentation </topics/http/sessions>` for more information. - -Once you have those middlewares installed, you'll be able to access -:attr:`request.user <django.http.HttpRequest.user>` in views. -:attr:`request.user <django.http.HttpRequest.user>` will give you a -:class:`~django.contrib.auth.models.User` object representing the currently -logged-in user. If a user isn't currently logged in, -:attr:`request.user <django.http.HttpRequest.user>` will be set to an instance -of :class:`~django.contrib.auth.models.AnonymousUser` (see the previous -section). You can tell them apart with -:meth:`~django.contrib.auth.models.User.is_authenticated()`, like so:: - - if request.user.is_authenticated(): - # Do something for authenticated users. - else: - # Do something for anonymous users. - -.. _how-to-log-a-user-in: - -How to log a user in --------------------- - -Django provides two functions in :mod:`django.contrib.auth`: -:func:`~django.contrib.auth.authenticate()` and -:func:`~django.contrib.auth.login()`. - -.. function:: authenticate() - - To authenticate a given username and password, use - :func:`~django.contrib.auth.authenticate()`. It takes two keyword - arguments, ``username`` and ``password``, and it returns a - :class:`~django.contrib.auth.models.User` object if the password is valid - for the given username. If the password is invalid, - :func:`~django.contrib.auth.authenticate()` returns ``None``. Example:: - - from django.contrib.auth import authenticate - user = authenticate(username='john', password='secret') - if user is not None: - if user.is_active: - print "You provided a correct username and password!" - else: - print "Your account has been disabled!" - else: - print "Your username and password were incorrect." - -.. function:: login() - - To log a user in, in a view, use :func:`~django.contrib.auth.login()`. It - takes an :class:`~django.http.HttpRequest` object and a - :class:`~django.contrib.auth.models.User` object. - :func:`~django.contrib.auth.login()` saves the user's ID in the session, - using Django's session framework, so, as mentioned above, you'll need to - make sure to have the session middleware installed. - - This example shows how you might use both - :func:`~django.contrib.auth.authenticate()` and - :func:`~django.contrib.auth.login()`:: - - from django.contrib.auth import authenticate, login - - def my_view(request): - username = request.POST['username'] - password = request.POST['password'] - user = authenticate(username=username, password=password) - if user is not None: - if user.is_active: - login(request, user) - # Redirect to a success page. - else: - # Return a 'disabled account' error message - else: - # Return an 'invalid login' error message. - -.. admonition:: Calling ``authenticate()`` first - - When you're manually logging a user in, you *must* call - :func:`~django.contrib.auth.authenticate()` before you call - :func:`~django.contrib.auth.login()`. - :func:`~django.contrib.auth.authenticate()` - sets an attribute on the :class:`~django.contrib.auth.models.User` noting - which authentication backend successfully authenticated that user (see the - `backends documentation`_ for details), and this information is needed - later during the login process. - -.. _backends documentation: #other-authentication-sources - -Manually checking a user's password ------------------------------------ - -.. function:: check_password() - - If you'd like to manually authenticate a user by comparing a plain-text - password to the hashed password in the database, use the convenience - function :func:`django.contrib.auth.models.check_password`. It takes two - arguments: the plain-text password to check, and the full value of a user's - ``password`` field in the database to check against, and returns ``True`` - if they match, ``False`` otherwise. - -How to log a user out ---------------------- - -.. function:: logout() - - To log out a user who has been logged in via - :func:`django.contrib.auth.login()`, use - :func:`django.contrib.auth.logout()` within your view. It takes an - :class:`~django.http.HttpRequest` object and has no return value. - Example:: - - from django.contrib.auth import logout - - def logout_view(request): - logout(request) - # Redirect to a success page. - - Note that :func:`~django.contrib.auth.logout()` doesn't throw any errors if - the user wasn't logged in. - - .. versionchanged:: 1.0 - Calling ``logout()`` now cleans session data. - - When you call :func:`~django.contrib.auth.logout()`, the session data for - the current request is completely cleaned out. All existing data is - removed. This is to prevent another person from using the same Web browser - to log in and have access to the previous user's session data. If you want - to put anything into the session that will be available to the user - immediately after logging out, do that *after* calling - :func:`django.contrib.auth.logout()`. - -Limiting access to logged-in users ----------------------------------- - -The raw way -~~~~~~~~~~~ - -The simple, raw way to limit access to pages is to check -:meth:`request.user.is_authenticated() -<django.contrib.auth.models.User.is_authenticated()>` and either redirect to a -login page:: - - from django.http import HttpResponseRedirect - - def my_view(request): - if not request.user.is_authenticated(): - return HttpResponseRedirect('/login/?next=%s' % request.path) - # ... - -...or display an error message:: - - def my_view(request): - if not request.user.is_authenticated(): - return render_to_response('myapp/login_error.html') - # ... - -The login_required decorator -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. function:: decorators.login_required([redirect_field_name=REDIRECT_FIELD_NAME]) - - As a shortcut, you can use the convenient - :func:`~django.contrib.auth.decorators.login_required` decorator:: - - from django.contrib.auth.decorators import login_required - - @login_required - def my_view(request): - ... - - :func:`~django.contrib.auth.decorators.login_required` does the following: - - * If the user isn't logged in, redirect to - :setting:`settings.LOGIN_URL <LOGIN_URL>`, passing the current absolute - path in the query string. Example: ``/accounts/login/?next=/polls/3/``. - - * If the user is logged in, execute the view normally. The view code is - free to assume the user is logged in. - - By default, the path that the user should be redirected to upon - successful authentication is stored in a query string parameter called - ``"next"``. If you would prefer to use a different name for this parameter, - :func:`~django.contrib.auth.decorators.login_required` takes an - optional ``redirect_field_name`` parameter:: - - from django.contrib.auth.decorators import login_required - - @login_required(redirect_field_name='my_redirect_field') - def my_view(request): - ... - - If you provide a value to ``redirect_field_name``, you will most - likely need to customize your login template as well, since the template - context variable which stores the redirect path will use the value of - ``redirect_field_name`` as it's key rather than ``"next"`` (the default). - - Note that you'll need to map the appropriate Django view to - :setting:`settings.LOGIN_URL <LOGIN_URL>`. For example, using the defaults, - add the following line to your URLconf:: - - (r'^accounts/login/$', 'django.contrib.auth.views.login'), - -.. function:: views.login(request, [template_name, redirect_field_name, authentication_form]) - - Here's what ``django.contrib.auth.views.login`` does: - - * If called via ``GET``, it displays a login form that POSTs to the - same URL. More on this in a bit. - - * If called via ``POST``, it tries to log the user in. If login is - successful, the view redirects to the URL specified in ``next``. If - ``next`` isn't provided, it redirects to - :setting:`settings.LOGIN_REDIRECT_URL <LOGIN_REDIRECT_URL>` (which - defaults to ``/accounts/profile/``). If login isn't successful, it - redisplays the login form. - - It's your responsibility to provide the login form in a template called - ``registration/login.html`` by default. This template gets passed four - template context variables: - - * ``form``: A :class:`~django.forms.Form` object representing the login - form. See the :doc:`forms documentation </topics/forms/index>` for - more on ``Form`` objects. - - * ``next``: The URL to redirect to after successful login. This may - contain a query string, too. - - * ``site``: The current :class:`~django.contrib.sites.models.Site`, - according to the :setting:`SITE_ID` setting. If you don't have the - site framework installed, this will be set to an instance of - :class:`~django.contrib.sites.models.RequestSite`, which derives the - site name and domain from the current - :class:`~django.http.HttpRequest`. - - * ``site_name``: An alias for ``site.name``. If you don't have the site - framework installed, this will be set to the value of - :attr:`request.META['SERVER_NAME'] <django.http.HttpRequest.META>`. - For more on sites, see :doc:`/ref/contrib/sites`. - - If you'd prefer not to call the template :file:`registration/login.html`, - you can pass the ``template_name`` parameter via the extra arguments to - the view in your URLconf. For example, this URLconf line would use - :file:`myapp/login.html` instead:: - - (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}), - - You can also specify the name of the ``GET`` field which contains the URL - to redirect to after login by passing ``redirect_field_name`` to the view. - By default, the field is called ``next``. - - Here's a sample :file:`registration/login.html` template you can use as a - starting point. It assumes you have a :file:`base.html` template that - defines a ``content`` block: - - .. code-block:: html+django - - {% extends "base.html" %} - - {% block content %} - - {% if form.errors %} - <p>Your username and password didn't match. Please try again.</p> - {% endif %} - - <form method="post" action="{% url django.contrib.auth.views.login %}"> - {% csrf_token %} - <table> - <tr> - <td>{{ form.username.label_tag }}</td> - <td>{{ form.username }}</td> - </tr> - <tr> - <td>{{ form.password.label_tag }}</td> - <td>{{ form.password }}</td> - </tr> - </table> - - <input type="submit" value="login" /> - <input type="hidden" name="next" value="{{ next }}" /> - </form> - - {% endblock %} - - .. versionadded:: 1.2 - - If you are using alternate authentication (see - :ref:`authentication-backends`) you can pass a custom authentication form - to the login view via the ``authentication_form`` parameter. This form must - accept a ``request`` keyword argument in its ``__init__`` method, and - provide a ``get_user`` method which returns the authenticated user object - (this method is only ever called after successful form validation). - - .. _forms documentation: ../forms/ - .. _site framework docs: ../sites/ - -Other built-in views --------------------- - -In addition to the :func:`~views.login` view, the authentication system -includes a few other useful built-in views located in -:mod:`django.contrib.auth.views`: - -.. function:: views.logout(request, [next_page, template_name, redirect_field_name]) - - Logs a user out. - - **Optional arguments:** - - * ``next_page``: The URL to redirect to after logout. - - * ``template_name``: The full name of a template to display after - logging the user out. This will default to - :file:`registration/logged_out.html` if no argument is supplied. - - * ``redirect_field_name``: The name of a ``GET`` field containing the - URL to redirect to after log out. Overrides ``next_page`` if the given - ``GET`` parameter is passed. - - **Template context:** - - * ``title``: The string "Logged out", localized. - -.. function:: views.logout_then_login(request[, login_url]) - - Logs a user out, then redirects to the login page. - - **Optional arguments:** - - * ``login_url``: The URL of the login page to redirect to. This will - default to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied. - -.. function:: views.password_change(request[, template_name, post_change_redirect, password_change_form]) - - Allows a user to change their password. - - **Optional arguments:** - - * ``template_name``: The full name of a template to use for - displaying the password change form. This will default to - :file:`registration/password_change_form.html` if not supplied. - - * ``post_change_redirect``: The URL to redirect to after a successful - password change. - - * .. versionadded:: 1.2 - - ``password_change_form``: A custom "change password" form which must - accept a ``user`` keyword argument. The form is responsible for - actually changing the user's password. - - - **Template context:** - - * ``form``: The password change form. - -.. function:: views.password_change_done(request[, template_name]) - - The page shown after a user has changed their password. - - **Optional arguments:** - - * ``template_name``: The full name of a template to use. This will - default to :file:`registration/password_change_done.html` if not - supplied. - -.. function:: views.password_reset(request[, is_admin_site, template_name, email_template_name, password_reset_form, token_generator, post_reset_redirect]) - - Allows a user to reset their password by generating a one-time use link - that can be used to reset the password, and sending that link to the - user's registered e-mail address. - - **Optional arguments:** - - * ``template_name``: The full name of a template to use for - displaying the password reset form. This will default to - :file:`registration/password_reset_form.html` if not supplied. - - * ``email_template_name``: The full name of a template to use for - generating the e-mail with the new password. This will default to - :file:`registration/password_reset_email.html` if not supplied. - - * ``password_reset_form``: Form that will be used to set the password. - Defaults to :class:`~django.contrib.auth.forms.PasswordResetForm`. - - * ``token_generator``: Instance of the class to check the password. This - will default to ``default_token_generator``, it's an instance of - ``django.contrib.auth.tokens.PasswordResetTokenGenerator``. - - * ``post_reset_redirect``: The URL to redirect to after a successful - password change. - - **Template context:** - - * ``form``: The form for resetting the user's password. - -.. function:: views.password_reset_done(request[, template_name]) - - The page shown after a user has reset their password. - - **Optional arguments:** - - * ``template_name``: The full name of a template to use. This will - default to :file:`registration/password_reset_done.html` if not - supplied. - -.. function:: views.redirect_to_login(next[, login_url, redirect_field_name]) - - Redirects to the login page, and then back to another URL after a - successful login. - - **Required arguments:** - - * ``next``: The URL to redirect to after a successful login. - - **Optional arguments:** - - * ``login_url``: The URL of the login page to redirect to. This will - default to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied. - - * ``redirect_field_name``: The name of a ``GET`` field containing the - URL to redirect to after log out. Overrides ``next`` if the given - ``GET`` parameter is passed. - -.. function:: password_reset_confirm(request[, uidb36, token, template_name, token_generator, set_password_form, post_reset_redirect]) - - Presents a form for entering a new password. - - **Optional arguments:** - - * ``uidb36``: The user's id encoded in base 36. This will default to - ``None``. - * ``token``: Token to check that the password is valid. This will default to ``None``. - * ``template_name``: The full name of a template to display the confirm - password view. Default value is :file:`registration/password_reset_confirm.html`. - * ``token_generator``: Instance of the class to check the password. This - will default to ``default_token_generator``, it's an instance of - ``django.contrib.auth.tokens.PasswordResetTokenGenerator``. - * ``set_password_form``: Form that will be used to set the password. - This will default to ``SetPasswordForm``. - * ``post_reset_redirect``: URL to redirect after the password reset - done. This will default to ``None``. - -.. function:: password_reset_complete(request[,template_name]) - - Presents a view which informs the user that the password has been - successfully changed. - - **Optional arguments:** - - * ``template_name``: The full name of a template to display the view. - This will default to :file:`registration/password_reset_complete.html`. - -Built-in forms --------------- - -.. module:: django.contrib.auth.forms - -If you don't want to use the built-in views, but want the convenience of not -having to write forms for this functionality, the authentication system -provides several built-in forms located in :mod:`django.contrib.auth.forms`: - -.. class:: AdminPasswordChangeForm - - A form used in the admin interface to change a user's password. - -.. class:: AuthenticationForm - - A form for logging a user in. - -.. class:: PasswordChangeForm - - A form for allowing a user to change their password. - -.. class:: PasswordResetForm - - A form for generating and e-mailing a one-time use link to reset a - user's password. - -.. class:: SetPasswordForm - - A form that lets a user change his/her password without entering the old - password. - -.. class:: UserChangeForm - - A form used in the admin interface to change a user's information and - permissions. - -.. class:: UserCreationForm - - A form for creating a new user. - -Limiting access to logged-in users that pass a test ---------------------------------------------------- - -.. currentmodule:: django.contrib.auth - -To limit access based on certain permissions or some other test, you'd do -essentially the same thing as described in the previous section. - -The simple way is to run your test on :attr:`request.user -<django.http.HttpRequest.user>` in the view directly. For example, this view -checks to make sure the user is logged in and has the permission -``polls.can_vote``:: - - def my_view(request): - if not request.user.has_perm('polls.can_vote'): - return HttpResponse("You can't vote in this poll.") - # ... - -.. function:: decorators.user_passes_test() - - As a shortcut, you can use the convenient ``user_passes_test`` decorator:: - - from django.contrib.auth.decorators import user_passes_test - - @user_passes_test(lambda u: u.has_perm('polls.can_vote')) - def my_view(request): - ... - - We're using this particular test as a relatively simple example. However, - if you just want to test whether a permission is available to a user, you - can use the :func:`~django.contrib.auth.decorators.permission_required()` - decorator, described later in this document. - - :func:`~django.contrib.auth.decorators.user_passes_test` takes a required - argument: a callable that takes a - :class:`~django.contrib.auth.models.User` object and returns ``True`` if - the user is allowed to view the page. Note that - :func:`~django.contrib.auth.decorators.user_passes_test` does not - automatically check that the :class:`~django.contrib.auth.models.User` is - not anonymous. - - :func:`~django.contrib.auth.decorators.user_passes_test()` takes an - optional ``login_url`` argument, which lets you specify the URL for your - login page (:setting:`settings.LOGIN_URL <LOGIN_URL>` by default). - - For example:: - - from django.contrib.auth.decorators import user_passes_test - - @user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/') - def my_view(request): - ... - -The permission_required decorator -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. function:: decorators.permission_required() - - It's a relatively common task to check whether a user has a particular - permission. For that reason, Django provides a shortcut for that case: the - :func:`~django.contrib.auth.decorators.permission_required()` decorator. - Using this decorator, the earlier example can be written as:: - - from django.contrib.auth.decorators import permission_required - - @permission_required('polls.can_vote') - def my_view(request): - ... - - As for the :meth:`User.has_perm` method, permission names take the form - ``"<app label>.<permission codename>"`` (i.e. ``polls.can_vote`` for a - permission on a model in the ``polls`` application). - - Note that :func:`~django.contrib.auth.decorators.permission_required()` - also takes an optional ``login_url`` parameter. Example:: - - from django.contrib.auth.decorators import permission_required - - @permission_required('polls.can_vote', login_url='/loginpage/') - def my_view(request): - ... - - As in the :func:`~decorators.login_required` decorator, ``login_url`` - defaults to :setting:`settings.LOGIN_URL <LOGIN_URL>`. - -Limiting access to generic views --------------------------------- - -To limit access to a :doc:`generic view </ref/generic-views>`, write a thin -wrapper around the view, and point your URLconf to your wrapper instead of the -generic view itself. For example:: - - from django.views.generic.date_based import object_detail - - @login_required - def limited_object_detail(*args, **kwargs): - return object_detail(*args, **kwargs) - -.. _permissions: - -Permissions -=========== - -Django comes with a simple permissions system. It provides a way to assign -permissions to specific users and groups of users. - -It's used by the Django admin site, but you're welcome to use it in your own -code. - -The Django admin site uses permissions as follows: - - * Access to view the "add" form and add an object is limited to users with - the "add" permission for that type of object. - * Access to view the change list, view the "change" form and change an - object is limited to users with the "change" permission for that type of - object. - * Access to delete an object is limited to users with the "delete" - permission for that type of object. - -Permissions are set globally per type of object, not per specific object -instance. For example, it's possible to say "Mary may change news stories," but -it's not currently possible to say "Mary may change news stories, but only the -ones she created herself" or "Mary may only change news stories that have a -certain status, publication date or ID." The latter functionality is something -Django developers are currently discussing. - -Default permissions -------------------- - -When ``django.contrib.auth`` is listed in your :setting:`INSTALLED_APPS` -setting, it will ensure that three default permissions -- add, change and -delete -- are created for each Django model defined in one of your installed -applications. - -These permissions will be created when you run :djadmin:`manage.py syncdb -<syncdb>`; the first time you run ``syncdb`` after adding -``django.contrib.auth`` to :setting:`INSTALLED_APPS`, the default permissions -will be created for all previously-installed models, as well as for any new -models being installed at that time. Afterward, it will create default -permissions for new models each time you run :djadmin:`manage.py syncdb -<syncdb>`. - -Assuming you have an application with an -:attr:`~django.db.models.Options.app_label` ``foo`` and a model named ``Bar``, -to test for basic permissions you should use: - - * add: ``user.has_perm('foo.add_bar')`` - * change: ``user.has_perm('foo.change_bar')`` - * delete: ``user.has_perm('foo.delete_bar')`` - -.. _custom-permissions: - -Custom permissions ------------------- - -To create custom permissions for a given model object, use the ``permissions`` -:ref:`model Meta attribute <meta-options>`. - -This example Task model creates three custom permissions, i.e., actions users -can or cannot do with Task instances, specific to your appication:: - - class Task(models.Model): - ... - class Meta: - permissions = ( - ("can_view", "Can see available tasks"), - ("can_change_status", "Can change the status of tasks"), - ("can_close", "Can remove a task by setting its status as closed"), - ) - -The only thing this does is create those extra permissions when you run -:djadmin:`manage.py syncdb <syncdb>`. Your code is in charge of checking the -value of these permissions when an user is trying to access the functionality -provided by the application (viewing tasks, changing the status of tasks, -closing tasks.) - -API reference -------------- - -.. class:: models.Permission - - Just like users, permissions are implemented in a Django model that lives - in `django/contrib/auth/models.py`_. - -.. _django/contrib/auth/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py - -Fields -~~~~~~ - -:class:`~django.contrib.auth.models.Permission` objects have the following -fields: - -.. attribute:: models.Permission.name - - Required. 50 characters or fewer. Example: ``'Can vote'``. - -.. attribute:: models.Permission.content_type - - Required. A reference to the ``django_content_type`` database table, which - contains a record for each installed Django model. - -.. attribute:: models.Permission.codename - - Required. 100 characters or fewer. Example: ``'can_vote'``. - -Methods -~~~~~~~ - -:class:`~django.contrib.auth.models.Permission` objects have the standard -data-access methods like any other :doc:`Django model </ref/models/instances>`. - -Authentication data in templates -================================ - -The currently logged-in user and his/her permissions are made available in the -:doc:`template context </ref/templates/api>` when you use -:class:`~django.template.context.RequestContext`. - -.. admonition:: Technicality - - Technically, these variables are only made available in the template context - if you use :class:`~django.template.context.RequestContext` *and* your - :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting contains - ``"django.contrib.auth.context_processors.auth"``, which is default. For - more, see the :ref:`RequestContext docs <subclassing-context-requestcontext>`. - -Users ------ - -When rendering a template :class:`~django.template.context.RequestContext`, the -currently logged-in user, either a :class:`~django.contrib.auth.models.User` -instance or an :class:`~django.contrib.auth.models.AnonymousUser` instance, is -stored in the template variable ``{{ user }}``: - -.. code-block:: html+django - - {% if user.is_authenticated %} - <p>Welcome, {{ user.username }}. Thanks for logging in.</p> - {% else %} - <p>Welcome, new user. Please log in.</p> - {% endif %} - -This template context variable is not available if a ``RequestContext`` is not -being used. - -Permissions ------------ - -The currently logged-in user's permissions are stored in the template variable -``{{ perms }}``. This is an instance of -:class:`django.core.context_processors.PermWrapper`, which is a -template-friendly proxy of permissions. - -In the ``{{ perms }}`` object, single-attribute lookup is a proxy to -:meth:`User.has_module_perms <django.contrib.auth.models.User.has_module_perms>`. -This example would display ``True`` if the logged-in user had any permissions -in the ``foo`` app:: - - {{ perms.foo }} - -Two-level-attribute lookup is a proxy to -:meth:`User.has_perm <django.contrib.auth.models.User.has_perm>`. This example -would display ``True`` if the logged-in user had the permission -``foo.can_vote``:: - - {{ perms.foo.can_vote }} - -Thus, you can check permissions in template ``{% if %}`` statements: - -.. code-block:: html+django - - {% if perms.foo %} - <p>You have permission to do something in the foo app.</p> - {% if perms.foo.can_vote %} - <p>You can vote!</p> - {% endif %} - {% if perms.foo.can_drive %} - <p>You can drive!</p> - {% endif %} - {% else %} - <p>You don't have permission to do anything in the foo app.</p> - {% endif %} - -Groups -====== - -Groups are a generic way of categorizing users so you can apply permissions, or -some other label, to those users. A user can belong to any number of groups. - -A user in a group automatically has the permissions granted to that group. For -example, if the group ``Site editors`` has the permission -``can_edit_home_page``, any user in that group will have that permission. - -Beyond permissions, groups are a convenient way to categorize users to give -them some label, or extended functionality. For example, you could create a -group ``'Special users'``, and you could write code that could, say, give them -access to a members-only portion of your site, or send them members-only e-mail -messages. - -Messages -======== - -.. deprecated:: 1.2 - This functionality will be removed in Django 1.4. You should use the - :doc:`messages framework </ref/contrib/messages>` for all new projects and - begin to update your existing code immediately. - -The message system is a lightweight way to queue messages for given users. - -A message is associated with a :class:`~django.contrib.auth.models.User`. -There's no concept of expiration or timestamps. - -Messages are used by the Django admin after successful actions. For example, -``"The poll Foo was created successfully."`` is a message. - -The API is simple: - -.. method:: models.User.message_set.create(message) - - To create a new message, use - ``user_obj.message_set.create(message='message_text')``. - - To retrieve/delete messages, use - :meth:`user_obj.get_and_delete_messages() <django.contrib.auth.models.User.get_and_delete_messages>`, - which returns a list of ``Message`` objects in the user's queue (if any) - and deletes the messages from the queue. - -In this example view, the system saves a message for the user after creating -a playlist:: - - def create_playlist(request, songs): - # Create the playlist with the given songs. - # ... - request.user.message_set.create(message="Your playlist was added successfully.") - return render_to_response("playlists/create.html", - context_instance=RequestContext(request)) - -When you use :class:`~django.template.context.RequestContext`, the currently -logged-in user and his/her messages are made available in the -:doc:`template context </ref/templates/api>` as the template variable -``{{ messages }}``. Here's an example of template code that displays messages: - -.. code-block:: html+django - - {% if messages %} - <ul> - {% for message in messages %} - <li>{{ message }}</li> - {% endfor %} - </ul> - {% endif %} - -.. versionchanged:: 1.2 - The ``messages`` template variable uses a backwards compatible method in the - :doc:`messages framework </ref/contrib/messages>` to retrieve messages from - both the user ``Message`` model and from the new framework. Unlike in - previous revisions, the messages will not be erased unless they are actually - displayed. - -Finally, note that this messages framework only works with users in the user -database. To send messages to anonymous users, use the -:doc:`messages framework </ref/contrib/messages>`. - -.. _authentication-backends: - -Other authentication sources -============================ - -The authentication that comes with Django is good enough for most common cases, -but you may have the need to hook into another authentication source -- that -is, another source of usernames and passwords or authentication methods. - -For example, your company may already have an LDAP setup that stores a username -and password for every employee. It'd be a hassle for both the network -administrator and the users themselves if users had separate accounts in LDAP -and the Django-based applications. - -So, to handle situations like this, the Django authentication system lets you -plug in other authentication sources. You can override Django's default -database-based scheme, or you can use the default system in tandem with other -systems. - -See the :doc:`authentication backend reference </ref/authbackends>` -for information on the authentication backends included with Django. - -Specifying authentication backends ----------------------------------- - -Behind the scenes, Django maintains a list of "authentication backends" that it -checks for authentication. When somebody calls -:func:`django.contrib.auth.authenticate()` -- as described in :ref:`How to log -a user in <how-to-log-a-user-in>` above -- Django tries authenticating across -all of its authentication backends. If the first authentication method fails, -Django tries the second one, and so on, until all backends have been attempted. - -The list of authentication backends to use is specified in the -:setting:`AUTHENTICATION_BACKENDS` setting. This should be a tuple of Python -path names that point to Python classes that know how to authenticate. These -classes can be anywhere on your Python path. - -By default, :setting:`AUTHENTICATION_BACKENDS` is set to:: - - ('django.contrib.auth.backends.ModelBackend',) - -That's the basic authentication scheme that checks the Django users database. - -The order of :setting:`AUTHENTICATION_BACKENDS` matters, so if the same -username and password is valid in multiple backends, Django will stop -processing at the first positive match. - -.. note:: - - Once a user has authenticated, Django stores which backend was used to - authenticate the user in the user's session, and re-uses the same backend - for subsequent authentication attempts for that user. This effectively means - that authentication sources are cached, so if you change - :setting:`AUTHENTICATION_BACKENDS`, you'll need to clear out session data if - you need to force users to re-authenticate using different methods. A simple - way to do that is simply to execute ``Session.objects.all().delete()``. - -Writing an authentication backend ---------------------------------- - -An authentication backend is a class that implements two methods: -``get_user(user_id)`` and ``authenticate(**credentials)``. - -The ``get_user`` method takes a ``user_id`` -- which could be a username, -database ID or whatever -- and returns a ``User`` object. - -The ``authenticate`` method takes credentials as keyword arguments. Most of -the time, it'll just look like this:: - - class MyBackend: - def authenticate(self, username=None, password=None): - # Check the username/password and return a User. - -But it could also authenticate a token, like so:: - - class MyBackend: - def authenticate(self, token=None): - # Check the token and return a User. - -Either way, ``authenticate`` should check the credentials it gets, and it -should return a ``User`` object that matches those credentials, if the -credentials are valid. If they're not valid, it should return ``None``. - -The Django admin system is tightly coupled to the Django ``User`` object -described at the beginning of this document. For now, the best way to deal with -this is to create a Django ``User`` object for each user that exists for your -backend (e.g., in your LDAP directory, your external SQL database, etc.) You -can either write a script to do this in advance, or your ``authenticate`` -method can do it the first time a user logs in. - -Here's an example backend that authenticates against a username and password -variable defined in your ``settings.py`` file and creates a Django ``User`` -object the first time a user authenticates:: - - from django.conf import settings - from django.contrib.auth.models import User, check_password - - class SettingsBackend: - """ - Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD. - - Use the login name, and a hash of the password. For example: - - ADMIN_LOGIN = 'admin' - ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de' - """ - def authenticate(self, username=None, password=None): - login_valid = (settings.ADMIN_LOGIN == username) - pwd_valid = check_password(password, settings.ADMIN_PASSWORD) - if login_valid and pwd_valid: - try: - user = User.objects.get(username=username) - except User.DoesNotExist: - # Create a new user. Note that we can set password - # to anything, because it won't be checked; the password - # from settings.py will. - user = User(username=username, password='get from settings.py') - user.is_staff = True - user.is_superuser = True - user.save() - return user - return None - - def get_user(self, user_id): - try: - return User.objects.get(pk=user_id) - except User.DoesNotExist: - return None - -Handling authorization in custom backends ------------------------------------------ - -Custom auth backends can provide their own permissions. - -The user model will delegate permission lookup functions -(:meth:`~django.contrib.auth.models.User.get_group_permissions()`, -:meth:`~django.contrib.auth.models.User.get_all_permissions()`, -:meth:`~django.contrib.auth.models.User.has_perm()`, and -:meth:`~django.contrib.auth.models.User.has_module_perms()`) to any -authentication backend that implements these functions. - -The permissions given to the user will be the superset of all permissions -returned by all backends. That is, Django grants a permission to a user that -any one backend grants. - -The simple backend above could implement permissions for the magic admin -fairly simply:: - - class SettingsBackend: - - # ... - - def has_perm(self, user_obj, perm): - if user_obj.username == settings.ADMIN_LOGIN: - return True - else: - return False - -This gives full permissions to the user granted access in the above example. -Notice that the backend auth functions all take the user object as an argument, -and they also accept the same arguments given to the associated -:class:`django.contrib.auth.models.User` functions. - -A full authorization implementation can be found in -`django/contrib/auth/backends.py`_, which is the default backend and queries -the ``auth_permission`` table most of the time. - -.. _django/contrib/auth/backends.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py - -Authorization for anonymous users -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionchanged:: 1.2 - -An anonymous user is one that is not authenticated i.e. they have provided no -valid authentication details. However, that does not necessarily mean they are -not authorized to do anything. At the most basic level, most Web sites -authorize anonymous users to browse most of the site, and many allow anonymous -posting of comments etc. - -Django's permission framework does not have a place to store permissions for -anonymous users. However, it has a foundation that allows custom authentication -backends to specify authorization for anonymous users. This is especially useful -for the authors of re-usable apps, who can delegate all questions of authorization -to the auth backend, rather than needing settings, for example, to control -anonymous access. - -To enable this in your own backend, you must set the class attribute -``supports_anonymous_user`` to ``True``. (This precaution is to maintain -compatibility with backends that assume that all user objects are actual -instances of the :class:`django.contrib.auth.models.User` class). With this -in place, :class:`django.contrib.auth.models.AnonymousUser` will delegate all -the relevant permission methods to the authentication backends. - -A nonexistent ``supports_anonymous_user`` attribute will raise a hidden -``PendingDeprecationWarning`` if used in Django 1.2. In Django 1.3, this -warning will be upgraded to a ``DeprecationWarning``, which will be displayed -loudly. Additionally ``supports_anonymous_user`` will be set to ``False``. -Django 1.4 will assume that every backend supports anonymous users being -passed to the authorization methods. - -Handling object permissions ---------------------------- - -Django's permission framework has a foundation for object permissions, though -there is no implementation for it in the core. That means that checking for -object permissions will always return ``False`` or an empty list (depending on -the check performed). - -To enable object permissions in your own -:doc:`authentication backend </ref/authbackends>` you'll just have -to allow passing an ``obj`` parameter to the permission methods and set the -``supports_object_permissions`` class attribute to ``True``. - -A nonexistent ``supports_object_permissions`` will raise a hidden -``PendingDeprecationWarning`` if used in Django 1.2. In Django 1.3, this -warning will be upgraded to a ``DeprecationWarning``, which will be displayed -loudly. Additionally ``supports_object_permissions`` will be set to ``False``. -Django 1.4 will assume that every backend supports object permissions and -won't check for the existence of ``supports_object_permissions``, which -means not supporting ``obj`` as a parameter will raise a ``TypeError``. diff --git a/parts/django/docs/topics/cache.txt b/parts/django/docs/topics/cache.txt deleted file mode 100644 index c18b811..0000000 --- a/parts/django/docs/topics/cache.txt +++ /dev/null @@ -1,917 +0,0 @@ -======================== -Django's cache framework -======================== - -A fundamental trade-off in dynamic Web sites is, well, they're dynamic. Each -time a user requests a page, the Web server makes all sorts of calculations -- -from database queries to template rendering to business logic -- to create the -page that your site's visitor sees. This is a lot more expensive, from a -processing-overhead perspective, than your standard -read-a-file-off-the-filesystem server arrangement. - -For most Web applications, this overhead isn't a big deal. Most Web -applications aren't washingtonpost.com or slashdot.org; they're simply small- -to medium-sized sites with so-so traffic. But for medium- to high-traffic -sites, it's essential to cut as much overhead as possible. - -That's where caching comes in. - -To cache something is to save the result of an expensive calculation so that -you don't have to perform the calculation next time. Here's some pseudocode -explaining how this would work for a dynamically generated Web page:: - - given a URL, try finding that page in the cache - if the page is in the cache: - return the cached page - else: - generate the page - save the generated page in the cache (for next time) - return the generated page - -Django comes with a robust cache system that lets you save dynamic pages so -they don't have to be calculated for each request. For convenience, Django -offers different levels of cache granularity: You can cache the output of -specific views, you can cache only the pieces that are difficult to produce, or -you can cache your entire site. - -Django also works well with "upstream" caches, such as `Squid -<http://www.squid-cache.org>`_ and browser-based caches. These are the types of -caches that you don't directly control but to which you can provide hints (via -HTTP headers) about which parts of your site should be cached, and how. - -Setting up the cache -==================== - -The cache system requires a small amount of setup. Namely, you have to tell it -where your cached data should live -- whether in a database, on the filesystem -or directly in memory. This is an important decision that affects your cache's -performance; yes, some cache types are faster than others. - -Your cache preference goes in the ``CACHE_BACKEND`` setting in your settings -file. Here's an explanation of all available values for ``CACHE_BACKEND``. - -Memcached ---------- - -By far the fastest, most efficient type of cache available to Django, Memcached -is an entirely memory-based cache framework originally developed to handle high -loads at LiveJournal.com and subsequently open-sourced by Danga Interactive. -It's used by sites such as Facebook and Wikipedia to reduce database access and -dramatically increase site performance. - -Memcached is available for free at http://memcached.org/. It runs as a -daemon and is allotted a specified amount of RAM. All it does is provide a -fast interface for adding, retrieving and deleting arbitrary data in the cache. -All data is stored directly in memory, so there's no overhead of database or -filesystem usage. - -After installing Memcached itself, you'll need to install -``python-memcached``, which provides Python bindings to Memcached. -This is available at ftp://ftp.tummy.com/pub/python-memcached/ - -.. versionchanged:: 1.2 - In Django 1.0 and 1.1, you could also use ``cmemcache`` as a binding. - However, support for this library was deprecated in 1.2 due to - a lack of maintenance on the ``cmemcache`` library itself. Support for - ``cmemcache`` will be removed completely in Django 1.4. - -To use Memcached with Django, set ``CACHE_BACKEND`` to -``memcached://ip:port/``, where ``ip`` is the IP address of the Memcached -daemon and ``port`` is the port on which Memcached is running. - -In this example, Memcached is running on localhost (127.0.0.1) port 11211:: - - CACHE_BACKEND = 'memcached://127.0.0.1:11211/' - -One excellent feature of Memcached is its ability to share cache over multiple -servers. This means you can run Memcached daemons on multiple machines, and the -program will treat the group of machines as a *single* cache, without the need -to duplicate cache values on each machine. To take advantage of this feature, -include all server addresses in ``CACHE_BACKEND``, separated by semicolons. - -In this example, the cache is shared over Memcached instances running on IP -address 172.19.26.240 and 172.19.26.242, both on port 11211:: - - CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/' - -In the following example, the cache is shared over Memcached instances running -on the IP addresses 172.19.26.240 (port 11211), 172.19.26.242 (port 11212), and -172.19.26.244 (port 11213):: - - CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11212;172.19.26.244:11213/' - -A final point about Memcached is that memory-based caching has one -disadvantage: Because the cached data is stored in memory, the data will be -lost if your server crashes. Clearly, memory isn't intended for permanent data -storage, so don't rely on memory-based caching as your only data storage. -Without a doubt, *none* of the Django caching backends should be used for -permanent storage -- they're all intended to be solutions for caching, not -storage -- but we point this out here because memory-based caching is -particularly temporary. - -Database caching ----------------- - -To use a database table as your cache backend, first create a cache table in -your database by running this command:: - - python manage.py createcachetable [cache_table_name] - -...where ``[cache_table_name]`` is the name of the database table to create. -(This name can be whatever you want, as long as it's a valid table name that's -not already being used in your database.) This command creates a single table -in your database that is in the proper format that Django's database-cache -system expects. - -Once you've created that database table, set your ``CACHE_BACKEND`` setting to -``"db://tablename"``, where ``tablename`` is the name of the database table. -In this example, the cache table's name is ``my_cache_table``:: - - CACHE_BACKEND = 'db://my_cache_table' - -The database caching backend uses the same database as specified in your -settings file. You can't use a different database backend for your cache table. - -Database caching works best if you've got a fast, well-indexed database server. - -Database caching and multiple databases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you use database caching with multiple databases, you'll also need -to set up routing instructions for your database cache table. For the -purposes of routing, the database cache table appears as a model named -``CacheEntry``, in an application named ``django_cache``. This model -won't appear in the models cache, but the model details can be used -for routing purposes. - -For example, the following router would direct all cache read -operations to ``cache_slave``, and all write operations to -``cache_master``. The cache table will only be synchronized onto -``cache_master``:: - - class CacheRouter(object): - """A router to control all database cache operations""" - - def db_for_read(self, model, **hints): - "All cache read operations go to the slave" - if model._meta.app_label in ('django_cache',): - return 'cache_slave' - return None - - def db_for_write(self, model, **hints): - "All cache write operations go to master" - if model._meta.app_label in ('django_cache',): - return 'cache_master' - return None - - def allow_syncdb(self, db, model): - "Only synchronize the cache model on master" - if model._meta.app_label in ('django_cache',): - return db == 'cache_master' - return None - -If you don't specify routing directions for the database cache model, -the cache backend will use the ``default`` database. - -Of course, if you don't use the database cache backend, you don't need -to worry about providing routing instructions for the database cache -model. - -Filesystem caching ------------------- - -To store cached items on a filesystem, use the ``"file://"`` cache type for -``CACHE_BACKEND``. For example, to store cached data in ``/var/tmp/django_cache``, -use this setting:: - - CACHE_BACKEND = 'file:///var/tmp/django_cache' - -Note that there are three forward slashes toward the beginning of that example. -The first two are for ``file://``, and the third is the first character of the -directory path, ``/var/tmp/django_cache``. If you're on Windows, put the -drive letter after the ``file://``, like this:: - - file://c:/foo/bar - -The directory path should be absolute -- that is, it should start at the root -of your filesystem. It doesn't matter whether you put a slash at the end of the -setting. - -Make sure the directory pointed-to by this setting exists and is readable and -writable by the system user under which your Web server runs. Continuing the -above example, if your server runs as the user ``apache``, make sure the -directory ``/var/tmp/django_cache`` exists and is readable and writable by the -user ``apache``. - -Each cache value will be stored as a separate file whose contents are the -cache data saved in a serialized ("pickled") format, using Python's ``pickle`` -module. Each file's name is the cache key, escaped for safe filesystem use. - -Local-memory caching --------------------- - -If you want the speed advantages of in-memory caching but don't have the -capability of running Memcached, consider the local-memory cache backend. This -cache is multi-process and thread-safe. To use it, set ``CACHE_BACKEND`` to -``"locmem://"``. For example:: - - CACHE_BACKEND = 'locmem://' - -Note that each process will have its own private cache instance, which means no -cross-process caching is possible. This obviously also means the local memory -cache isn't particularly memory-efficient, so it's probably not a good choice -for production environments. It's nice for development. - -Dummy caching (for development) -------------------------------- - -Finally, Django comes with a "dummy" cache that doesn't actually cache -- it -just implements the cache interface without doing anything. - -This is useful if you have a production site that uses heavy-duty caching in -various places but a development/test environment where you don't want to cache -and don't want to have to change your code to special-case the latter. To -activate dummy caching, set ``CACHE_BACKEND`` like so:: - - CACHE_BACKEND = 'dummy://' - -Using a custom cache backend ----------------------------- - -.. versionadded:: 1.0 - -While Django includes support for a number of cache backends out-of-the-box, -sometimes you might want to use a customized cache backend. To use an external -cache backend with Django, use a Python import path as the scheme portion (the -part before the initial colon) of the ``CACHE_BACKEND`` URI, like so:: - - CACHE_BACKEND = 'path.to.backend://' - -If you're building your own backend, you can use the standard cache backends -as reference implementations. You'll find the code in the -``django/core/cache/backends/`` directory of the Django source. - -Note: Without a really compelling reason, such as a host that doesn't support -them, you should stick to the cache backends included with Django. They've -been well-tested and are easy to use. - -CACHE_BACKEND arguments ------------------------ - -Each cache backend may take arguments. They're given in query-string style on -the ``CACHE_BACKEND`` setting. Valid arguments are as follows: - - * ``timeout``: The default timeout, in seconds, to use for the cache. - This argument defaults to 300 seconds (5 minutes). - - * ``max_entries``: For the ``locmem``, ``filesystem`` and ``database`` - backends, the maximum number of entries allowed in the cache before old - values are deleted. This argument defaults to 300. - - * ``cull_frequency``: The fraction of entries that are culled when - ``max_entries`` is reached. The actual ratio is ``1/cull_frequency``, so - set ``cull_frequency=2`` to cull half of the entries when ``max_entries`` - is reached. - - A value of ``0`` for ``cull_frequency`` means that the entire cache will - be dumped when ``max_entries`` is reached. This makes culling *much* - faster at the expense of more cache misses. - -In this example, ``timeout`` is set to ``60``:: - - CACHE_BACKEND = "memcached://127.0.0.1:11211/?timeout=60" - -In this example, ``timeout`` is ``30`` and ``max_entries`` is ``400``:: - - CACHE_BACKEND = "locmem://?timeout=30&max_entries=400" - -Invalid arguments are silently ignored, as are invalid values of known -arguments. - -The per-site cache -================== - -.. versionchanged:: 1.0 - (previous versions of Django only provided a single ``CacheMiddleware`` instead - of the two pieces described below). - -Once the cache is set up, the simplest way to use caching is to cache your -entire site. You'll need to add -``'django.middleware.cache.UpdateCacheMiddleware'`` and -``'django.middleware.cache.FetchFromCacheMiddleware'`` to your -``MIDDLEWARE_CLASSES`` setting, as in this example:: - - MIDDLEWARE_CLASSES = ( - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware', - ) - -.. note:: - - No, that's not a typo: the "update" middleware must be first in the list, - and the "fetch" middleware must be last. The details are a bit obscure, but - see `Order of MIDDLEWARE_CLASSES`_ below if you'd like the full story. - -Then, add the following required settings to your Django settings file: - -* ``CACHE_MIDDLEWARE_SECONDS`` -- The number of seconds each page should be - cached. -* ``CACHE_MIDDLEWARE_KEY_PREFIX`` -- If the cache is shared across multiple - sites using the same Django installation, set this to the name of the site, - or some other string that is unique to this Django instance, to prevent key - collisions. Use an empty string if you don't care. - -The cache middleware caches every page that doesn't have GET or POST -parameters. Optionally, if the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting is -``True``, only anonymous requests (i.e., not those made by a logged-in user) -will be cached. This is a simple and effective way of disabling caching for any -user-specific pages (include Django's admin interface). Note that if you use -``CACHE_MIDDLEWARE_ANONYMOUS_ONLY``, you should make sure you've activated -``AuthenticationMiddleware``. - -Additionally, the cache middleware automatically sets a few headers in each -:class:`~django.http.HttpResponse`: - - * Sets the ``Last-Modified`` header to the current date/time when a fresh - (uncached) version of the page is requested. - - * Sets the ``Expires`` header to the current date/time plus the defined - ``CACHE_MIDDLEWARE_SECONDS``. - - * Sets the ``Cache-Control`` header to give a max age for the page -- - again, from the ``CACHE_MIDDLEWARE_SECONDS`` setting. - -See :doc:`/topics/http/middleware` for more on middleware. - -.. versionadded:: 1.0 - -If a view sets its own cache expiry time (i.e. it has a ``max-age`` section in -its ``Cache-Control`` header) then the page will be cached until the expiry -time, rather than ``CACHE_MIDDLEWARE_SECONDS``. Using the decorators in -``django.views.decorators.cache`` you can easily set a view's expiry time -(using the ``cache_control`` decorator) or disable caching for a view (using -the ``never_cache`` decorator). See the `using other headers`__ section for -more on these decorators. - -.. _i18n-cache-key: - -.. versionadded:: 1.2 - -If :setting:`USE_I18N` is set to ``True`` then the generated cache key will -include the name of the active :term:`language<language code>`. -This allows you to easily cache multilingual sites without having to create -the cache key yourself. - -See :doc:`/topics/i18n/deployment` for more on how Django discovers the active -language. - -__ `Controlling cache: Using other headers`_ - -The per-view cache -================== - -A more granular way to use the caching framework is by caching the output of -individual views. ``django.views.decorators.cache`` defines a ``cache_page`` -decorator that will automatically cache the view's response for you. It's easy -to use:: - - from django.views.decorators.cache import cache_page - - @cache_page(60 * 15) - def my_view(request): - ... - -``cache_page`` takes a single argument: the cache timeout, in seconds. In the -above example, the result of the ``my_view()`` view will be cached for 15 -minutes. (Note that we've written it as ``60 * 15`` for the purpose of -readability. ``60 * 15`` will be evaluated to ``900`` -- that is, 15 minutes -multiplied by 60 seconds per minute.) - -The per-view cache, like the per-site cache, is keyed off of the URL. If -multiple URLs point at the same view, each URL will be cached separately. -Continuing the ``my_view`` example, if your URLconf looks like this:: - - urlpatterns = ('', - (r'^foo/(\d{1,2})/$', my_view), - ) - -then requests to ``/foo/1/`` and ``/foo/23/`` will be cached separately, as -you may expect. But once a particular URL (e.g., ``/foo/23/``) has been -requested, subsequent requests to that URL will use the cache. - -``cache_page`` can also take an optional keyword argument, ``key_prefix``, which -works in the same way as the ``CACHE_MIDDLEWARE_KEY_PREFIX`` setting for the -middleware. It can be used like this:: - - @cache_page(60 * 15, key_prefix="site1") - def my_view(request): - ... - -Specifying per-view cache in the URLconf ----------------------------------------- - -The examples in the previous section have hard-coded the fact that the view is -cached, because ``cache_page`` alters the ``my_view`` function in place. This -approach couples your view to the cache system, which is not ideal for several -reasons. For instance, you might want to reuse the view functions on another, -cache-less site, or you might want to distribute the views to people who might -want to use them without being cached. The solution to these problems is to -specify the per-view cache in the URLconf rather than next to the view functions -themselves. - -Doing so is easy: simply wrap the view function with ``cache_page`` when you -refer to it in the URLconf. Here's the old URLconf from earlier:: - - urlpatterns = ('', - (r'^foo/(\d{1,2})/$', my_view), - ) - -Here's the same thing, with ``my_view`` wrapped in ``cache_page``:: - - from django.views.decorators.cache import cache_page - - urlpatterns = ('', - (r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)), - ) - -If you take this approach, don't forget to import ``cache_page`` within your -URLconf. - -Template fragment caching -========================= - -.. versionadded:: 1.0 - -If you're after even more control, you can also cache template fragments using -the ``cache`` template tag. To give your template access to this tag, put -``{% load cache %}`` near the top of your template. - -The ``{% cache %}`` template tag caches the contents of the block for a given -amount of time. It takes at least two arguments: the cache timeout, in seconds, -and the name to give the cache fragment. For example: - -.. code-block:: html+django - - {% load cache %} - {% cache 500 sidebar %} - .. sidebar .. - {% endcache %} - -Sometimes you might want to cache multiple copies of a fragment depending on -some dynamic data that appears inside the fragment. For example, you might want a -separate cached copy of the sidebar used in the previous example for every user -of your site. Do this by passing additional arguments to the ``{% cache %}`` -template tag to uniquely identify the cache fragment: - -.. code-block:: html+django - - {% load cache %} - {% cache 500 sidebar request.user.username %} - .. sidebar for logged in user .. - {% endcache %} - -It's perfectly fine to specify more than one argument to identify the fragment. -Simply pass as many arguments to ``{% cache %}`` as you need. - -If :setting:`USE_I18N` is set to ``True`` the per-site middleware cache will -:ref:`respect the active language<i18n-cache-key>`. For the ``cache`` template -tag you could use one of the -:ref:`translation-specific variables<template-translation-vars>` available in -templates to archieve the same result: - -.. code-block:: html+django - - {% load i18n %} - {% load cache %} - - {% get_current_language as LANGUAGE_CODE %} - - {% cache 600 welcome LANGUAGE_CODE %} - {% trans "Welcome to example.com" %} - {% endcache %} - -The cache timeout can be a template variable, as long as the template variable -resolves to an integer value. For example, if the template variable -``my_timeout`` is set to the value ``600``, then the following two examples are -equivalent: - -.. code-block:: html+django - - {% cache 600 sidebar %} ... {% endcache %} - {% cache my_timeout sidebar %} ... {% endcache %} - -This feature is useful in avoiding repetition in templates. You can set the -timeout in a variable, in one place, and just reuse that value. - -The low-level cache API -======================= - -.. highlight:: python - -Sometimes, caching an entire rendered page doesn't gain you very much and is, -in fact, inconvenient overkill. - -Perhaps, for instance, your site includes a view whose results depend on -several expensive queries, the results of which change at different intervals. -In this case, it would not be ideal to use the full-page caching that the -per-site or per-view cache strategies offer, because you wouldn't want to -cache the entire result (since some of the data changes often), but you'd still -want to cache the results that rarely change. - -For cases like this, Django exposes a simple, low-level cache API. You can use -this API to store objects in the cache with any level of granularity you like. -You can cache any Python object that can be pickled safely: strings, -dictionaries, lists of model objects, and so forth. (Most common Python objects -can be pickled; refer to the Python documentation for more information about -pickling.) - -The cache module, ``django.core.cache``, has a ``cache`` object that's -automatically created from the ``CACHE_BACKEND`` setting:: - - >>> from django.core.cache import cache - -The basic interface is ``set(key, value, timeout)`` and ``get(key)``:: - - >>> cache.set('my_key', 'hello, world!', 30) - >>> cache.get('my_key') - 'hello, world!' - -The ``timeout`` argument is optional and defaults to the ``timeout`` -argument in the ``CACHE_BACKEND`` setting (explained above). It's the number of -seconds the value should be stored in the cache. - -If the object doesn't exist in the cache, ``cache.get()`` returns ``None``:: - - # Wait 30 seconds for 'my_key' to expire... - - >>> cache.get('my_key') - None - -We advise against storing the literal value ``None`` in the cache, because you -won't be able to distinguish between your stored ``None`` value and a cache -miss signified by a return value of ``None``. - -``cache.get()`` can take a ``default`` argument. This specifies which value to -return if the object doesn't exist in the cache:: - - >>> cache.get('my_key', 'has expired') - 'has expired' - -.. versionadded:: 1.0 - -To add a key only if it doesn't already exist, use the ``add()`` method. -It takes the same parameters as ``set()``, but it will not attempt to -update the cache if the key specified is already present:: - - >>> cache.set('add_key', 'Initial value') - >>> cache.add('add_key', 'New value') - >>> cache.get('add_key') - 'Initial value' - -If you need to know whether ``add()`` stored a value in the cache, you can -check the return value. It will return ``True`` if the value was stored, -``False`` otherwise. - -There's also a ``get_many()`` interface that only hits the cache once. -``get_many()`` returns a dictionary with all the keys you asked for that -actually exist in the cache (and haven't expired):: - - >>> cache.set('a', 1) - >>> cache.set('b', 2) - >>> cache.set('c', 3) - >>> cache.get_many(['a', 'b', 'c']) - {'a': 1, 'b': 2, 'c': 3} - -.. versionadded:: 1.2 - -To set multiple values more efficiently, use ``set_many()`` to pass a dictionary -of key-value pairs:: - - >>> cache.set_many({'a': 1, 'b': 2, 'c': 3}) - >>> cache.get_many(['a', 'b', 'c']) - {'a': 1, 'b': 2, 'c': 3} - -Like ``cache.set()``, ``set_many()`` takes an optional ``timeout`` parameter. - -You can delete keys explicitly with ``delete()``. This is an easy way of -clearing the cache for a particular object:: - - >>> cache.delete('a') - -.. versionadded:: 1.2 - -If you want to clear a bunch of keys at once, ``delete_many()`` can take a list -of keys to be cleared:: - - >>> cache.delete_many(['a', 'b', 'c']) - -.. versionadded:: 1.2 - -Finally, if you want to delete all the keys in the cache, use -``cache.clear()``. Be careful with this; ``clear()`` will remove *everything* -from the cache, not just the keys set by your application. :: - - >>> cache.clear() - -.. versionadded:: 1.1 - -You can also increment or decrement a key that already exists using the -``incr()`` or ``decr()`` methods, respectively. By default, the existing cache -value will incremented or decremented by 1. Other increment/decrement values -can be specified by providing an argument to the increment/decrement call. A -ValueError will be raised if you attempt to increment or decrement a -nonexistent cache key.:: - - >>> cache.set('num', 1) - >>> cache.incr('num') - 2 - >>> cache.incr('num', 10) - 12 - >>> cache.decr('num') - 11 - >>> cache.decr('num', 5) - 6 - -.. note:: - - ``incr()``/``decr()`` methods are not guaranteed to be atomic. On those - backends that support atomic increment/decrement (most notably, the - memcached backend), increment and decrement operations will be atomic. - However, if the backend doesn't natively provide an increment/decrement - operation, it will be implemented using a two-step retrieve/update. - -Cache key warnings ------------------- - -.. versionadded:: 1.3 - -Memcached, the most commonly-used production cache backend, does not allow -cache keys longer than 250 characters or containing whitespace or control -characters, and using such keys will cause an exception. To encourage -cache-portable code and minimize unpleasant surprises, the other built-in cache -backends issue a warning (``django.core.cache.backends.base.CacheKeyWarning``) -if a key is used that would cause an error on memcached. - -If you are using a production backend that can accept a wider range of keys (a -custom backend, or one of the non-memcached built-in backends), and want to use -this wider range without warnings, you can silence ``CacheKeyWarning`` with -this code in the ``management`` module of one of your -:setting:`INSTALLED_APPS`:: - - import warnings - - from django.core.cache import CacheKeyWarning - - warnings.simplefilter("ignore", CacheKeyWarning) - -If you want to instead provide custom key validation logic for one of the -built-in backends, you can subclass it, override just the ``validate_key`` -method, and follow the instructions for `using a custom cache backend`_. For -instance, to do this for the ``locmem`` backend, put this code in a module:: - - from django.core.cache.backends.locmem import CacheClass as LocMemCacheClass - - class CacheClass(LocMemCacheClass): - def validate_key(self, key): - """Custom validation, raising exceptions or warnings as needed.""" - # ... - -...and use the dotted Python path to this module as the scheme portion of your -:setting:`CACHE_BACKEND`. - -Upstream caches -=============== - -So far, this document has focused on caching your *own* data. But another type -of caching is relevant to Web development, too: caching performed by "upstream" -caches. These are systems that cache pages for users even before the request -reaches your Web site. - -Here are a few examples of upstream caches: - - * Your ISP may cache certain pages, so if you requested a page from - http://example.com/, your ISP would send you the page without having to - access example.com directly. The maintainers of example.com have no - knowledge of this caching; the ISP sits between example.com and your Web - browser, handling all of the caching transparently. - - * Your Django Web site may sit behind a *proxy cache*, such as Squid Web - Proxy Cache (http://www.squid-cache.org/), that caches pages for - performance. In this case, each request first would be handled by the - proxy, and it would be passed to your application only if needed. - - * Your Web browser caches pages, too. If a Web page sends out the - appropriate headers, your browser will use the local cached copy for - subsequent requests to that page, without even contacting the Web page - again to see whether it has changed. - -Upstream caching is a nice efficiency boost, but there's a danger to it: -Many Web pages' contents differ based on authentication and a host of other -variables, and cache systems that blindly save pages based purely on URLs could -expose incorrect or sensitive data to subsequent visitors to those pages. - -For example, say you operate a Web e-mail system, and the contents of the -"inbox" page obviously depend on which user is logged in. If an ISP blindly -cached your site, then the first user who logged in through that ISP would have -his user-specific inbox page cached for subsequent visitors to the site. That's -not cool. - -Fortunately, HTTP provides a solution to this problem. A number of HTTP headers -exist to instruct upstream caches to differ their cache contents depending on -designated variables, and to tell caching mechanisms not to cache particular -pages. We'll look at some of these headers in the sections that follow. - -Using Vary headers -================== - -The ``Vary`` header defines which request headers a cache -mechanism should take into account when building its cache key. For example, if -the contents of a Web page depend on a user's language preference, the page is -said to "vary on language." - -By default, Django's cache system creates its cache keys using the requested -path (e.g., ``"/stories/2005/jun/23/bank_robbed/"``). This means every request -to that URL will use the same cached version, regardless of user-agent -differences such as cookies or language preferences. However, if this page -produces different content based on some difference in request headers -- such -as a cookie, or a language, or a user-agent -- you'll need to use the ``Vary`` -header to tell caching mechanisms that the page output depends on those things. - -To do this in Django, use the convenient ``vary_on_headers`` view decorator, -like so:: - - from django.views.decorators.vary import vary_on_headers - - @vary_on_headers('User-Agent') - def my_view(request): - # ... - -In this case, a caching mechanism (such as Django's own cache middleware) will -cache a separate version of the page for each unique user-agent. - -The advantage to using the ``vary_on_headers`` decorator rather than manually -setting the ``Vary`` header (using something like -``response['Vary'] = 'user-agent'``) is that the decorator *adds* to the -``Vary`` header (which may already exist), rather than setting it from scratch -and potentially overriding anything that was already in there. - -You can pass multiple headers to ``vary_on_headers()``:: - - @vary_on_headers('User-Agent', 'Cookie') - def my_view(request): - # ... - -This tells upstream caches to vary on *both*, which means each combination of -user-agent and cookie will get its own cache value. For example, a request with -the user-agent ``Mozilla`` and the cookie value ``foo=bar`` will be considered -different from a request with the user-agent ``Mozilla`` and the cookie value -``foo=ham``. - -Because varying on cookie is so common, there's a ``vary_on_cookie`` -decorator. These two views are equivalent:: - - @vary_on_cookie - def my_view(request): - # ... - - @vary_on_headers('Cookie') - def my_view(request): - # ... - -The headers you pass to ``vary_on_headers`` are not case sensitive; -``"User-Agent"`` is the same thing as ``"user-agent"``. - -You can also use a helper function, ``django.utils.cache.patch_vary_headers``, -directly. This function sets, or adds to, the ``Vary header``. For example:: - - from django.utils.cache import patch_vary_headers - - def my_view(request): - # ... - response = render_to_response('template_name', context) - patch_vary_headers(response, ['Cookie']) - return response - -``patch_vary_headers`` takes an :class:`~django.http.HttpResponse` instance as -its first argument and a list/tuple of case-insensitive header names as its -second argument. - -For more on Vary headers, see the `official Vary spec`_. - -.. _`official Vary spec`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44 - -Controlling cache: Using other headers -====================================== - -Other problems with caching are the privacy of data and the question of where -data should be stored in a cascade of caches. - -A user usually faces two kinds of caches: his or her own browser cache (a -private cache) and his or her provider's cache (a public cache). A public cache -is used by multiple users and controlled by someone else. This poses problems -with sensitive data--you don't want, say, your bank account number stored in a -public cache. So Web applications need a way to tell caches which data is -private and which is public. - -The solution is to indicate a page's cache should be "private." To do this in -Django, use the ``cache_control`` view decorator. Example:: - - from django.views.decorators.cache import cache_control - - @cache_control(private=True) - def my_view(request): - # ... - -This decorator takes care of sending out the appropriate HTTP header behind the -scenes. - -There are a few other ways to control cache parameters. For example, HTTP -allows applications to do the following: - - * Define the maximum time a page should be cached. - - * Specify whether a cache should always check for newer versions, only - delivering the cached content when there are no changes. (Some caches - might deliver cached content even if the server page changed, simply - because the cache copy isn't yet expired.) - -In Django, use the ``cache_control`` view decorator to specify these cache -parameters. In this example, ``cache_control`` tells caches to revalidate the -cache on every access and to store cached versions for, at most, 3,600 seconds:: - - from django.views.decorators.cache import cache_control - - @cache_control(must_revalidate=True, max_age=3600) - def my_view(request): - # ... - -Any valid ``Cache-Control`` HTTP directive is valid in ``cache_control()``. -Here's a full list: - - * ``public=True`` - * ``private=True`` - * ``no_cache=True`` - * ``no_transform=True`` - * ``must_revalidate=True`` - * ``proxy_revalidate=True`` - * ``max_age=num_seconds`` - * ``s_maxage=num_seconds`` - -For explanation of Cache-Control HTTP directives, see the `Cache-Control spec`_. - -(Note that the caching middleware already sets the cache header's max-age with -the value of the :setting:`CACHE_MIDDLEWARE_SECONDS` setting. If you use a custom -``max_age`` in a ``cache_control`` decorator, the decorator will take -precedence, and the header values will be merged correctly.) - -If you want to use headers to disable caching altogether, -``django.views.decorators.cache.never_cache`` is a view decorator that adds -headers to ensure the response won't be cached by browsers or other caches. -Example:: - - from django.views.decorators.cache import never_cache - - @never_cache - def myview(request): - # ... - -.. _`Cache-Control spec`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 - -Other optimizations -=================== - -Django comes with a few other pieces of middleware that can help optimize your -site's performance: - - * ``django.middleware.http.ConditionalGetMiddleware`` adds support for - modern browsers to conditionally GET responses based on the ``ETag`` - and ``Last-Modified`` headers. - - * ``django.middleware.gzip.GZipMiddleware`` compresses responses for all - moderns browsers, saving bandwidth and transfer time. - -Order of MIDDLEWARE_CLASSES -=========================== - -If you use caching middleware, it's important to put each half in the right -place within the ``MIDDLEWARE_CLASSES`` setting. That's because the cache -middleware needs to know which headers by which to vary the cache storage. -Middleware always adds something to the ``Vary`` response header when it can. - -``UpdateCacheMiddleware`` runs during the response phase, where middleware is -run in reverse order, so an item at the top of the list runs *last* during the -response phase. Thus, you need to make sure that ``UpdateCacheMiddleware`` -appears *before* any other middleware that might add something to the ``Vary`` -header. The following middleware modules do so: - - * ``SessionMiddleware`` adds ``Cookie`` - * ``GZipMiddleware`` adds ``Accept-Encoding`` - * ``LocaleMiddleware`` adds ``Accept-Language`` - -``FetchFromCacheMiddleware``, on the other hand, runs during the request phase, -where middleware is applied first-to-last, so an item at the top of the list -runs *first* during the request phase. The ``FetchFromCacheMiddleware`` also -needs to run after other middleware updates the ``Vary`` header, so -``FetchFromCacheMiddleware`` must be *after* any item that does so. - diff --git a/parts/django/docs/topics/conditional-view-processing.txt b/parts/django/docs/topics/conditional-view-processing.txt deleted file mode 100644 index c631a13..0000000 --- a/parts/django/docs/topics/conditional-view-processing.txt +++ /dev/null @@ -1,199 +0,0 @@ -=========================== -Conditional View Processing -=========================== - -.. versionadded:: 1.1 - -HTTP clients can send a number of headers to tell the server about copies of a -resource that they have already seen. This is commonly used when retrieving a -Web page (using an HTTP ``GET`` request) to avoid sending all the data for -something the client has already retrieved. However, the same headers can be -used for all HTTP methods (``POST``, ``PUT``, ``DELETE``, etc). - -For each page (response) that Django sends back from a view, it might provide -two HTTP headers: the ``ETag`` header and the ``Last-Modified`` header. These -headers are optional on HTTP responses. They can be set by your view function, -or you can rely on the :class:`~django.middleware.common.CommonMiddleware` -middleware to set the ``ETag`` header. - -When the client next requests the same resource, it might send along a header -such as `If-modified-since`_, containing the date of the last modification -time it was sent, or `If-none-match`_, containing the ``ETag`` it was sent. -If the current version of the page matches the ``ETag`` sent by the client, or -if the resource has not been modified, a 304 status code can be sent back, -instead of a full response, telling the client that nothing has changed. - -.. _If-none-match: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26 -.. _If-modified-since: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25 - -When you need more fine-grained control you may use per-view conditional -processing functions. - -.. conditional-decorators: - -The ``condition`` decorator -=========================== - -Sometimes (in fact, quite often) you can create functions to rapidly compute the ETag_ -value or the last-modified time for a resource, **without** needing to do all -the computations needed to construct the full view. Django can then use these -functions to provide an "early bailout" option for the view processing. -Telling the client that the content has not been modified since the last -request, perhaps. - -.. _ETag: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.11 - -These two functions are passed as parameters the -``django.views.decorators.http.condition`` decorator. This decorator uses -the two functions (you only need to supply one, if you can't compute both -quantities easily and quickly) to work out if the headers in the HTTP request -match those on the resource. If they don't match, a new copy of the resource -must be computed and your normal view is called. - -The ``condition`` decorator's signature looks like this:: - - condition(etag_func=None, last_modified_func=None) - -The two functions, to compute the ETag and the last modified time, will be -passed the incoming ``request`` object and the same parameters, in the same -order, as the view function they are helping to wrap. The function passed -``last_modified_func`` should return a standard datetime value specifying the -last time the resource was modified, or ``None`` if the resource doesn't -exist. The function passed to the ``etag`` decorator should return a string -representing the `Etag`_ for the resource, or ``None`` if it doesn't exist. - -Using this feature usefully is probably best explained with an example. -Suppose you have this pair of models, representing a simple blog system:: - - import datetime - from django.db import models - - class Blog(models.Model): - ... - - class Entry(models.Model): - blog = models.ForeignKey(Blog) - published = models.DateTimeField(default=datetime.datetime.now) - ... - -If the front page, displaying the latest blog entries, only changes when you -add a new blog entry, you can compute the last modified time very quickly. You -need the latest ``published`` date for every entry associated with that blog. -One way to do this would be:: - - def latest_entry(request, blog_id): - return Entry.objects.filter(blog=blog_id).latest("published").published - -You can then use this function to provide early detection of an unchanged page -for your front page view:: - - from django.views.decorators.http import condition - - @condition(last_modified_func=latest_entry) - def front_page(request, blog_id): - ... - -Shortcuts for only computing one value -====================================== - -As a general rule, if you can provide functions to compute *both* the ETag and -the last modified time, you should do so. You don't know which headers any -given HTTP client will send you, so be prepared to handle both. However, -sometimes only one value is easy to compute and Django provides decorators -that handle only ETag or only last-modified computations. - -The ``django.views.decorators.http.etag`` and -``django.views.decorators.http.last_modified`` decorators are passed the same -type of functions as the ``condition`` decorator. Their signatures are:: - - etag(etag_func) - last_modified(last_modified_func) - -We could write the earlier example, which only uses a last-modified function, -using one of these decorators:: - - @last_modified(latest_entry) - def front_page(request, blog_id): - ... - -...or:: - - def front_page(request, blog_id): - ... - front_page = last_modified(latest_entry)(front_page) - -Use ``condition`` when testing both conditions ------------------------------------------------- - -It might look nicer to some people to try and chain the ``etag`` and -``last_modified`` decorators if you want to test both preconditions. However, -this would lead to incorrect behavior. - -:: - - # Bad code. Don't do this! - @etag(etag_func) - @last_modified(last_modified_func) - def my_view(request): - # ... - - # End of bad code. - -The first decorator doesn't know anything about the second and might -answer that the response is not modified even if the second decorators would -determine otherwise. The ``condition`` decorator uses both callback functions -simultaneously to work out the right action to take. - -Using the decorators with other HTTP methods -============================================ - -The ``condition`` decorator is useful for more than only ``GET`` and -``HEAD`` requests (``HEAD`` requests are the same as ``GET`` in this -situation). It can be used also to be used to provide checking for ``POST``, -``PUT`` and ``DELETE`` requests. In these situations, the idea isn't to return -a "not modified" response, but to tell the client that the resource they are -trying to change has been altered in the meantime. - -For example, consider the following exchange between the client and server: - - 1. Client requests ``/foo/``. - 2. Server responds with some content with an ETag of ``"abcd1234"``. - 3. Client sends an HTTP ``PUT`` request to ``/foo/`` to update the - resource. It also sends an ``If-Match: "abcd1234"`` header to specify - the version it is trying to update. - 4. Server checks to see if the resource has changed, by computing the ETag - the same way it does for a ``GET`` request (using the same function). - If the resource *has* changed, it will return a 412 status code code, - meaning "precondition failed". - 5. Client sends a ``GET`` request to ``/foo/``, after receiving a 412 - response, to retrieve an updated version of the content before updating - it. - -The important thing this example shows is that the same functions can be used -to compute the ETag and last modification values in all situations. In fact, -you **should** use the same functions, so that the same values are returned -every time. - -Comparison with middleware conditional processing -================================================= - -You may notice that Django already provides simple and straightforward -conditional ``GET`` handling via the -:class:`django.middleware.http.ConditionalGetMiddleware` and -:class:`~django.middleware.common.CommonMiddleware`. Whilst certainly being -easy to use and suitable for many situations, those pieces of middleware -functionality have limitations for advanced usage: - - * They are applied globally to all views in your project - * They don't save you from generating the response itself, which may be - expensive - * They are only appropriate for HTTP ``GET`` requests. - -You should choose the most appropriate tool for your particular problem here. -If you have a way to compute ETags and modification times quickly and if some -view takes a while to generate the content, you should consider using the -``condition`` decorator described in this document. If everything already runs -fairly quickly, stick to using the middleware and the amount of network -traffic sent back to the clients will still be reduced if the view hasn't -changed. - diff --git a/parts/django/docs/topics/db/aggregation.txt b/parts/django/docs/topics/db/aggregation.txt deleted file mode 100644 index eb21021..0000000 --- a/parts/django/docs/topics/db/aggregation.txt +++ /dev/null @@ -1,378 +0,0 @@ -=========== -Aggregation -=========== - -.. versionadded:: 1.1 - -.. currentmodule:: django.db.models - -The topic guide on :doc:`Django's database-abstraction API </topics/db/queries>` -described the way that you can use Django queries that create, -retrieve, update and delete individual objects. However, sometimes you will -need to retrieve values that are derived by summarizing or *aggregating* a -collection of objects. This topic guide describes the ways that aggregate values -can be generated and returned using Django queries. - -Throughout this guide, we'll refer to the following models. These models are -used to track the inventory for a series of online bookstores: - -.. _queryset-model-example: - -.. code-block:: python - - class Author(models.Model): - name = models.CharField(max_length=100) - age = models.IntegerField() - friends = models.ManyToManyField('self', blank=True) - - class Publisher(models.Model): - name = models.CharField(max_length=300) - num_awards = models.IntegerField() - - class Book(models.Model): - isbn = models.CharField(max_length=9) - name = models.CharField(max_length=300) - pages = models.IntegerField() - price = models.DecimalField(max_digits=10, decimal_places=2) - rating = models.FloatField() - authors = models.ManyToManyField(Author) - publisher = models.ForeignKey(Publisher) - pubdate = models.DateField() - - class Store(models.Model): - name = models.CharField(max_length=300) - books = models.ManyToManyField(Book) - - -Generating aggregates over a QuerySet -===================================== - -Django provides two ways to generate aggregates. The first way is to generate -summary values over an entire ``QuerySet``. For example, say you wanted to -calculate the average price of all books available for sale. Django's query -syntax provides a means for describing the set of all books:: - - >>> Book.objects.all() - -What we need is a way to calculate summary values over the objects that -belong to this ``QuerySet``. This is done by appending an ``aggregate()`` -clause onto the ``QuerySet``:: - - >>> from django.db.models import Avg - >>> Book.objects.all().aggregate(Avg('price')) - {'price__avg': 34.35} - -The ``all()`` is redundant in this example, so this could be simplified to:: - - >>> Book.objects.aggregate(Avg('price')) - {'price__avg': 34.35} - -The argument to the ``aggregate()`` clause describes the aggregate value that -we want to compute - in this case, the average of the ``price`` field on the -``Book`` model. A list of the aggregate functions that are available can be -found in the :ref:`QuerySet reference <aggregation-functions>`. - -``aggregate()`` is a terminal clause for a ``QuerySet`` that, when invoked, -returns a dictionary of name-value pairs. The name is an identifier for the -aggregate value; the value is the computed aggregate. The name is -automatically generated from the name of the field and the aggregate function. -If you want to manually specify a name for the aggregate value, you can do so -by providing that name when you specify the aggregate clause:: - - >>> Book.objects.aggregate(average_price=Avg('price')) - {'average_price': 34.35} - -If you want to generate more than one aggregate, you just add another -argument to the ``aggregate()`` clause. So, if we also wanted to know -the maximum and minimum price of all books, we would issue the query:: - - >>> from django.db.models import Avg, Max, Min, Count - >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) - {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')} - -Generating aggregates for each item in a QuerySet -================================================= - -The second way to generate summary values is to generate an independent -summary for each object in a ``QuerySet``. For example, if you are retrieving -a list of books, you may want to know how many authors contributed to -each book. Each Book has a many-to-many relationship with the Author; we -want to summarize this relationship for each book in the ``QuerySet``. - -Per-object summaries can be generated using the ``annotate()`` clause. -When an ``annotate()`` clause is specified, each object in the ``QuerySet`` -will be annotated with the specified values. - -The syntax for these annotations is identical to that used for the -``aggregate()`` clause. Each argument to ``annotate()`` describes an -aggregate that is to be calculated. For example, to annotate Books with -the number of authors:: - - # Build an annotated queryset - >>> q = Book.objects.annotate(Count('authors')) - # Interrogate the first object in the queryset - >>> q[0] - <Book: The Definitive Guide to Django> - >>> q[0].authors__count - 2 - # Interrogate the second object in the queryset - >>> q[1] - <Book: Practical Django Projects> - >>> q[1].authors__count - 1 - -As with ``aggregate()``, the name for the annotation is automatically derived -from the name of the aggregate function and the name of the field being -aggregated. You can override this default name by providing an alias when you -specify the annotation:: - - >>> q = Book.objects.annotate(num_authors=Count('authors')) - >>> q[0].num_authors - 2 - >>> q[1].num_authors - 1 - -Unlike ``aggregate()``, ``annotate()`` is *not* a terminal clause. The output -of the ``annotate()`` clause is a ``QuerySet``; this ``QuerySet`` can be -modified using any other ``QuerySet`` operation, including ``filter()``, -``order_by``, or even additional calls to ``annotate()``. - -Joins and aggregates -==================== - -So far, we have dealt with aggregates over fields that belong to the -model being queried. However, sometimes the value you want to aggregate -will belong to a model that is related to the model you are querying. - -When specifying the field to be aggregated in an aggregate function, Django -will allow you to use the same :ref:`double underscore notation -<field-lookups-intro>` that is used when referring to related fields in -filters. Django will then handle any table joins that are required to retrieve -and aggregate the related value. - -For example, to find the price range of books offered in each store, -you could use the annotation:: - - >>> Store.objects.annotate(min_price=Min('books__price'), max_price=Max('books__price')) - -This tells Django to retrieve the Store model, join (through the -many-to-many relationship) with the Book model, and aggregate on the -price field of the book model to produce a minimum and maximum value. - -The same rules apply to the ``aggregate()`` clause. If you wanted to -know the lowest and highest price of any book that is available for sale -in a store, you could use the aggregate:: - - >>> Store.objects.aggregate(min_price=Min('books__price'), max_price=Max('books__price')) - -Join chains can be as deep as you require. For example, to extract the -age of the youngest author of any book available for sale, you could -issue the query:: - - >>> Store.objects.aggregate(youngest_age=Min('books__authors__age')) - -Aggregations and other QuerySet clauses -======================================= - -``filter()`` and ``exclude()`` ------------------------------- - -Aggregates can also participate in filters. Any ``filter()`` (or -``exclude()``) applied to normal model fields will have the effect of -constraining the objects that are considered for aggregation. - -When used with an ``annotate()`` clause, a filter has the effect of -constraining the objects for which an annotation is calculated. For example, -you can generate an annotated list of all books that have a title starting -with "Django" using the query:: - - >>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count('authors')) - -When used with an ``aggregate()`` clause, a filter has the effect of -constraining the objects over which the aggregate is calculated. -For example, you can generate the average price of all books with a -title that starts with "Django" using the query:: - - >>> Book.objects.filter(name__startswith="Django").aggregate(Avg('price')) - -Filtering on annotations -~~~~~~~~~~~~~~~~~~~~~~~~ - -Annotated values can also be filtered. The alias for the annotation can be -used in ``filter()`` and ``exclude()`` clauses in the same way as any other -model field. - -For example, to generate a list of books that have more than one author, -you can issue the query:: - - >>> Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1) - -This query generates an annotated result set, and then generates a filter -based upon that annotation. - -Order of ``annotate()`` and ``filter()`` clauses -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When developing a complex query that involves both ``annotate()`` and -``filter()`` clauses, particular attention should be paid to the order -in which the clauses are applied to the ``QuerySet``. - -When an ``annotate()`` clause is applied to a query, the annotation is -computed over the state of the query up to the point where the annotation -is requested. The practical implication of this is that ``filter()`` and -``annotate()`` are not commutative operations -- that is, there is a -difference between the query:: - - >>> Publisher.objects.annotate(num_books=Count('book')).filter(book__rating__gt=3.0) - -and the query:: - - >>> Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book')) - -Both queries will return a list of Publishers that have at least one good -book (i.e., a book with a rating exceeding 3.0). However, the annotation in -the first query will provide the total number of all books published by the -publisher; the second query will only include good books in the annotated -count. In the first query, the annotation precedes the filter, so the -filter has no effect on the annotation. In the second query, the filter -preceeds the annotation, and as a result, the filter constrains the objects -considered when calculating the annotation. - -``order_by()`` --------------- - -Annotations can be used as a basis for ordering. When you -define an ``order_by()`` clause, the aggregates you provide can reference -any alias defined as part of an ``annotate()`` clause in the query. - -For example, to order a ``QuerySet`` of books by the number of authors -that have contributed to the book, you could use the following query:: - - >>> Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors') - -``values()`` ------------- - -Ordinarily, annotations are generated on a per-object basis - an annotated -``QuerySet`` will return one result for each object in the original -``QuerySet``. However, when a ``values()`` clause is used to constrain the -columns that are returned in the result set, the method for evaluating -annotations is slightly different. Instead of returning an annotated result -for each result in the original ``QuerySet``, the original results are -grouped according to the unique combinations of the fields specified in the -``values()`` clause. An annotation is then provided for each unique group; -the annotation is computed over all members of the group. - -For example, consider an author query that attempts to find out the average -rating of books written by each author: - - >>> Author.objects.annotate(average_rating=Avg('book__rating')) - -This will return one result for each author in the database, annotated with -their average book rating. - -However, the result will be slightly different if you use a ``values()`` clause:: - - >>> Author.objects.values('name').annotate(average_rating=Avg('book__rating')) - -In this example, the authors will be grouped by name, so you will only get -an annotated result for each *unique* author name. This means if you have -two authors with the same name, their results will be merged into a single -result in the output of the query; the average will be computed as the -average over the books written by both authors. - -Order of ``annotate()`` and ``values()`` clauses -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As with the ``filter()`` clause, the order in which ``annotate()`` and -``values()`` clauses are applied to a query is significant. If the -``values()`` clause precedes the ``annotate()``, the annotation will be -computed using the grouping described by the ``values()`` clause. - -However, if the ``annotate()`` clause precedes the ``values()`` clause, -the annotations will be generated over the entire query set. In this case, -the ``values()`` clause only constrains the fields that are generated on -output. - -For example, if we reverse the order of the ``values()`` and ``annotate()`` -clause from our previous example:: - - >>> Author.objects.annotate(average_rating=Avg('book__rating')).values('name', 'average_rating') - -This will now yield one unique result for each author; however, only -the author's name and the ``average_rating`` annotation will be returned -in the output data. - -You should also note that ``average_rating`` has been explicitly included -in the list of values to be returned. This is required because of the -ordering of the ``values()`` and ``annotate()`` clause. - -If the ``values()`` clause precedes the ``annotate()`` clause, any annotations -will be automatically added to the result set. However, if the ``values()`` -clause is applied after the ``annotate()`` clause, you need to explicitly -include the aggregate column. - -Interaction with default ordering or ``order_by()`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Fields that are mentioned in the ``order_by()`` part of a queryset (or which -are used in the default ordering on a model) are used when selecting the -output data, even if they are not otherwise specified in the ``values()`` -call. These extra fields are used to group "like" results together and they -can make otherwise identical result rows appear to be separate. This shows up, -particularly, when counting things. - -By way of example, suppose you have a model like this:: - - class Item(models.Model): - name = models.CharField(max_length=10) - data = models.IntegerField() - - class Meta: - ordering = ["name"] - -The important part here is the default ordering on the ``name`` field. If you -want to count how many times each distinct ``data`` value appears, you might -try this:: - - # Warning: not quite correct! - Item.objects.values("data").annotate(Count("id")) - -...which will group the ``Item`` objects by their common ``data`` values and -then count the number of ``id`` values in each group. Except that it won't -quite work. The default ordering by ``name`` will also play a part in the -grouping, so this query will group by distinct ``(data, name)`` pairs, which -isn't what you want. Instead, you should construct this queryset:: - - Item.objects.values("data").annotate(Count("id")).order_by() - -...clearing any ordering in the query. You could also order by, say, ``data`` -without any harmful effects, since that is already playing a role in the -query. - -This behavior is the same as that noted in the queryset documentation for -:meth:`~django.db.models.QuerySet.distinct` and the general rule is the same: -normally you won't want extra columns playing a part in the result, so clear -out the ordering, or at least make sure it's restricted only to those fields -you also select in a ``values()`` call. - -.. note:: - You might reasonably ask why Django doesn't remove the extraneous columns - for you. The main reason is consistency with ``distinct()`` and other - places: Django **never** removes ordering constraints that you have - specified (and we can't change those other methods' behavior, as that - would violate our :doc:`/misc/api-stability` policy). - -Aggregating annotations ------------------------ - -You can also generate an aggregate on the result of an annotation. When you -define an ``aggregate()`` clause, the aggregates you provide can reference -any alias defined as part of an ``annotate()`` clause in the query. - -For example, if you wanted to calculate the average number of authors per -book you first annotate the set of books with the author count, then -aggregate that author count, referencing the annotation field:: - - >>> Book.objects.annotate(num_authors=Count('authors')).aggregate(Avg('num_authors')) - {'num_authors__avg': 1.66} diff --git a/parts/django/docs/topics/db/index.txt b/parts/django/docs/topics/db/index.txt deleted file mode 100644 index c49f158..0000000 --- a/parts/django/docs/topics/db/index.txt +++ /dev/null @@ -1,18 +0,0 @@ -Models and databases -==================== - -A model is the single, definitive source of data about your data. It contains -the essential fields and behaviors of the data you're storing. Generally, each -model maps to a single database table. - -.. toctree:: - :maxdepth: 1 - - models - queries - aggregation - managers - sql - transactions - multi-db - optimization diff --git a/parts/django/docs/topics/db/managers.txt b/parts/django/docs/topics/db/managers.txt deleted file mode 100644 index 5ebe0b1..0000000 --- a/parts/django/docs/topics/db/managers.txt +++ /dev/null @@ -1,376 +0,0 @@ -======== -Managers -======== - -.. currentmodule:: django.db.models - -.. class:: Manager() - -A ``Manager`` is the interface through which database query operations are -provided to Django models. At least one ``Manager`` exists for every model in -a Django application. - -The way ``Manager`` classes work is documented in :doc:`/topics/db/queries`; -this document specifically touches on model options that customize ``Manager`` -behavior. - -.. _manager-names: - -Manager names -============= - -By default, Django adds a ``Manager`` with the name ``objects`` to every Django -model class. However, if you want to use ``objects`` as a field name, or if you -want to use a name other than ``objects`` for the ``Manager``, you can rename -it on a per-model basis. To rename the ``Manager`` for a given class, define a -class attribute of type ``models.Manager()`` on that model. For example:: - - from django.db import models - - class Person(models.Model): - #... - people = models.Manager() - -Using this example model, ``Person.objects`` will generate an -``AttributeError`` exception, but ``Person.people.all()`` will provide a list -of all ``Person`` objects. - -.. _custom-managers: - -Custom Managers -=============== - -You can use a custom ``Manager`` in a particular model by extending the base -``Manager`` class and instantiating your custom ``Manager`` in your model. - -There are two reasons you might want to customize a ``Manager``: to add extra -``Manager`` methods, and/or to modify the initial ``QuerySet`` the ``Manager`` -returns. - -Adding extra Manager methods ----------------------------- - -Adding extra ``Manager`` methods is the preferred way to add "table-level" -functionality to your models. (For "row-level" functionality -- i.e., functions -that act on a single instance of a model object -- use :ref:`Model methods -<model-methods>`, not custom ``Manager`` methods.) - -A custom ``Manager`` method can return anything you want. It doesn't have to -return a ``QuerySet``. - -For example, this custom ``Manager`` offers a method ``with_counts()``, which -returns a list of all ``OpinionPoll`` objects, each with an extra -``num_responses`` attribute that is the result of an aggregate query:: - - class PollManager(models.Manager): - def with_counts(self): - from django.db import connection - cursor = connection.cursor() - cursor.execute(""" - SELECT p.id, p.question, p.poll_date, COUNT(*) - FROM polls_opinionpoll p, polls_response r - WHERE p.id = r.poll_id - GROUP BY 1, 2, 3 - ORDER BY 3 DESC""") - result_list = [] - for row in cursor.fetchall(): - p = self.model(id=row[0], question=row[1], poll_date=row[2]) - p.num_responses = row[3] - result_list.append(p) - return result_list - - class OpinionPoll(models.Model): - question = models.CharField(max_length=200) - poll_date = models.DateField() - objects = PollManager() - - class Response(models.Model): - poll = models.ForeignKey(Poll) - person_name = models.CharField(max_length=50) - response = models.TextField() - -With this example, you'd use ``OpinionPoll.objects.with_counts()`` to return -that list of ``OpinionPoll`` objects with ``num_responses`` attributes. - -Another thing to note about this example is that ``Manager`` methods can -access ``self.model`` to get the model class to which they're attached. - -Modifying initial Manager QuerySets ------------------------------------ - -A ``Manager``'s base ``QuerySet`` returns all objects in the system. For -example, using this model:: - - class Book(models.Model): - title = models.CharField(max_length=100) - author = models.CharField(max_length=50) - -...the statement ``Book.objects.all()`` will return all books in the database. - -You can override a ``Manager``\'s base ``QuerySet`` by overriding the -``Manager.get_query_set()`` method. ``get_query_set()`` should return a -``QuerySet`` with the properties you require. - -For example, the following model has *two* ``Manager``\s -- one that returns -all objects, and one that returns only the books by Roald Dahl:: - - # First, define the Manager subclass. - class DahlBookManager(models.Manager): - def get_query_set(self): - return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl') - - # Then hook it into the Book model explicitly. - class Book(models.Model): - title = models.CharField(max_length=100) - author = models.CharField(max_length=50) - - objects = models.Manager() # The default manager. - dahl_objects = DahlBookManager() # The Dahl-specific manager. - -With this sample model, ``Book.objects.all()`` will return all books in the -database, but ``Book.dahl_objects.all()`` will only return the ones written by -Roald Dahl. - -Of course, because ``get_query_set()`` returns a ``QuerySet`` object, you can -use ``filter()``, ``exclude()`` and all the other ``QuerySet`` methods on it. -So these statements are all legal:: - - Book.dahl_objects.all() - Book.dahl_objects.filter(title='Matilda') - Book.dahl_objects.count() - -This example also pointed out another interesting technique: using multiple -managers on the same model. You can attach as many ``Manager()`` instances to -a model as you'd like. This is an easy way to define common "filters" for your -models. - -For example:: - - class MaleManager(models.Manager): - def get_query_set(self): - return super(MaleManager, self).get_query_set().filter(sex='M') - - class FemaleManager(models.Manager): - def get_query_set(self): - return super(FemaleManager, self).get_query_set().filter(sex='F') - - class Person(models.Model): - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female'))) - people = models.Manager() - men = MaleManager() - women = FemaleManager() - -This example allows you to request ``Person.men.all()``, ``Person.women.all()``, -and ``Person.people.all()``, yielding predictable results. - -If you use custom ``Manager`` objects, take note that the first ``Manager`` -Django encounters (in the order in which they're defined in the model) has a -special status. Django interprets the first ``Manager`` defined in a class as -the "default" ``Manager``, and several parts of Django -(including :djadmin:`dumpdata`) will use that ``Manager`` -exclusively for that model. As a result, it's a good idea to be careful in -your choice of default manager in order to avoid a situation where overriding -``get_query_set()`` results in an inability to retrieve objects you'd like to -work with. - -.. _managers-for-related-objects: - -Using managers for related object access -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default, Django uses an instance of a "plain" manager class when accessing -related objects (i.e. ``choice.poll``), not the default manager on the related -object. This is because Django needs to be able to retrieve the related -object, even if it would otherwise be filtered out (and hence be inaccessible) -by the default manager. - -If the normal plain manager class (:class:`django.db.models.Manager`) is not -appropriate for your circumstances, you can force Django to use the same class -as the default manager for your model by setting the `use_for_related_fields` -attribute on the manager class. This is documented fully below_. - -.. _below: manager-types_ - -.. _custom-managers-and-inheritance: - -Custom managers and model inheritance -------------------------------------- - -Class inheritance and model managers aren't quite a perfect match for each -other. Managers are often specific to the classes they are defined on and -inheriting them in subclasses isn't necessarily a good idea. Also, because the -first manager declared is the *default manager*, it is important to allow that -to be controlled. So here's how Django handles custom managers and -:ref:`model inheritance <model-inheritance>`: - - 1. Managers defined on non-abstract base classes are *not* inherited by - child classes. If you want to reuse a manager from a non-abstract base, - redeclare it explicitly on the child class. These sorts of managers are - likely to be fairly specific to the class they are defined on, so - inheriting them can often lead to unexpected results (particularly as - far as the default manager goes). Therefore, they aren't passed onto - child classes. - - 2. Managers from abstract base classes are always inherited by the child - class, using Python's normal name resolution order (names on the child - class override all others; then come names on the first parent class, - and so on). Abstract base classes are designed to capture information - and behavior that is common to their child classes. Defining common - managers is an appropriate part of this common information. - - 3. The default manager on a class is either the first manager declared on - the class, if that exists, or the default manager of the first abstract - base class in the parent hierarchy, if that exists. If no default - manager is explicitly declared, Django's normal default manager is - used. - -These rules provide the necessary flexibility if you want to install a -collection of custom managers on a group of models, via an abstract base -class, but still customize the default manager. For example, suppose you have -this base class:: - - class AbstractBase(models.Model): - ... - objects = CustomManager() - - class Meta: - abstract = True - -If you use this directly in a subclass, ``objects`` will be the default -manager if you declare no managers in the base class:: - - class ChildA(AbstractBase): - ... - # This class has CustomManager as the default manager. - -If you want to inherit from ``AbstractBase``, but provide a different default -manager, you can provide the default manager on the child class:: - - class ChildB(AbstractBase): - ... - # An explicit default manager. - default_manager = OtherManager() - -Here, ``default_manager`` is the default. The ``objects`` manager is -still available, since it's inherited. It just isn't used as the default. - -Finally for this example, suppose you want to add extra managers to the child -class, but still use the default from ``AbstractBase``. You can't add the new -manager directly in the child class, as that would override the default and you would -have to also explicitly include all the managers from the abstract base class. -The solution is to put the extra managers in another base class and introduce -it into the inheritance hierarchy *after* the defaults:: - - class ExtraManager(models.Model): - extra_manager = OtherManager() - - class Meta: - abstract = True - - class ChildC(AbstractBase, ExtraManager): - ... - # Default manager is CustomManager, but OtherManager is - # also available via the "extra_manager" attribute. - -.. _manager-types: - -Controlling Automatic Manager Types -=================================== - -This document has already mentioned a couple of places where Django creates a -manager class for you: `default managers`_ and the "plain" manager used to -`access related objects`_. There are other places in the implementation of -Django where temporary plain managers are needed. Those automatically created -managers will normally be instances of the :class:`django.db.models.Manager` -class. - -.. _default managers: manager-names_ -.. _access related objects: managers-for-related-objects_ - -Throughout this section, we will use the term "automatic manager" to mean a -manager that Django creates for you -- either as a default manager on a model -with no managers, or to use temporarily when accessing related objects. - -Sometimes this default class won't be the right choice. One example is in the -:mod:`django.contrib.gis` application that ships with Django itself. All ``gis`` -models must use a special manager class (:class:`~django.contrib.gis.db.models.GeoManager`) -because they need a special queryset (:class:`~django.contrib.gis.db.models.GeoQuerySet`) -to be used for interacting with the database. It turns out that models which require -a special manager like this need to use the same manager class wherever an automatic -manager is created. - -Django provides a way for custom manager developers to say that their manager -class should be used for automatic managers whenever it is the default manager -on a model. This is done by setting the ``use_for_related_fields`` attribute on -the manager class:: - - class MyManager(models.Manager): - use_for_related_fields = True - - ... - -If this attribute is set on the *default* manager for a model (only the -default manager is considered in these situations), Django will use that class -whenever it needs to automatically create a manager for the class. Otherwise, -it will use :class:`django.db.models.Manager`. - -.. admonition:: Historical Note - - Given the purpose for which it's used, the name of this attribute - (``use_for_related_fields``) might seem a little odd. Originally, the - attribute only controlled the type of manager used for related field - access, which is where the name came from. As it became clear the concept - was more broadly useful, the name hasn't been changed. This is primarily - so that existing code will :doc:`continue to work </misc/api-stability>` in - future Django versions. - -Writing Correct Managers For Use In Automatic Manager Instances ---------------------------------------------------------------- - -As already suggested by the `django.contrib.gis` example, above, the -``use_for_related_fields`` feature is primarily for managers that need to -return a custom ``QuerySet`` subclass. In providing this functionality in your -manager, there are a couple of things to remember. - -Do not filter away any results in this type of manager subclass -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -One reason an automatic manager is used is to access objects that are related -to from some other model. In those situations, Django has to be able to see -all the objects for the model it is fetching, so that *anything* which is -referred to can be retrieved. - -If you override the ``get_query_set()`` method and filter out any rows, Django -will return incorrect results. Don't do that. A manager that filters results -in ``get_query_set()`` is not appropriate for use as an automatic manager. - -Set ``use_for_related_fields`` when you define the class -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``use_for_related_fields`` attribute must be set on the manager *class*, -object not on an *instance* of the class. The earlier example shows the -correct way to set it, whereas the following will not work:: - - # BAD: Incorrect code - class MyManager(models.Manager): - ... - - # Sets the attribute on an instance of MyManager. Django will - # ignore this setting. - mgr = MyManager() - mgr.use_for_related_fields = True - - class MyModel(models.Model): - ... - objects = mgr - - # End of incorrect code. - -You also shouldn't change the attribute on the class object after it has been -used in a model, since the attribute's value is processed when the model class -is created and not subsequently reread. Set the attribute on the manager class -when it is first defined, as in the initial example of this section and -everything will work smoothly. - diff --git a/parts/django/docs/topics/db/models.txt b/parts/django/docs/topics/db/models.txt deleted file mode 100644 index 2a19cbd..0000000 --- a/parts/django/docs/topics/db/models.txt +++ /dev/null @@ -1,1234 +0,0 @@ -====== -Models -====== - -.. module:: django.db.models - -A model is the single, definitive source of data about your data. It contains -the essential fields and behaviors of the data you're storing. Generally, each -model maps to a single database table. - -The basics: - - * Each model is a Python class that subclasses - :class:`django.db.models.Model`. - - * Each attribute of the model represents a database field. - - * With all of this, Django gives you an automatically-generated - database-access API; see :doc:`/topics/db/queries`. - -.. seealso:: - - A companion to this document is the `official repository of model - examples`_. (In the Django source distribution, these examples are in the - ``tests/modeltests`` directory.) - - .. _official repository of model examples: http://www.djangoproject.com/documentation/models/ - -Quick example -============= - -This example model defines a ``Person``, which has a ``first_name`` and -``last_name``:: - - from django.db import models - - class Person(models.Model): - first_name = models.CharField(max_length=30) - last_name = models.CharField(max_length=30) - -``first_name`` and ``last_name`` are fields_ of the model. Each field is -specified as a class attribute, and each attribute maps to a database column. - -The above ``Person`` model would create a database table like this: - -.. code-block:: sql - - CREATE TABLE myapp_person ( - "id" serial NOT NULL PRIMARY KEY, - "first_name" varchar(30) NOT NULL, - "last_name" varchar(30) NOT NULL - ); - -Some technical notes: - - * The name of the table, ``myapp_person``, is automatically derived from - some model metadata but can be overridden. See :ref:`table-names` for more - details.. - - * An ``id`` field is added automatically, but this behavior can be - overridden. See :ref:`automatic-primary-key-fields`. - - * The ``CREATE TABLE`` SQL in this example is formatted using PostgreSQL - syntax, but it's worth noting Django uses SQL tailored to the database - backend specified in your :doc:`settings file </topics/settings>`. - -Using models -============ - -Once you have defined your models, you need to tell Django you're going to *use* -those models. Do this by editing your settings file and changing the -:setting:`INSTALLED_APPS` setting to add the name of the module that contains -your ``models.py``. - -For example, if the models for your application live in the module -``mysite.myapp.models`` (the package structure that is created for an -application by the :djadmin:`manage.py startapp <startapp>` script), -:setting:`INSTALLED_APPS` should read, in part:: - - INSTALLED_APPS = ( - #... - 'mysite.myapp', - #... - ) - -When you add new apps to :setting:`INSTALLED_APPS`, be sure to run -:djadmin:`manage.py syncdb <syncdb>`. - -Fields -====== - -The most important part of a model -- and the only required part of a model -- -is the list of database fields it defines. Fields are specified by class -attributes. - -Example:: - - class Musician(models.Model): - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - instrument = models.CharField(max_length=100) - - class Album(models.Model): - artist = models.ForeignKey(Musician) - name = models.CharField(max_length=100) - release_date = models.DateField() - num_stars = models.IntegerField() - -Field types ------------ - -Each field in your model should be an instance of the appropriate -:class:`~django.db.models.Field` class. Django uses the field class types to -determine a few things: - - * The database column type (e.g. ``INTEGER``, ``VARCHAR``). - - * The :doc:`widget </ref/forms/widgets>` to use in Django's admin interface, - if you care to use it (e.g. ``<input type="text">``, ``<select>``). - - * The minimal validation requirements, used in Django's admin and in - automatically-generated forms. - -Django ships with dozens of built-in field types; you can find the complete list -in the :ref:`model field reference <model-field-types>`. You can easily write -your own fields if Django's built-in ones don't do the trick; see -:doc:`/howto/custom-model-fields`. - -Field options -------------- - -Each field takes a certain set of field-specific arguments (documented in the -:ref:`model field reference <model-field-types>`). For example, -:class:`~django.db.models.CharField` (and its subclasses) require a -:attr:`~django.db.models.CharField.max_length` argument which specifies the size -of the ``VARCHAR`` database field used to store the data. - -There's also a set of common arguments available to all field types. All are -optional. They're fully explained in the :ref:`reference -<common-model-field-options>`, but here's a quick summary of the most often-used -ones: - - :attr:`~Field.null` - If ``True``, Django will store empty values as ``NULL`` in the database. - Default is ``False``. - - :attr:`~Field.blank` - If ``True``, the field is allowed to be blank. Default is ``False``. - - Note that this is different than :attr:`~Field.null`. - :attr:`~Field.null` is purely database-related, whereas - :attr:`~Field.blank` is validation-related. If a field has - :attr:`blank=True <Field.blank>`, validation on Django's admin site will - allow entry of an empty value. If a field has :attr:`blank=False - <Field.blank>`, the field will be required. - - :attr:`~Field.choices` - An iterable (e.g., a list or tuple) of 2-tuples to use as choices for - this field. If this is given, Django's admin will use a select box - instead of the standard text field and will limit choices to the choices - given. - - A choices list looks like this:: - - YEAR_IN_SCHOOL_CHOICES = ( - (u'FR', u'Freshman'), - (u'SO', u'Sophomore'), - (u'JR', u'Junior'), - (u'SR', u'Senior'), - (u'GR', u'Graduate'), - ) - - The first element in each tuple is the value that will be stored in the - database, the second element will be displayed by the admin interface, - or in a ModelChoiceField. Given an instance of a model object, the - display value for a choices field can be accessed using the - ``get_FOO_display`` method. For example:: - - from django.db import models - - class Person(models.Model): - GENDER_CHOICES = ( - (u'M', u'Male'), - (u'F', u'Female'), - ) - name = models.CharField(max_length=60) - gender = models.CharField(max_length=2, choices=GENDER_CHOICES) - - :: - - >>> p = Person(name="Fred Flinstone", gender="M") - >>> p.save() - >>> p.gender - u'M' - >>> p.get_gender_display() - u'Male' - - :attr:`~Field.default` - The default value for the field. This can be a value or a callable - object. If callable it will be called every time a new object is - created. - - :attr:`~Field.help_text` - Extra "help" text to be displayed under the field on the object's admin - form. It's useful for documentation even if your object doesn't have an - admin form. - - :attr:`~Field.primary_key` - If ``True``, this field is the primary key for the model. - - If you don't specify :attr:`primary_key=True <Field.primary_key>` for - any fields in your model, Django will automatically add an - :class:`IntegerField` to hold the primary key, so you don't need to set - :attr:`primary_key=True <Field.primary_key>` on any of your fields - unless you want to override the default primary-key behavior. For more, - see :ref:`automatic-primary-key-fields`. - - :attr:`~Field.unique` - If ``True``, this field must be unique throughout the table. - -Again, these are just short descriptions of the most common field options. Full -details can be found in the :ref:`common model field option reference -<common-model-field-options>`. - -.. _automatic-primary-key-fields: - -Automatic primary key fields ----------------------------- - -By default, Django gives each model the following field:: - - id = models.AutoField(primary_key=True) - -This is an auto-incrementing primary key. - -If you'd like to specify a custom primary key, just specify -:attr:`primary_key=True <Field.primary_key>` on one of your fields. If Django -sees you've explicitly set :attr:`Field.primary_key`, it won't add the automatic -``id`` column. - -Each model requires exactly one field to have :attr:`primary_key=True -<Field.primary_key>`. - -.. _verbose-field-names: - -Verbose field names -------------------- - -Each field type, except for :class:`~django.db.models.ForeignKey`, -:class:`~django.db.models.ManyToManyField` and -:class:`~django.db.models.OneToOneField`, takes an optional first positional -argument -- a verbose name. If the verbose name isn't given, Django will -automatically create it using the field's attribute name, converting underscores -to spaces. - -In this example, the verbose name is ``"person's first name"``:: - - first_name = models.CharField("person's first name", max_length=30) - -In this example, the verbose name is ``"first name"``:: - - first_name = models.CharField(max_length=30) - -:class:`~django.db.models.ForeignKey`, -:class:`~django.db.models.ManyToManyField` and -:class:`~django.db.models.OneToOneField` require the first argument to be a -model class, so use the :attr:`~Field.verbose_name` keyword argument:: - - poll = models.ForeignKey(Poll, verbose_name="the related poll") - sites = models.ManyToManyField(Site, verbose_name="list of sites") - place = models.OneToOneField(Place, verbose_name="related place") - -The convention is not to capitalize the first letter of the -:attr:`~Field.verbose_name`. Django will automatically capitalize the first -letter where it needs to. - -Relationships -------------- - -Clearly, the power of relational databases lies in relating tables to each -other. Django offers ways to define the three most common types of database -relationships: many-to-one, many-to-many and one-to-one. - -Many-to-one relationships -~~~~~~~~~~~~~~~~~~~~~~~~~ - -To define a many-to-one relationship, use :class:`~django.db.models.ForeignKey`. -You use it just like any other :class:`~django.db.models.Field` type: by -including it as a class attribute of your model. - -:class:`~django.db.models.ForeignKey` requires a positional argument: the class -to which the model is related. - -For example, if a ``Car`` model has a ``Manufacturer`` -- that is, a -``Manufacturer`` makes multiple cars but each ``Car`` only has one -``Manufacturer`` -- use the following definitions:: - - class Manufacturer(models.Model): - # ... - - class Car(models.Model): - manufacturer = models.ForeignKey(Manufacturer) - # ... - -You can also create :ref:`recursive relationships <recursive-relationships>` (an -object with a many-to-one relationship to itself) and :ref:`relationships to -models not yet defined <lazy-relationships>`; see :ref:`the model field -reference <ref-foreignkey>` for details. - -It's suggested, but not required, that the name of a -:class:`~django.db.models.ForeignKey` field (``manufacturer`` in the example -above) be the name of the model, lowercase. You can, of course, call the field -whatever you want. For example:: - - class Car(models.Model): - company_that_makes_it = models.ForeignKey(Manufacturer) - # ... - -.. seealso:: - - See the `Many-to-one relationship model example`_ for a full example. - -.. _Many-to-one relationship model example: http://www.djangoproject.com/documentation/models/many_to_one/ - -:class:`~django.db.models.ForeignKey` fields also accept a number of extra -arguments which are explained in :ref:`the model field reference -<foreign-key-arguments>`. These options help define how the relationship should -work; all are optional. - -Many-to-many relationships -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To define a many-to-many relationship, use -:class:`~django.db.models.ManyToManyField`. You use it just like any other -:class:`~django.db.models.Field` type: by including it as a class attribute of -your model. - -:class:`~django.db.models.ManyToManyField` requires a positional argument: the -class to which the model is related. - -For example, if a ``Pizza`` has multiple ``Topping`` objects -- that is, a -``Topping`` can be on multiple pizzas and each ``Pizza`` has multiple toppings --- here's how you'd represent that:: - - class Topping(models.Model): - # ... - - class Pizza(models.Model): - # ... - toppings = models.ManyToManyField(Topping) - -As with :class:`~django.db.models.ForeignKey`, you can also create -:ref:`recursive relationships <recursive-relationships>` (an object with a -many-to-many relationship to itself) and :ref:`relationships to models not yet -defined <lazy-relationships>`; see :ref:`the model field reference -<ref-manytomany>` for details. - -It's suggested, but not required, that the name of a -:class:`~django.db.models.ManyToManyField` (``toppings`` in the example above) -be a plural describing the set of related model objects. - -It doesn't matter which model gets the -:class:`~django.db.models.ManyToManyField`, but you only need it in one of the -models -- not in both. - -Generally, :class:`~django.db.models.ManyToManyField` instances should go in the -object that's going to be edited in the admin interface, if you're using -Django's admin. In the above example, ``toppings`` is in ``Pizza`` (rather than -``Topping`` having a ``pizzas`` :class:`~django.db.models.ManyToManyField` ) -because it's more natural to think about a pizza having toppings than a -topping being on multiple pizzas. The way it's set up above, the ``Pizza`` admin -form would let users select the toppings. - -.. seealso:: - - See the `Many-to-many relationship model example`_ for a full example. - -.. _Many-to-many relationship model example: http://www.djangoproject.com/documentation/models/many_to_many/ - -:class:`~django.db.models.ManyToManyField` fields also accept a number of extra -arguments which are explained in :ref:`the model field reference -<manytomany-arguments>`. These options help define how the relationship should -work; all are optional. - -.. _intermediary-manytomany: - -Extra fields on many-to-many relationships -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -When you're only dealing with simple many-to-many relationships such as -mixing and matching pizzas and toppings, a standard :class:`~django.db.models.ManyToManyField` is all you need. However, sometimes -you may need to associate data with the relationship between two models. - -For example, consider the case of an application tracking the musical groups -which musicians belong to. There is a many-to-many relationship between a person -and the groups of which they are a member, so you could use a -:class:`~django.db.models.ManyToManyField` to represent this relationship. -However, there is a lot of detail about the membership that you might want to -collect, such as the date at which the person joined the group. - -For these situations, Django allows you to specify the model that will be used -to govern the many-to-many relationship. You can then put extra fields on the -intermediate model. The intermediate model is associated with the -:class:`~django.db.models.ManyToManyField` using the -:attr:`through <ManyToManyField.through>` argument to point to the model -that will act as an intermediary. For our musician example, the code would look -something like this:: - - class Person(models.Model): - name = models.CharField(max_length=128) - - def __unicode__(self): - return self.name - - class Group(models.Model): - name = models.CharField(max_length=128) - members = models.ManyToManyField(Person, through='Membership') - - def __unicode__(self): - return self.name - - class Membership(models.Model): - person = models.ForeignKey(Person) - group = models.ForeignKey(Group) - date_joined = models.DateField() - invite_reason = models.CharField(max_length=64) - -When you set up the intermediary model, you explicitly specify foreign -keys to the models that are involved in the ManyToMany relation. This -explicit declaration defines how the two models are related. - -There are a few restrictions on the intermediate model: - - * Your intermediate model must contain one - and *only* one - foreign key - to the target model (this would be ``Person`` in our example). If you - have more than one foreign key, a validation error will be raised. - - * Your intermediate model must contain one - and *only* one - foreign key - to the source model (this would be ``Group`` in our example). If you - have more than one foreign key, a validation error will be raised. - - * The only exception to this is a model which has a many-to-many - relationship to itself, through an intermediary model. In this - case, two foreign keys to the same model are permitted, but they - will be treated as the two (different) sides of the many-to-many - relation. - - * When defining a many-to-many relationship from a model to - itself, using an intermediary model, you *must* use - :attr:`symmetrical=False <ManyToManyField.symmetrical>` (see - :ref:`the model field reference <manytomany-arguments>`). - -Now that you have set up your :class:`~django.db.models.ManyToManyField` to use -your intermediary model (``Membership``, in this case), you're ready to start -creating some many-to-many relationships. You do this by creating instances of -the intermediate model:: - - >>> ringo = Person.objects.create(name="Ringo Starr") - >>> paul = Person.objects.create(name="Paul McCartney") - >>> beatles = Group.objects.create(name="The Beatles") - >>> m1 = Membership(person=ringo, group=beatles, - ... date_joined=date(1962, 8, 16), - ... invite_reason= "Needed a new drummer.") - >>> m1.save() - >>> beatles.members.all() - [<Person: Ringo Starr>] - >>> ringo.group_set.all() - [<Group: The Beatles>] - >>> m2 = Membership.objects.create(person=paul, group=beatles, - ... date_joined=date(1960, 8, 1), - ... invite_reason= "Wanted to form a band.") - >>> beatles.members.all() - [<Person: Ringo Starr>, <Person: Paul McCartney>] - -Unlike normal many-to-many fields, you *can't* use ``add``, ``create``, -or assignment (i.e., ``beatles.members = [...]``) to create relationships:: - - # THIS WILL NOT WORK - >>> beatles.members.add(john) - # NEITHER WILL THIS - >>> beatles.members.create(name="George Harrison") - # AND NEITHER WILL THIS - >>> beatles.members = [john, paul, ringo, george] - -Why? You can't just create a relationship between a ``Person`` and a ``Group`` -- you need to specify all the detail for the relationship required by the -``Membership`` model. The simple ``add``, ``create`` and assignment calls -don't provide a way to specify this extra detail. As a result, they are -disabled for many-to-many relationships that use an intermediate model. -The only way to create this type of relationship is to create instances of the -intermediate model. - -The :meth:`~django.db.models.fields.related.RelatedManager.remove` method is -disabled for similar reasons. However, the -:meth:`~django.db.models.fields.related.RelatedManager.clear` method can be -used to remove all many-to-many relationships for an instance:: - - # Beatles have broken up - >>> beatles.members.clear() - -Once you have established the many-to-many relationships by creating instances -of your intermediate model, you can issue queries. Just as with normal -many-to-many relationships, you can query using the attributes of the -many-to-many-related model:: - - # Find all the groups with a member whose name starts with 'Paul' - >>> Group.objects.filter(members__name__startswith='Paul') - [<Group: The Beatles>] - -As you are using an intermediate model, you can also query on its attributes:: - - # Find all the members of the Beatles that joined after 1 Jan 1961 - >>> Person.objects.filter( - ... group__name='The Beatles', - ... membership__date_joined__gt=date(1961,1,1)) - [<Person: Ringo Starr] - - -One-to-one relationships -~~~~~~~~~~~~~~~~~~~~~~~~ - -To define a one-to-one relationship, use -:class:`~django.db.models.OneToOneField`. You use it just like any other -``Field`` type: by including it as a class attribute of your model. - -This is most useful on the primary key of an object when that object "extends" -another object in some way. - -:class:`~django.db.models.OneToOneField` requires a positional argument: the -class to which the model is related. - -For example, if you were building a database of "places", you would -build pretty standard stuff such as address, phone number, etc. in the -database. Then, if you wanted to build a database of restaurants on -top of the places, instead of repeating yourself and replicating those -fields in the ``Restaurant`` model, you could make ``Restaurant`` have -a :class:`~django.db.models.OneToOneField` to ``Place`` (because a -restaurant "is a" place; in fact, to handle this you'd typically use -:ref:`inheritance <model-inheritance>`, which involves an implicit -one-to-one relation). - -As with :class:`~django.db.models.ForeignKey`, a -:ref:`recursive relationship <recursive-relationships>` -can be defined and -:ref:`references to as-yet undefined models <lazy-relationships>` -can be made; see :ref:`the model field reference <ref-onetoone>` for details. - -.. seealso:: - - See the `One-to-one relationship model example`_ for a full example. - -.. _One-to-one relationship model example: http://www.djangoproject.com/documentation/models/one_to_one/ - -.. versionadded:: 1.0 - -:class:`~django.db.models.OneToOneField` fields also accept one optional argument -described in the :ref:`model field reference <ref-onetoone>`. - -:class:`~django.db.models.OneToOneField` classes used to automatically become -the primary key on a model. This is no longer true (although you can manually -pass in the :attr:`~django.db.models.Field.primary_key` argument if you like). -Thus, it's now possible to have multiple fields of type -:class:`~django.db.models.OneToOneField` on a single model. - -Models across files -------------------- - -It's perfectly OK to relate a model to one from another app. To do this, -import the related model at the top of the model that holds your model. Then, -just refer to the other model class wherever needed. For example:: - - from geography.models import ZipCode - - class Restaurant(models.Model): - # ... - zip_code = models.ForeignKey(ZipCode) - -Field name restrictions ------------------------ - -Django places only two restrictions on model field names: - - 1. A field name cannot be a Python reserved word, because that would result - in a Python syntax error. For example:: - - class Example(models.Model): - pass = models.IntegerField() # 'pass' is a reserved word! - - 2. A field name cannot contain more than one underscore in a row, due to - the way Django's query lookup syntax works. For example:: - - class Example(models.Model): - foo__bar = models.IntegerField() # 'foo__bar' has two underscores! - -These limitations can be worked around, though, because your field name doesn't -necessarily have to match your database column name. See the -:attr:`~Field.db_column` option. - -SQL reserved words, such as ``join``, ``where`` or ``select``, *are* allowed as -model field names, because Django escapes all database table names and column -names in every underlying SQL query. It uses the quoting syntax of your -particular database engine. - -Custom field types ------------------- - -.. versionadded:: 1.0 - -If one of the existing model fields cannot be used to fit your purposes, or if -you wish to take advantage of some less common database column types, you can -create your own field class. Full coverage of creating your own fields is -provided in :doc:`/howto/custom-model-fields`. - -.. _meta-options: - -Meta options -============ - -Give your model metadata by using an inner ``class Meta``, like so:: - - class Ox(models.Model): - horn_length = models.IntegerField() - - class Meta: - ordering = ["horn_length"] - verbose_name_plural = "oxen" - -Model metadata is "anything that's not a field", such as ordering options -(:attr:`~Options.ordering`), database table name (:attr:`~Options.db_table`), or -human-readable singular and plural names (:attr:`~Options.verbose_name` and -:attr:`~Options.verbose_name_plural`). None are required, and adding ``class -Meta`` to a model is completely optional. - -A complete list of all possible ``Meta`` options can be found in the :doc:`model -option reference </ref/models/options>`. - -.. _model-methods: - -Model methods -============= - -Define custom methods on a model to add custom "row-level" functionality to your -objects. Whereas :class:`~django.db.models.Manager` methods are intended to do -"table-wide" things, model methods should act on a particular model instance. - -This is a valuable technique for keeping business logic in one place -- the -model. - -For example, this model has a few custom methods:: - - from django.contrib.localflavor.us.models import USStateField - - class Person(models.Model): - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - birth_date = models.DateField() - address = models.CharField(max_length=100) - city = models.CharField(max_length=50) - state = USStateField() # Yes, this is America-centric... - - def baby_boomer_status(self): - "Returns the person's baby-boomer status." - import datetime - if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31): - return "Baby boomer" - if self.birth_date < datetime.date(1945, 8, 1): - return "Pre-boomer" - return "Post-boomer" - - def is_midwestern(self): - "Returns True if this person is from the Midwest." - return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO') - - def _get_full_name(self): - "Returns the person's full name." - return '%s %s' % (self.first_name, self.last_name) - full_name = property(_get_full_name) - -The last method in this example is a :term:`property`. `Read more about -properties`_. - -.. _Read more about properties: http://www.python.org/download/releases/2.2/descrintro/#property - -The :doc:`model instance reference </ref/models/instances>` has a complete list -of :ref:`methods automatically given to each model <model-instance-methods>`. -You can override most of these -- see `overriding predefined model methods`_, -below -- but there are a couple that you'll almost always want to define: - - :meth:`~Model.__unicode__` - A Python "magic method" that returns a unicode "representation" of any - object. This is what Python and Django will use whenever a model - instance needs to be coerced and displayed as a plain string. Most - notably, this happens when you display an object in an interactive - console or in the admin. - - You'll always want to define this method; the default isn't very helpful - at all. - - :meth:`~Model.get_absolute_url` - This tells Django how to calculate the URL for an object. Django uses - this in its admin interface, and any time it needs to figure out a URL - for an object. - - Any object that has a URL that uniquely identifies it should define this - method. - -.. _overriding-model-methods: - -Overriding predefined model methods ------------------------------------ - -There's another set of :ref:`model methods <model-instance-methods>` that -encapsulate a bunch of database behavior that you'll want to customize. In -particular you'll often want to change the way :meth:`~Model.save` and -:meth:`~Model.delete` work. - -You're free to override these methods (and any other model method) to alter -behavior. - -A classic use-case for overriding the built-in methods is if you want something -to happen whenever you save an object. For example (see -:meth:`~Model.save` for documentation of the parameters it accepts):: - - class Blog(models.Model): - name = models.CharField(max_length=100) - tagline = models.TextField() - - def save(self, *args, **kwargs): - do_something() - super(Blog, self).save(*args, **kwargs) # Call the "real" save() method. - do_something_else() - -You can also prevent saving:: - - class Blog(models.Model): - name = models.CharField(max_length=100) - tagline = models.TextField() - - def save(self, *args, **kwargs): - if self.name == "Yoko Ono's blog": - return # Yoko shall never have her own blog! - else: - super(Blog, self).save(*args, **kwargs) # Call the "real" save() method. - -It's important to remember to call the superclass method -- that's -that ``super(Blog, self).save(*args, **kwargs)`` business -- to ensure -that the object still gets saved into the database. If you forget to -call the superclass method, the default behavior won't happen and the -database won't get touched. - -It's also important that you pass through the arguments that can be -passed to the model method -- that's what the ``*args, **kwargs`` bit -does. Django will, from time to time, extend the capabilities of -built-in model methods, adding new arguments. If you use ``*args, -**kwargs`` in your method definitions, you are guaranteed that your -code will automatically support those arguments when they are added. - -Executing custom SQL --------------------- - -Another common pattern is writing custom SQL statements in model methods and -module-level methods. For more details on using raw SQL, see the documentation -on :doc:`using raw SQL</topics/db/sql>`. - -.. _model-inheritance: - -Model inheritance -================= - -.. versionadded:: 1.0 - -Model inheritance in Django works almost identically to the way normal -class inheritance works in Python. The only decision you have to make -is whether you want the parent models to be models in their own right -(with their own database tables), or if the parents are just holders -of common information that will only be visible through the child -models. - -There are three styles of inheritance that are possible in Django. - - 1. Often, you will just want to use the parent class to hold information that - you don't want to have to type out for each child model. This class isn't - going to ever be used in isolation, so :ref:`abstract-base-classes` are - what you're after. - 2. If you're subclassing an existing model (perhaps something from another - application entirely) and want each model to have its own database table, - :ref:`multi-table-inheritance` is the way to go. - 3. Finally, if you only want to modify the Python-level behaviour of a model, - without changing the models fields in any way, you can use - :ref:`proxy-models`. - -.. _abstract-base-classes: - -Abstract base classes ---------------------- - -Abstract base classes are useful when you want to put some common -information into a number of other models. You write your base class -and put ``abstract=True`` in the :ref:`Meta <meta-options>` -class. This model will then not be used to create any database -table. Instead, when it is used as a base class for other models, its -fields will be added to those of the child class. It is an error to -have fields in the abstract base class with the same name as those in -the child (and Django will raise an exception). - -An example:: - - class CommonInfo(models.Model): - name = models.CharField(max_length=100) - age = models.PositiveIntegerField() - - class Meta: - abstract = True - - class Student(CommonInfo): - home_group = models.CharField(max_length=5) - -The ``Student`` model will have three fields: ``name``, ``age`` and -``home_group``. The ``CommonInfo`` model cannot be used as a normal Django -model, since it is an abstract base class. It does not generate a database -table or have a manager, and cannot be instantiated or saved directly. - -For many uses, this type of model inheritance will be exactly what you want. -It provides a way to factor out common information at the Python level, whilst -still only creating one database table per child model at the database level. - -``Meta`` inheritance -~~~~~~~~~~~~~~~~~~~~ - -When an abstract base class is created, Django makes any :ref:`Meta <meta-options>` -inner class you declared in the base class available as an -attribute. If a child class does not declare its own :ref:`Meta <meta-options>` -class, it will inherit the parent's :ref:`Meta <meta-options>`. If the child wants to -extend the parent's :ref:`Meta <meta-options>` class, it can subclass it. For example:: - - class CommonInfo(models.Model): - ... - class Meta: - abstract = True - ordering = ['name'] - - class Student(CommonInfo): - ... - class Meta(CommonInfo.Meta): - db_table = 'student_info' - -Django does make one adjustment to the :ref:`Meta <meta-options>` class of an abstract base -class: before installing the :ref:`Meta <meta-options>` attribute, it sets ``abstract=False``. -This means that children of abstract base classes don't automatically become -abstract classes themselves. Of course, you can make an abstract base class -that inherits from another abstract base class. You just need to remember to -explicitly set ``abstract=True`` each time. - -Some attributes won't make sense to include in the :ref:`Meta <meta-options>` class of an -abstract base class. For example, including ``db_table`` would mean that all -the child classes (the ones that don't specify their own :ref:`Meta <meta-options>`) would use -the same database table, which is almost certainly not what you want. - -.. _abstract-related-name: - -Be careful with ``related_name`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you are using the :attr:`~django.db.models.ForeignKey.related_name` attribute on a ``ForeignKey`` or -``ManyToManyField``, you must always specify a *unique* reverse name for the -field. This would normally cause a problem in abstract base classes, since the -fields on this class are included into each of the child classes, with exactly -the same values for the attributes (including :attr:`~django.db.models.ForeignKey.related_name`) each time. - -.. versionchanged:: 1.2 - -To work around this problem, when you are using :attr:`~django.db.models.ForeignKey.related_name` in an -abstract base class (only), part of the name should contain -``'%(app_label)s'`` and ``'%(class)s'``. - -- ``'%(class)s'`` is replaced by the lower-cased name of the child class - that the field is used in. -- ``'%(app_label)s'`` is replaced by the lower-cased name of the app the child - class is contained within. Each installed application name must be unique - and the model class names within each app must also be unique, therefore the - resulting name will end up being different. - -For example, given an app ``common/models.py``:: - - class Base(models.Model): - m2m = models.ManyToManyField(OtherModel, related_name="%(app_label)s_%(class)s_related") - - class Meta: - abstract = True - - class ChildA(Base): - pass - - class ChildB(Base): - pass - -Along with another app ``rare/models.py``:: - - from common.models import Base - - class ChildB(Base): - pass - -The reverse name of the ``commmon.ChildA.m2m`` field will be -``common_childa_related``, whilst the reverse name of the -``common.ChildB.m2m`` field will be ``common_childb_related``, and finally the -reverse name of the ``rare.ChildB.m2m`` field will be ``rare_childb_related``. -It is up to you how you use the ``'%(class)s'`` and ``'%(app_label)s`` portion -to construct your related name, but if you forget to use it, Django will raise -errors when you validate your models (or run :djadmin:`syncdb`). - -If you don't specify a :attr:`~django.db.models.ForeignKey.related_name` -attribute for a field in an abstract base class, the default reverse name will -be the name of the child class followed by ``'_set'``, just as it normally -would be if you'd declared the field directly on the child class. For example, -in the above code, if the :attr:`~django.db.models.ForeignKey.related_name` -attribute was omitted, the reverse name for the ``m2m`` field would be -``childa_set`` in the ``ChildA`` case and ``childb_set`` for the ``ChildB`` -field. - -.. _multi-table-inheritance: - -Multi-table inheritance ------------------------ - -The second type of model inheritance supported by Django is when each model in -the hierarchy is a model all by itself. Each model corresponds to its own -database table and can be queried and created individually. The inheritance -relationship introduces links between the child model and each of its parents -(via an automatically-created :class:`~django.db.models.fields.OneToOneField`). -For example:: - - class Place(models.Model): - name = models.CharField(max_length=50) - address = models.CharField(max_length=80) - - class Restaurant(Place): - serves_hot_dogs = models.BooleanField() - serves_pizza = models.BooleanField() - -All of the fields of ``Place`` will also be available in ``Restaurant``, -although the data will reside in a different database table. So these are both -possible:: - - >>> Place.objects.filter(name="Bob's Cafe") - >>> Restaurant.objects.filter(name="Bob's Cafe") - -If you have a ``Place`` that is also a ``Restaurant``, you can get from the -``Place`` object to the ``Restaurant`` object by using the lower-case version -of the model name:: - - >>> p = Place.objects.get(id=12) - # If p is a Restaurant object, this will give the child class: - >>> p.restaurant - <Restaurant: ...> - -However, if ``p`` in the above example was *not* a ``Restaurant`` (it had been -created directly as a ``Place`` object or was the parent of some other class), -referring to ``p.restaurant`` would raise a Restaurant.DoesNotExist exception. - -``Meta`` and multi-table inheritance -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In the multi-table inheritance situation, it doesn't make sense for a child -class to inherit from its parent's :ref:`Meta <meta-options>` class. All the :ref:`Meta <meta-options>` options -have already been applied to the parent class and applying them again would -normally only lead to contradictory behavior (this is in contrast with the -abstract base class case, where the base class doesn't exist in its own -right). - -So a child model does not have access to its parent's :ref:`Meta -<meta-options>` class. However, there are a few limited cases where the child -inherits behavior from the parent: if the child does not specify an -:attr:`~django.db.models.Options.ordering` attribute or a -:attr:`~django.db.models.Options.get_latest_by` attribute, it will inherit -these from its parent. - -If the parent has an ordering and you don't want the child to have any natural -ordering, you can explicitly disable it:: - - class ChildModel(ParentModel): - ... - class Meta: - # Remove parent's ordering effect - ordering = [] - -Inheritance and reverse relations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Because multi-table inheritance uses an implicit -:class:`~django.db.models.OneToOneField` to link the child and -the parent, it's possible to move from the parent down to the child, -as in the above example. However, this uses up the name that is the -default :attr:`~django.db.models.ForeignKey.related_name` value for -:class:`~django.db.models.ForeignKey` and -:class:`~django.db.models.ManyToManyField` relations. If you -are putting those types of relations on a subclass of another model, -you **must** specify the -:attr:`~django.db.models.ForeignKey.related_name` attribute on each -such field. If you forget, Django will raise an error when you run -:djadmin:`validate` or :djadmin:`syncdb`. - -For example, using the above ``Place`` class again, let's create another -subclass with a :class:`~django.db.models.ManyToManyField`:: - - class Supplier(Place): - # Must specify related_name on all relations. - customers = models.ManyToManyField(Restaurant, related_name='provider') - - -Specifying the parent link field -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As mentioned, Django will automatically create a -:class:`~django.db.models.OneToOneField` linking your child -class back any non-abstract parent models. If you want to control the -name of the attribute linking back to the parent, you can create your -own :class:`~django.db.models.OneToOneField` and set -:attr:`parent_link=True <django.db.models.OneToOneField.parent_link>` -to indicate that your field is the link back to the parent class. - -.. _proxy-models: - -Proxy models ------------- - -.. versionadded:: 1.1 - -When using :ref:`multi-table inheritance <multi-table-inheritance>`, a new -database table is created for each subclass of a model. This is usually the -desired behavior, since the subclass needs a place to store any additional -data fields that are not present on the base class. Sometimes, however, you -only want to change the Python behavior of a model -- perhaps to change the -default manager, or add a new method. - -This is what proxy model inheritance is for: creating a *proxy* for the -original model. You can create, delete and update instances of the proxy model -and all the data will be saved as if you were using the original (non-proxied) -model. The difference is that you can change things like the default model -ordering or the default manager in the proxy, without having to alter the -original. - -Proxy models are declared like normal models. You tell Django that it's a -proxy model by setting the :attr:`~django.db.models.Options.proxy` attribute of -the ``Meta`` class to ``True``. - -For example, suppose you want to add a method to the standard -:class:`~django.contrib.auth.models.User` model that will be used in your -templates. You can do it like this:: - - from django.contrib.auth.models import User - - class MyUser(User): - class Meta: - proxy = True - - def do_something(self): - ... - -The ``MyUser`` class operates on the same database table as its parent -:class:`~django.contrib.auth.models.User` class. In particular, any new -instances of :class:`~django.contrib.auth.models.User` will also be accessible -through ``MyUser``, and vice-versa:: - - >>> u = User.objects.create(username="foobar") - >>> MyUser.objects.get(username="foobar") - <MyUser: foobar> - -You could also use a proxy model to define a different default ordering on a -model. The standard :class:`~django.contrib.auth.models.User` model has no -ordering defined on it (intentionally; sorting is expensive and we don't want -to do it all the time when we fetch users). You might want to regularly order -by the ``username`` attribute when you use the proxy. This is easy:: - - class OrderedUser(User): - class Meta: - ordering = ["username"] - proxy = True - -Now normal :class:`~django.contrib.auth.models.User` queries will be unordered -and ``OrderedUser`` queries will be ordered by ``username``. - -QuerySets still return the model that was requested -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There is no way to have Django return, say, a ``MyUser`` object whenever you -query for :class:`~django.contrib.auth.models.User` objects. A queryset for -``User`` objects will return those types of objects. The whole point of proxy -objects is that code relying on the original ``User`` will use those and your -own code can use the extensions you included (that no other code is relying on -anyway). It is not a way to replace the ``User`` (or any other) model -everywhere with something of your own creation. - -Base class restrictions -~~~~~~~~~~~~~~~~~~~~~~~ - -A proxy model must inherit from exactly one non-abstract model class. You -can't inherit from multiple non-abstract models as the proxy model doesn't -provide any connection between the rows in the different database tables. A -proxy model can inherit from any number of abstract model classes, providing -they do *not* define any model fields. - -Proxy models inherit any ``Meta`` options that they don't define from their -non-abstract model parent (the model they are proxying for). - -Proxy model managers -~~~~~~~~~~~~~~~~~~~~ - -If you don't specify any model managers on a proxy model, it inherits the -managers from its model parents. If you define a manager on the proxy model, -it will become the default, although any managers defined on the parent -classes will still be available. - -Continuing our example from above, you could change the default manager used -when you query the ``User`` model like this:: - - class NewManager(models.Manager): - ... - - class MyUser(User): - objects = NewManager() - - class Meta: - proxy = True - -If you wanted to add a new manager to the Proxy, without replacing the -existing default, you can use the techniques described in the :ref:`custom -manager <custom-managers-and-inheritance>` documentation: create a base class -containing the new managers and inherit that after the primary base class:: - - # Create an abstract class for the new manager. - class ExtraManagers(models.Model): - secondary = NewManager() - - class Meta: - abstract = True - - class MyUser(User, ExtraManagers): - class Meta: - proxy = True - -You probably won't need to do this very often, but, when you do, it's -possible. - -.. _proxy-vs-unmanaged-models: - -Differences between proxy inheritance and unmanaged models -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Proxy model inheritance might look fairly similar to creating an unmanaged -model, using the :attr:`~django.db.models.Options.managed` attribute on a -model's ``Meta`` class. The two alternatives are not quite the same and it's -worth considering which one you should use. - -One difference is that you can (and, in fact, must unless you want an empty -model) specify model fields on models with ``Meta.managed=False``. You could, -with careful setting of :attr:`Meta.db_table -<django.db.models.Options.db_table>` create an unmanaged model that shadowed -an existing model and add Python methods to it. However, that would be very -repetitive and fragile as you need to keep both copies synchronized if you -make any changes. - -The other difference that is more important for proxy models, is how model -managers are handled. Proxy models are intended to behave exactly like the -model they are proxying for. So they inherit the parent model's managers, -including the default manager. In the normal multi-table model inheritance -case, children do not inherit managers from their parents as the custom -managers aren't always appropriate when extra fields are involved. The -:ref:`manager documentation <custom-managers-and-inheritance>` has more -details about this latter case. - -When these two features were implemented, attempts were made to squash them -into a single option. It turned out that interactions with inheritance, in -general, and managers, in particular, made the API very complicated and -potentially difficult to understand and use. It turned out that two options -were needed in any case, so the current separation arose. - -So, the general rules are: - - 1. If you are mirroring an existing model or database table and don't want - all the original database table columns, use ``Meta.managed=False``. - That option is normally useful for modeling database views and tables - not under the control of Django. - 2. If you are wanting to change the Python-only behavior of a model, but - keep all the same fields as in the original, use ``Meta.proxy=True``. - This sets things up so that the proxy model is an exact copy of the - storage structure of the original model when data is saved. - -Multiple inheritance --------------------- - -Just as with Python's subclassing, it's possible for a Django model to inherit -from multiple parent models. Keep in mind that normal Python name resolution -rules apply. The first base class that a particular name (e.g. :ref:`Meta -<meta-options>`) appears in will be the one that is used; for example, this -means that if multiple parents contain a :ref:`Meta <meta-options>` class, -only the first one is going to be used, and all others will be ignored. - -Generally, you won't need to inherit from multiple parents. The main use-case -where this is useful is for "mix-in" classes: adding a particular extra -field or method to every class that inherits the mix-in. Try to keep your -inheritance hierarchies as simple and straightforward as possible so that you -won't have to struggle to work out where a particular piece of information is -coming from. - -Field name "hiding" is not permitted -------------------------------------- - -In normal Python class inheritance, it is permissible for a child class to -override any attribute from the parent class. In Django, this is not permitted -for attributes that are :class:`~django.db.models.fields.Field` instances (at -least, not at the moment). If a base class has a field called ``author``, you -cannot create another model field called ``author`` in any class that inherits -from that base class. - -Overriding fields in a parent model leads to difficulties in areas such as -initialising new instances (specifying which field is being initialized in -``Model.__init__``) and serialization. These are features which normal Python -class inheritance doesn't have to deal with in quite the same way, so the -difference between Django model inheritance and Python class inheritance isn't -arbitrary. - -This restriction only applies to attributes which are -:class:`~django.db.models.fields.Field` instances. Normal Python attributes -can be overridden if you wish. It also only applies to the name of the -attribute as Python sees it: if you are manually specifying the database -column name, you can have the same column name appearing in both a child and -an ancestor model for multi-table inheritance (they are columns in two -different database tables). - -Django will raise a :exc:`~django.core.exceptions.FieldError` if you override -any model field in any ancestor model. diff --git a/parts/django/docs/topics/db/multi-db.txt b/parts/django/docs/topics/db/multi-db.txt deleted file mode 100644 index 1a939b0..0000000 --- a/parts/django/docs/topics/db/multi-db.txt +++ /dev/null @@ -1,574 +0,0 @@ -================== -Multiple databases -================== - -.. versionadded:: 1.2 - -This topic guide describes Django's support for interacting with -multiple databases. Most of the rest of Django's documentation assumes -you are interacting with a single database. If you want to interact -with multiple databases, you'll need to take some additional steps. - -Defining your databases -======================= - -The first step to using more than one database with Django is to tell -Django about the database servers you'll be using. This is done using -the :setting:`DATABASES` setting. This setting maps database aliases, -which are a way to refer to a specific database throughout Django, to -a dictionary of settings for that specific connection. The settings in -the inner dictionaries are described fully in the :setting:`DATABASES` -documentation. - -Databases can have any alias you choose. However, the alias -``default`` has special significance. Django uses the database with -the alias of ``default`` when no other database has been selected. If -you don't have a ``default`` database, you need to be careful to -always specify the database that you want to use. - -The following is an example ``settings.py`` snippet defining two -databases -- a default PostgreSQL database and a MySQL database called -``users``: - -.. code-block:: python - - DATABASES = { - 'default': { - 'NAME': 'app_data', - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'USER': 'postgres_user', - 'PASSWORD': 's3krit' - }, - 'users': { - 'NAME': 'user_data', - 'ENGINE': 'django.db.backends.mysql', - 'USER': 'mysql_user', - 'PASSWORD': 'priv4te' - } - } - -If you attempt to access a database that you haven't defined in your -:setting:`DATABASES` setting, Django will raise a -``django.db.utils.ConnectionDoesNotExist`` exception. - -Synchronizing your databases -============================ - -The :djadmin:`syncdb` management command operates on one database at a -time. By default, it operates on the ``default`` database, but by -providing a :djadminopt:`--database` argument, you can tell syncdb to -synchronize a different database. So, to synchronize all models onto -all databases in our example, you would need to call:: - - $ ./manage.py syncdb - $ ./manage.py syncdb --database=users - -If you don't want every application to be synchronized onto a -particular database, you can define a :ref:`database -router<topics-db-multi-db-routing>` that implements a policy -constraining the availability of particular models. - -Alternatively, if you want fine-grained control of synchronization, -you can pipe all or part of the output of :djadmin:`sqlall` for a -particular application directly into your database prompt, like this:: - - $ ./manage.py sqlall sales | ./manage.py dbshell - -Using other management commands -------------------------------- - -The other ``django-admin.py`` commands that interact with the database -operate in the same way as :djadmin:`syncdb` -- they only ever operate -on one database at a time, using :djadminopt:`--database` to control -the database used. - -.. _topics-db-multi-db-routing: - -Automatic database routing -========================== - -The easiest way to use multiple databases is to set up a database -routing scheme. The default routing scheme ensures that objects remain -'sticky' to their original database (i.e., an object retrieved from -the ``foo`` database will be saved on the same database). The default -routing scheme ensures that if a database isn't specified, all queries -fall back to the ``default`` database. - -You don't have to do anything to activate the default routing scheme --- it is provided 'out of the box' on every Django project. However, -if you want to implement more interesting database allocation -behaviors, you can define and install your own database routers. - -Database routers ----------------- - -A database Router is a class that provides up to four methods: - -.. method:: db_for_read(model, **hints) - - Suggest the database that should be used for read operations for - objects of type ``model``. - - If a database operation is able to provide any additional - information that might assist in selecting a database, it will be - provided in the ``hints`` dictionary. Details on valid hints are - provided :ref:`below <topics-db-multi-db-hints>`. - - Returns None if there is no suggestion. - -.. method:: db_for_write(model, **hints) - - Suggest the database that should be used for writes of objects of - type Model. - - If a database operation is able to provide any additional - information that might assist in selecting a database, it will be - provided in the ``hints`` dictionary. Details on valid hints are - provided :ref:`below <topics-db-multi-db-hints>`. - - Returns None if there is no suggestion. - -.. method:: allow_relation(obj1, obj2, **hints) - - Return True if a relation between obj1 and obj2 should be - allowed, False if the relation should be prevented, or None if - the router has no opinion. This is purely a validation operation, - used by foreign key and many to many operations to determine if a - relation should be allowed between two objects. - -.. method:: allow_syncdb(db, model) - - Determine if the ``model`` should be synchronized onto the - database with alias ``db``. Return True if the model should be - synchronized, False if it should not be synchronized, or None if - the router has no opinion. This method can be used to determine - the availability of a model on a given database. - -A router doesn't have to provide *all* these methods - it omit one or -more of them. If one of the methods is omitted, Django will skip that -router when performing the relevant check. - -.. _topics-db-multi-db-hints: - -Hints -~~~~~ - -The hints received by the database router can be used to decide which -database should receive a given request. - -At present, the only hint that will be provided is ``instance``, an -object instance that is related to the read or write operation that is -underway. This might be the instance that is being saved, or it might -be an instance that is being added in a many-to-many relation. In some -cases, no instance hint will be provided at all. The router checks for -the existence of an instance hint, and determine if that hint should be -used to alter routing behavior. - -Using routers -------------- - -Database routers are installed using the :setting:`DATABASE_ROUTERS` -setting. This setting defines a list of class names, each specifying a -router that should be used by the master router -(``django.db.router``). - -The master router is used by Django's database operations to allocate -database usage. Whenever a query needs to know which database to use, -it calls the master router, providing a model and a hint (if -available). Django then tries each router in turn until a database -suggestion can be found. If no suggestion can be found, it tries the -current ``_state.db`` of the hint instance. If a hint instance wasn't -provided, or the instance doesn't currently have database state, the -master router will allocate the ``default`` database. - -An example ----------- - -.. admonition:: Example purposes only! - - This example is intended as a demonstration of how the router - infrastructure can be used to alter database usage. It - intentionally ignores some complex issues in order to - demonstrate how routers are used. - - This example won't work if any of the models in ``myapp`` contain - relationships to models outside of the ``other`` database. - :ref:`Cross-database relationships <no_cross_database_relations>` - introduce referential integrity problems that Django can't - currently handle. - - The master/slave configuration described is also flawed -- it - doesn't provide any solution for handling replication lag (i.e., - query inconsistencies introduced because of the time taken for a - write to propagate to the slaves). It also doesn't consider the - interaction of transactions with the database utilization strategy. - -So - what does this mean in practice? Say you want ``myapp`` to -exist on the ``other`` database, and you want all other models in a -master/slave relationship between the databases ``master``, ``slave1`` and -``slave2``. To implement this, you would need 2 routers:: - - class MyAppRouter(object): - """A router to control all database operations on models in - the myapp application""" - - def db_for_read(self, model, **hints): - "Point all operations on myapp models to 'other'" - if model._meta.app_label == 'myapp': - return 'other' - return None - - def db_for_write(self, model, **hints): - "Point all operations on myapp models to 'other'" - if model._meta.app_label == 'myapp': - return 'other' - return None - - def allow_relation(self, obj1, obj2, **hints): - "Allow any relation if a model in myapp is involved" - if obj1._meta.app_label == 'myapp' or obj2._meta.app_label == 'myapp': - return True - return None - - def allow_syncdb(self, db, model): - "Make sure the myapp app only appears on the 'other' db" - if db == 'other': - return model._meta.app_label == 'myapp' - elif model._meta.app_label == 'myapp': - return False - return None - - class MasterSlaveRouter(object): - """A router that sets up a simple master/slave configuration""" - - def db_for_read(self, model, **hints): - "Point all read operations to a random slave" - return random.choice(['slave1','slave2']) - - def db_for_write(self, model, **hints): - "Point all write operations to the master" - return 'master' - - def allow_relation(self, obj1, obj2, **hints): - "Allow any relation between two objects in the db pool" - db_list = ('master','slave1','slave2') - if obj1._state.db in db_list and obj2._state.db in db_list: - return True - return None - - def allow_syncdb(self, db, model): - "Explicitly put all models on all databases." - return True - -Then, in your settings file, add the following (substituting ``path.to.`` with -the actual python path to the module where you define the routers):: - - DATABASE_ROUTERS = ['path.to.MyAppRouter', 'path.to.MasterSlaveRouter'] - -The order in which routers are processed is significant. Routers will -be queried in the order the are listed in the -:setting:`DATABASE_ROUTERS` setting . In this example, the -``MyAppRouter`` is processed before the ``MasterSlaveRouter``, and as a -result, decisions concerning the models in ``myapp`` are processed -before any other decision is made. If the :setting:`DATABASE_ROUTERS` -setting listed the two routers in the other order, -``MasterSlaveRouter.allow_syncdb()`` would be processed first. The -catch-all nature of the MasterSlaveRouter implementation would mean -that all models would be available on all databases. - -With this setup installed, lets run some Django code:: - - >>> # This retrieval will be performed on the 'credentials' database - >>> fred = User.objects.get(username='fred') - >>> fred.first_name = 'Frederick' - - >>> # This save will also be directed to 'credentials' - >>> fred.save() - - >>> # These retrieval will be randomly allocated to a slave database - >>> dna = Person.objects.get(name='Douglas Adams') - - >>> # A new object has no database allocation when created - >>> mh = Book(title='Mostly Harmless') - - >>> # This assignment will consult the router, and set mh onto - >>> # the same database as the author object - >>> mh.author = dna - - >>> # This save will force the 'mh' instance onto the master database... - >>> mh.save() - - >>> # ... but if we re-retrieve the object, it will come back on a slave - >>> mh = Book.objects.get(title='Mostly Harmless') - - -Manually selecting a database -============================= - -Django also provides an API that allows you to maintain complete control -over database usage in your code. A manually specified database allocation -will take priority over a database allocated by a router. - -Manually selecting a database for a ``QuerySet`` ------------------------------------------------- - -You can select the database for a ``QuerySet`` at any point in the -``QuerySet`` "chain." Just call ``using()`` on the ``QuerySet`` to get -another ``QuerySet`` that uses the specified database. - -``using()`` takes a single argument: the alias of the database on -which you want to run the query. For example:: - - >>> # This will run on the 'default' database. - >>> Author.objects.all() - - >>> # So will this. - >>> Author.objects.using('default').all() - - >>> # This will run on the 'other' database. - >>> Author.objects.using('other').all() - -Selecting a database for ``save()`` ------------------------------------ - -Use the ``using`` keyword to ``Model.save()`` to specify to which -database the data should be saved. - -For example, to save an object to the ``legacy_users`` database, you'd -use this:: - - >>> my_object.save(using='legacy_users') - -If you don't specify ``using``, the ``save()`` method will save into -the default database allocated by the routers. - -Moving an object from one database to another -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you've saved an instance to one database, it might be tempting to -use ``save(using=...)`` as a way to migrate the instance to a new -database. However, if you don't take appropriate steps, this could -have some unexpected consequences. - -Consider the following example:: - - >>> p = Person(name='Fred') - >>> p.save(using='first') # (statement 1) - >>> p.save(using='second') # (statement 2) - -In statement 1, a new ``Person`` object is saved to the ``first`` -database. At this time, ``p`` doesn't have a primary key, so Django -issues a SQL ``INSERT`` statement. This creates a primary key, and -Django assigns that primary key to ``p``. - -When the save occurs in statement 2, ``p`` already has a primary key -value, and Django will attempt to use that primary key on the new -database. If the primary key value isn't in use in the ``second`` -database, then you won't have any problems -- the object will be -copied to the new database. - -However, if the primary key of ``p`` is already in use on the -``second`` database, the existing object in the ``second`` database -will be overridden when ``p`` is saved. - -You can avoid this in two ways. First, you can clear the primary key -of the instance. If an object has no primary key, Django will treat it -as a new object, avoiding any loss of data on the ``second`` -database:: - - >>> p = Person(name='Fred') - >>> p.save(using='first') - >>> p.pk = None # Clear the primary key. - >>> p.save(using='second') # Write a completely new object. - -The second option is to use the ``force_insert`` option to ``save()`` -to ensure that Django does a SQL ``INSERT``:: - - >>> p = Person(name='Fred') - >>> p.save(using='first') - >>> p.save(using='second', force_insert=True) - -This will ensure that the person named ``Fred`` will have the same -primary key on both databases. If that primary key is already in use -when you try to save onto the ``second`` database, an error will be -raised. - -Selecting a database to delete from ------------------------------------ - -By default, a call to delete an existing object will be executed on -the same database that was used to retrieve the object in the first -place:: - - >>> u = User.objects.using('legacy_users').get(username='fred') - >>> u.delete() # will delete from the `legacy_users` database - -To specify the database from which a model will be deleted, pass a -``using`` keyword argument to the ``Model.delete()`` method. This -argument works just like the ``using`` keyword argument to ``save()``. - -For example, if you're migrating a user from the ``legacy_users`` -database to the ``new_users`` database, you might use these commands:: - - >>> user_obj.save(using='new_users') - >>> user_obj.delete(using='legacy_users') - -Using managers with multiple databases --------------------------------------- - -Use the ``db_manager()`` method on managers to give managers access to -a non-default database. - -For example, say you have a custom manager method that touches the -database -- ``User.objects.create_user()``. Because ``create_user()`` -is a manager method, not a ``QuerySet`` method, you can't do -``User.objects.using('new_users').create_user()``. (The -``create_user()`` method is only available on ``User.objects``, the -manager, not on ``QuerySet`` objects derived from the manager.) The -solution is to use ``db_manager()``, like this:: - - User.objects.db_manager('new_users').create_user(...) - -``db_manager()`` returns a copy of the manager bound to the database you specify. - -Using ``get_query_set()`` with multiple databases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you're overriding ``get_query_set()`` on your manager, be sure to -either call the method on the parent (using ``super()``) or do the -appropriate handling of the ``_db`` attribute on the manager (a string -containing the name of the database to use). - -For example, if you want to return a custom ``QuerySet`` class from -the ``get_query_set`` method, you could do this:: - - class MyManager(models.Manager): - def get_query_set(self): - qs = CustomQuerySet(self.model) - if self._db is not None: - qs = qs.using(self._db) - return qs - -Exposing multiple databases in Django's admin interface -======================================================= - -Django's admin doesn't have any explicit support for multiple -databases. If you want to provide an admin interface for a model on a -database other than that that specified by your router chain, you'll -need to write custom :class:`~django.contrib.admin.ModelAdmin` classes -that will direct the admin to use a specific database for content. - -``ModelAdmin`` objects have four methods that require customization for -multiple-database support:: - - class MultiDBModelAdmin(admin.ModelAdmin): - # A handy constant for the name of the alternate database. - using = 'other' - - def save_model(self, request, obj, form, change): - # Tell Django to save objects to the 'other' database. - obj.save(using=self.using) - - def queryset(self, request): - # Tell Django to look for objects on the 'other' database. - return super(MultiDBModelAdmin, self).queryset(request).using(self.using) - - def formfield_for_foreignkey(self, db_field, request=None, **kwargs): - # Tell Django to populate ForeignKey widgets using a query - # on the 'other' database. - return super(MultiDBModelAdmin, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs) - - def formfield_for_manytomany(self, db_field, request=None, **kwargs): - # Tell Django to populate ManyToMany widgets using a query - # on the 'other' database. - return super(MultiDBModelAdmin, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs) - -The implementation provided here implements a multi-database strategy -where all objects of a given type are stored on a specific database -(e.g., all ``User`` objects are in the ``other`` database). If your -usage of multiple databases is more complex, your ``ModelAdmin`` will -need to reflect that strategy. - -Inlines can be handled in a similar fashion. They require three customized methods:: - - class MultiDBTabularInline(admin.TabularInline): - using = 'other' - - def queryset(self, request): - # Tell Django to look for inline objects on the 'other' database. - return super(MultiDBTabularInline, self).queryset(request).using(self.using) - - def formfield_for_foreignkey(self, db_field, request=None, **kwargs): - # Tell Django to populate ForeignKey widgets using a query - # on the 'other' database. - return super(MultiDBTabularInline, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs) - - def formfield_for_manytomany(self, db_field, request=None, **kwargs): - # Tell Django to populate ManyToMany widgets using a query - # on the 'other' database. - return super(MultiDBTabularInline, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs) - -Once you've written your model admin definitions, they can be -registered with any ``Admin`` instance:: - - from django.contrib import admin - - # Specialize the multi-db admin objects for use with specific models. - class BookInline(MultiDBTabularInline): - model = Book - - class PublisherAdmin(MultiDBModelAdmin): - inlines = [BookInline] - - admin.site.register(Author, MultiDBModelAdmin) - admin.site.register(Publisher, PublisherAdmin) - - othersite = admin.Site('othersite') - othersite.register(Publisher, MultiDBModelAdmin) - -This example sets up two admin sites. On the first site, the -``Author`` and ``Publisher`` objects are exposed; ``Publisher`` -objects have an tabular inline showing books published by that -publisher. The second site exposes just publishers, without the -inlines. - -Using raw cursors with multiple databases -========================================= - -If you are using more than one database you can use -``django.db.connections`` to obtain the connection (and cursor) for a -specific database. ``django.db.connections`` is a dictionary-like -object that allows you to retrieve a specific connection using it's -alias:: - - from django.db import connections - cursor = connections['my_db_alias'].cursor() - -Limitations of multiple databases -================================= - -.. _no_cross_database_relations: - -Cross-database relations ------------------------- - -Django doesn't currently provide any support for foreign key or -many-to-many relationships spanning multiple databases. If you -have used a router to partition models to different databases, -any foreign key and many-to-many relationships defined by those -models must be internal to a single database. - -This is because of referential integrity. In order to maintain a -relationship between two objects, Django needs to know that the -primary key of the related object is valid. If the primary key is -stored on a separate database, it's not possible to easily evaluate -the validity of a primary key. - -If you're using Postgres, Oracle, or MySQL with InnoDB, this is -enforced at the database integrity level -- database level key -constraints prevent the creation of relations that can't be validated. - -However, if you're using SQLite or MySQL with MyISAM tables, there is -no enforced referential integrity; as a result, you may be able to -'fake' cross database foreign keys. However, this configuration is not -officially supported by Django. diff --git a/parts/django/docs/topics/db/optimization.txt b/parts/django/docs/topics/db/optimization.txt deleted file mode 100644 index 7d51052..0000000 --- a/parts/django/docs/topics/db/optimization.txt +++ /dev/null @@ -1,260 +0,0 @@ -============================ -Database access optimization -============================ - -Django's database layer provides various ways to help developers get the most -out of their databases. This document gathers together links to the relevant -documentation, and adds various tips, organized under a number of headings that -outline the steps to take when attempting to optimize your database usage. - -Profile first -============= - -As general programming practice, this goes without saying. Find out :ref:`what -queries you are doing and what they are costing you -<faq-see-raw-sql-queries>`. You may also want to use an external project like -django-debug-toolbar_, or a tool that monitors your database directly. - -Remember that you may be optimizing for speed or memory or both, depending on -your requirements. Sometimes optimizing for one will be detrimental to the -other, but sometimes they will help each other. Also, work that is done by the -database process might not have the same cost (to you) as the same amount of -work done in your Python process. It is up to you to decide what your -priorities are, where the balance must lie, and profile all of these as required -since this will depend on your application and server. - -With everything that follows, remember to profile after every change to ensure -that the change is a benefit, and a big enough benefit given the decrease in -readability of your code. **All** of the suggestions below come with the caveat -that in your circumstances the general principle might not apply, or might even -be reversed. - -.. _django-debug-toolbar: http://robhudson.github.com/django-debug-toolbar/ - -Use standard DB optimization techniques -======================================= - -...including: - -* Indexes. This is a number one priority, *after* you have determined from - profiling what indexes should be added. Use - :attr:`django.db.models.Field.db_index` to add these from Django. - -* Appropriate use of field types. - -We will assume you have done the obvious things above. The rest of this document -focuses on how to use Django in such a way that you are not doing unnecessary -work. This document also does not address other optimization techniques that -apply to all expensive operations, such as :doc:`general purpose caching -</topics/cache>`. - -Understand QuerySets -==================== - -Understanding :doc:`QuerySets </ref/models/querysets>` is vital to getting good -performance with simple code. In particular: - -Understand QuerySet evaluation ------------------------------- - -To avoid performance problems, it is important to understand: - -* that :ref:`QuerySets are lazy <querysets-are-lazy>`. - -* when :ref:`they are evaluated <when-querysets-are-evaluated>`. - -* how :ref:`the data is held in memory <caching-and-querysets>`. - -Understand cached attributes ----------------------------- - -As well as caching of the whole ``QuerySet``, there is caching of the result of -attributes on ORM objects. In general, attributes that are not callable will be -cached. For example, assuming the :ref:`example Weblog models -<queryset-model-example>`:: - - >>> entry = Entry.objects.get(id=1) - >>> entry.blog # Blog object is retrieved at this point - >>> entry.blog # cached version, no DB access - -But in general, callable attributes cause DB lookups every time:: - - >>> entry = Entry.objects.get(id=1) - >>> entry.authors.all() # query performed - >>> entry.authors.all() # query performed again - -Be careful when reading template code - the template system does not allow use -of parentheses, but will call callables automatically, hiding the above -distinction. - -Be careful with your own custom properties - it is up to you to implement -caching. - -Use the ``with`` template tag ------------------------------ - -To make use of the caching behaviour of ``QuerySet``, you may need to use the -:ttag:`with` template tag. - -Use ``iterator()`` ------------------- - -When you have a lot of objects, the caching behaviour of the ``QuerySet`` can -cause a large amount of memory to be used. In this case, -:meth:`~django.db.models.QuerySet.iterator()` may help. - -Do database work in the database rather than in Python -====================================================== - -For instance: - -* At the most basic level, use :ref:`filter and exclude <queryset-api>` to do - filtering in the database. - -* Use :ref:`F() object query expressions <query-expressions>` to do filtering - against other fields within the same model. - -* Use :doc:`annotate to do aggregation in the database </topics/db/aggregation>`. - -If these aren't enough to generate the SQL you need: - -Use ``QuerySet.extra()`` ------------------------- - -A less portable but more powerful method is -:meth:`~django.db.models.QuerySet.extra()`, which allows some SQL to be -explicitly added to the query. If that still isn't powerful enough: - -Use raw SQL ------------ - -Write your own :doc:`custom SQL to retrieve data or populate models -</topics/db/sql>`. Use ``django.db.connection.queries`` to find out what Django -is writing for you and start from there. - -Retrieve everything at once if you know you will need it -======================================================== - -Hitting the database multiple times for different parts of a single 'set' of -data that you will need all parts of is, in general, less efficient than -retrieving it all in one query. This is particularly important if you have a -query that is executed in a loop, and could therefore end up doing many database -queries, when only one was needed. So: - -Use ``QuerySet.select_related()`` ---------------------------------- - -Understand :ref:`QuerySet.select_related() <select-related>` thoroughly, and use it: - -* in view code, - -* and in :doc:`managers and default managers </topics/db/managers>` where - appropriate. Be aware when your manager is and is not used; sometimes this is - tricky so don't make assumptions. - -Don't retrieve things you don't need -==================================== - -Use ``QuerySet.values()`` and ``values_list()`` ------------------------------------------------ - -When you just want a ``dict`` or ``list`` of values, and don't need ORM model -objects, make appropriate usage of :meth:`~django.db.models.QuerySet.values()`. -These can be useful for replacing model objects in template code - as long as -the dicts you supply have the same attributes as those used in the template, -you are fine. - -Use ``QuerySet.defer()`` and ``only()`` ---------------------------------------- - -Use :meth:`~django.db.models.QuerySet.defer()` and -:meth:`~django.db.models.QuerySet.only()` if there are database columns you -know that you won't need (or won't need in most cases) to avoid loading -them. Note that if you *do* use them, the ORM will have to go and get them in a -separate query, making this a pessimization if you use it inappropriately. - -Use QuerySet.count() --------------------- - -...if you only want the count, rather than doing ``len(queryset)``. - -Use QuerySet.exists() ---------------------- - -...if you only want to find out if at least one result exists, rather than ``if -queryset``. - -But: - -Don't overuse ``count()`` and ``exists()`` ------------------------------------------- - -If you are going to need other data from the QuerySet, just evaluate it. - -For example, assuming an Email class that has a ``body`` attribute and a -many-to-many relation to User, the following template code is optimal: - -.. code-block:: html+django - - {% if display_inbox %} - {% with user.emails.all as emails %} - {% if emails %} - <p>You have {{ emails|length }} email(s)</p> - {% for email in emails %} - <p>{{ email.body }}</p> - {% endfor %} - {% else %} - <p>No messages today.</p> - {% endif %} - {% endwith %} - {% endif %} - - -It is optimal because: - - 1. Since QuerySets are lazy, this does no database if 'display_inbox' is False. - - #. Use of ``with`` means that we store ``user.emails.all`` in a variable for - later use, allowing its cache to be re-used. - - #. The line ``{% if emails %}`` causes ``QuerySet.__nonzero__()`` to be called, - which causes the ``user.emails.all()`` query to be run on the database, and - at the least the first line to be turned into an ORM object. If there aren't - any results, it will return False, otherwise True. - - #. The use of ``{{ emails|length }}`` calls ``QuerySet.__len__()``, filling - out the rest of the cache without doing another query. - - #. The ``for`` loop iterates over the already filled cache. - -In total, this code does either one or zero database queries. The only -deliberate optimization performed is the use of the ``with`` tag. Using -``QuerySet.exists()`` or ``QuerySet.count()`` at any point would cause -additional queries. - -Use ``QuerySet.update()`` and ``delete()`` ------------------------------------------- - -Rather than retrieve a load of objects, set some values, and save them -individual, use a bulk SQL UPDATE statement, via :ref:`QuerySet.update() -<topics-db-queries-update>`. Similarly, do :ref:`bulk deletes -<topics-db-queries-delete>` where possible. - -Note, however, that these bulk update methods cannot call the ``save()`` or -``delete()`` methods of individual instances, which means that any custom -behaviour you have added for these methods will not be executed, including -anything driven from the normal database object :doc:`signals </ref/signals>`. - -Use foreign key values directly -------------------------------- - -If you only need a foreign key value, use the foreign key value that is already on -the object you've got, rather than getting the whole related object and taking -its primary key. i.e. do:: - - entry.blog_id - -instead of:: - - entry.blog.id - diff --git a/parts/django/docs/topics/db/queries.txt b/parts/django/docs/topics/db/queries.txt deleted file mode 100644 index 923b1e4..0000000 --- a/parts/django/docs/topics/db/queries.txt +++ /dev/null @@ -1,1110 +0,0 @@ -============== -Making queries -============== - -.. currentmodule:: django.db.models - -Once you've created your :doc:`data models </topics/db/models>`, Django -automatically gives you a database-abstraction API that lets you create, -retrieve, update and delete objects. This document explains how to use this -API. Refer to the :doc:`data model reference </ref/models/index>` for full -details of all the various model lookup options. - -Throughout this guide (and in the reference), we'll refer to the following -models, which comprise a Weblog application: - -.. _queryset-model-example: - -.. code-block:: python - - class Blog(models.Model): - name = models.CharField(max_length=100) - tagline = models.TextField() - - def __unicode__(self): - return self.name - - class Author(models.Model): - name = models.CharField(max_length=50) - email = models.EmailField() - - def __unicode__(self): - return self.name - - class Entry(models.Model): - blog = models.ForeignKey(Blog) - headline = models.CharField(max_length=255) - body_text = models.TextField() - pub_date = models.DateTimeField() - authors = models.ManyToManyField(Author) - n_comments = models.IntegerField() - n_pingbacks = models.IntegerField() - rating = models.IntegerField() - - def __unicode__(self): - return self.headline - -Creating objects -================ - -To represent database-table data in Python objects, Django uses an intuitive -system: A model class represents a database table, and an instance of that -class represents a particular record in the database table. - -To create an object, instantiate it using keyword arguments to the model class, -then call ``save()`` to save it to the database. - -You import the model class from wherever it lives on the Python path, as you -may expect. (We point this out here because previous Django versions required -funky model importing.) - -Assuming models live in a file ``mysite/blog/models.py``, here's an example:: - - >>> from blog.models import Blog - >>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.') - >>> b.save() - -This performs an ``INSERT`` SQL statement behind the scenes. Django doesn't hit -the database until you explicitly call ``save()``. - -The ``save()`` method has no return value. - -.. seealso:: - - ``save()`` takes a number of advanced options not described here. - See the documentation for ``save()`` for complete details. - - To create an object and save it all in one step see the ```create()``` - method. - -Saving changes to objects -========================= - -To save changes to an object that's already in the database, use ``save()``. - -Given a ``Blog`` instance ``b5`` that has already been saved to the database, -this example changes its name and updates its record in the database:: - - >> b5.name = 'New name' - >> b5.save() - -This performs an ``UPDATE`` SQL statement behind the scenes. Django doesn't hit -the database until you explicitly call ``save()``. - -Saving ``ForeignKey`` and ``ManyToManyField`` fields ----------------------------------------------------- - -Updating a ``ForeignKey`` field works exactly the same way as saving a normal -field; simply assign an object of the right type to the field in question. -This example updates the ``blog`` attribute of an ``Entry`` instance ``entry``:: - - >>> from blog.models import Entry - >>> entry = Entry.objects.get(pk=1) - >>> cheese_blog = Blog.objects.get(name="Cheddar Talk") - >>> entry.blog = cheese_blog - >>> entry.save() - -Updating a ``ManyToManyField`` works a little differently; use the ``add()`` -method on the field to add a record to the relation. This example adds the -``Author`` instance ``joe`` to the ``entry`` object:: - - >>> from blog.models import Author - >>> joe = Author.objects.create(name="Joe") - >>> entry.authors.add(joe) - -Django will complain if you try to assign or add an object of the wrong type. - -Retrieving objects -================== - -To retrieve objects from your database, you construct a ``QuerySet`` via a -``Manager`` on your model class. - -A ``QuerySet`` represents a collection of objects from your database. It can -have zero, one or many *filters* -- criteria that narrow down the collection -based on given parameters. In SQL terms, a ``QuerySet`` equates to a ``SELECT`` -statement, and a filter is a limiting clause such as ``WHERE`` or ``LIMIT``. - -You get a ``QuerySet`` by using your model's ``Manager``. Each model has at -least one ``Manager``, and it's called ``objects`` by default. Access it -directly via the model class, like so:: - - >>> Blog.objects - <django.db.models.manager.Manager object at ...> - >>> b = Blog(name='Foo', tagline='Bar') - >>> b.objects - Traceback: - ... - AttributeError: "Manager isn't accessible via Blog instances." - -.. note:: - - ``Managers`` are accessible only via model classes, rather than from model - instances, to enforce a separation between "table-level" operations and - "record-level" operations. - -The ``Manager`` is the main source of ``QuerySets`` for a model. It acts as a -"root" ``QuerySet`` that describes all objects in the model's database table. -For example, ``Blog.objects`` is the initial ``QuerySet`` that contains all -``Blog`` objects in the database. - -Retrieving all objects ----------------------- - -The simplest way to retrieve objects from a table is to get all of them. -To do this, use the ``all()`` method on a ``Manager``:: - - >>> all_entries = Entry.objects.all() - -The ``all()`` method returns a ``QuerySet`` of all the objects in the database. - -(If ``Entry.objects`` is a ``QuerySet``, why can't we just do ``Entry.objects``? -That's because ``Entry.objects``, the root ``QuerySet``, is a special case -that cannot be evaluated. The ``all()`` method returns a ``QuerySet`` that -*can* be evaluated.) - - -Retrieving specific objects with filters ----------------------------------------- - -The root ``QuerySet`` provided by the ``Manager`` describes all objects in the -database table. Usually, though, you'll need to select only a subset of the -complete set of objects. - -To create such a subset, you refine the initial ``QuerySet``, adding filter -conditions. The two most common ways to refine a ``QuerySet`` are: - - ``filter(**kwargs)`` - Returns a new ``QuerySet`` containing objects that match the given - lookup parameters. - - ``exclude(**kwargs)`` - Returns a new ``QuerySet`` containing objects that do *not* match the - given lookup parameters. - -The lookup parameters (``**kwargs`` in the above function definitions) should -be in the format described in `Field lookups`_ below. - -For example, to get a ``QuerySet`` of blog entries from the year 2006, use -``filter()`` like so:: - - Entry.objects.filter(pub_date__year=2006) - -We don't have to add an ``all()`` -- ``Entry.objects.all().filter(...)``. That -would still work, but you only need ``all()`` when you want all objects from the -root ``QuerySet``. - -.. _chaining-filters: - -Chaining filters -~~~~~~~~~~~~~~~~ - -The result of refining a ``QuerySet`` is itself a ``QuerySet``, so it's -possible to chain refinements together. For example:: - - >>> Entry.objects.filter( - ... headline__startswith='What' - ... ).exclude( - ... pub_date__gte=datetime.now() - ... ).filter( - ... pub_date__gte=datetime(2005, 1, 1) - ... ) - -This takes the initial ``QuerySet`` of all entries in the database, adds a -filter, then an exclusion, then another filter. The final result is a -``QuerySet`` containing all entries with a headline that starts with "What", -that were published between January 1, 2005, and the current day. - -.. _filtered-querysets-are-unique: - -Filtered QuerySets are unique -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Each time you refine a ``QuerySet``, you get a brand-new ``QuerySet`` that is -in no way bound to the previous ``QuerySet``. Each refinement creates a -separate and distinct ``QuerySet`` that can be stored, used and reused. - -Example:: - - >> q1 = Entry.objects.filter(headline__startswith="What") - >> q2 = q1.exclude(pub_date__gte=datetime.now()) - >> q3 = q1.filter(pub_date__gte=datetime.now()) - -These three ``QuerySets`` are separate. The first is a base ``QuerySet`` -containing all entries that contain a headline starting with "What". The second -is a subset of the first, with an additional criteria that excludes records -whose ``pub_date`` is greater than now. The third is a subset of the first, -with an additional criteria that selects only the records whose ``pub_date`` is -greater than now. The initial ``QuerySet`` (``q1``) is unaffected by the -refinement process. - -.. _querysets-are-lazy: - -QuerySets are lazy -~~~~~~~~~~~~~~~~~~ - -``QuerySets`` are lazy -- the act of creating a ``QuerySet`` doesn't involve any -database activity. You can stack filters together all day long, and Django won't -actually run the query until the ``QuerySet`` is *evaluated*. Take a look at -this example:: - - >>> q = Entry.objects.filter(headline__startswith="What") - >>> q = q.filter(pub_date__lte=datetime.now()) - >>> q = q.exclude(body_text__icontains="food") - >>> print q - -Though this looks like three database hits, in fact it hits the database only -once, at the last line (``print q``). In general, the results of a ``QuerySet`` -aren't fetched from the database until you "ask" for them. When you do, the -``QuerySet`` is *evaluated* by accessing the database. For more details on -exactly when evaluation takes place, see :ref:`when-querysets-are-evaluated`. - - -.. _retrieving-single-object-with-get: - -Retrieving a single object with get ------------------------------------ - -``.filter()`` will always give you a ``QuerySet``, even if only a single -object matches the query - in this case, it will be a ``QuerySet`` containing -a single element. - -If you know there is only one object that matches your query, you can use -the ``get()`` method on a `Manager` which returns the object directly:: - - >>> one_entry = Entry.objects.get(pk=1) - -You can use any query expression with ``get()``, just like with ``filter()`` - -again, see `Field lookups`_ below. - -Note that there is a difference between using ``.get()``, and using -``.filter()`` with a slice of ``[0]``. If there are no results that match the -query, ``.get()`` will raise a ``DoesNotExist`` exception. This exception is an -attribute of the model class that the query is being performed on - so in the -code above, if there is no ``Entry`` object with a primary key of 1, Django will -raise ``Entry.DoesNotExist``. - -Similarly, Django will complain if more than one item matches the ``get()`` -query. In this case, it will raise ``MultipleObjectsReturned``, which again is -an attribute of the model class itself. - - -Other QuerySet methods ----------------------- - -Most of the time you'll use ``all()``, ``get()``, ``filter()`` and ``exclude()`` -when you need to look up objects from the database. However, that's far from all -there is; see the :ref:`QuerySet API Reference <queryset-api>` for a complete -list of all the various ``QuerySet`` methods. - -.. _limiting-querysets: - -Limiting QuerySets ------------------- - -Use a subset of Python's array-slicing syntax to limit your ``QuerySet`` to a -certain number of results. This is the equivalent of SQL's ``LIMIT`` and -``OFFSET`` clauses. - -For example, this returns the first 5 objects (``LIMIT 5``):: - - >>> Entry.objects.all()[:5] - -This returns the sixth through tenth objects (``OFFSET 5 LIMIT 5``):: - - >>> Entry.objects.all()[5:10] - -Negative indexing (i.e. ``Entry.objects.all()[-1]``) is not supported. - -Generally, slicing a ``QuerySet`` returns a new ``QuerySet`` -- it doesn't -evaluate the query. An exception is if you use the "step" parameter of Python -slice syntax. For example, this would actually execute the query in order to -return a list of every *second* object of the first 10:: - - >>> Entry.objects.all()[:10:2] - -To retrieve a *single* object rather than a list -(e.g. ``SELECT foo FROM bar LIMIT 1``), use a simple index instead of a -slice. For example, this returns the first ``Entry`` in the database, after -ordering entries alphabetically by headline:: - - >>> Entry.objects.order_by('headline')[0] - -This is roughly equivalent to:: - - >>> Entry.objects.order_by('headline')[0:1].get() - -Note, however, that the first of these will raise ``IndexError`` while the -second will raise ``DoesNotExist`` if no objects match the given criteria. See -:meth:`~django.db.models.QuerySet.get` for more details. - -.. _field-lookups-intro: - -Field lookups -------------- - -Field lookups are how you specify the meat of an SQL ``WHERE`` clause. They're -specified as keyword arguments to the ``QuerySet`` methods ``filter()``, -``exclude()`` and ``get()``. - -Basic lookups keyword arguments take the form ``field__lookuptype=value``. -(That's a double-underscore). For example:: - - >>> Entry.objects.filter(pub_date__lte='2006-01-01') - -translates (roughly) into the following SQL:: - - SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01'; - -.. admonition:: How this is possible - - Python has the ability to define functions that accept arbitrary name-value - arguments whose names and values are evaluated at runtime. For more - information, see `Keyword Arguments`_ in the official Python tutorial. - - .. _`Keyword Arguments`: http://docs.python.org/tutorial/controlflow.html#keyword-arguments - -If you pass an invalid keyword argument, a lookup function will raise -``TypeError``. - -The database API supports about two dozen lookup types; a complete reference -can be found in the :ref:`field lookup reference <field-lookups>`. To give you a taste of what's available, here's some of the more common lookups -you'll probably use: - - :lookup:`exact` - An "exact" match. For example:: - - >>> Entry.objects.get(headline__exact="Man bites dog") - - Would generate SQL along these lines: - - .. code-block:: sql - - SELECT ... WHERE headline = 'Man bites dog'; - - If you don't provide a lookup type -- that is, if your keyword argument - doesn't contain a double underscore -- the lookup type is assumed to be - ``exact``. - - For example, the following two statements are equivalent:: - - >>> Blog.objects.get(id__exact=14) # Explicit form - >>> Blog.objects.get(id=14) # __exact is implied - - This is for convenience, because ``exact`` lookups are the common case. - - :lookup:`iexact` - A case-insensitive match. So, the query:: - - >>> Blog.objects.get(name__iexact="beatles blog") - - Would match a ``Blog`` titled "Beatles Blog", "beatles blog", or even - "BeAtlES blOG". - - :lookup:`contains` - Case-sensitive containment test. For example:: - - Entry.objects.get(headline__contains='Lennon') - - Roughly translates to this SQL: - - .. code-block:: sql - - SELECT ... WHERE headline LIKE '%Lennon%'; - - Note this will match the headline ``'Today Lennon honored'`` but not - ``'today lennon honored'``. - - There's also a case-insensitive version, :lookup:`icontains`. - - :lookup:`startswith`, :lookup:`endswith` - Starts-with and ends-with search, respectively. There are also - case-insensitive versions called :lookup:`istartswith` and - :lookup:`iendswith`. - -Again, this only scratches the surface. A complete reference can be found in the -:ref:`field lookup reference <field-lookups>`. - -Lookups that span relationships -------------------------------- - -Django offers a powerful and intuitive way to "follow" relationships in -lookups, taking care of the SQL ``JOIN``\s for you automatically, behind the -scenes. To span a relationship, just use the field name of related fields -across models, separated by double underscores, until you get to the field you -want. - -This example retrieves all ``Entry`` objects with a ``Blog`` whose ``name`` -is ``'Beatles Blog'``:: - - >>> Entry.objects.filter(blog__name__exact='Beatles Blog') - -This spanning can be as deep as you'd like. - -It works backwards, too. To refer to a "reverse" relationship, just use the -lowercase name of the model. - -This example retrieves all ``Blog`` objects which have at least one ``Entry`` -whose ``headline`` contains ``'Lennon'``:: - - >>> Blog.objects.filter(entry__headline__contains='Lennon') - -If you are filtering across multiple relationships and one of the intermediate -models doesn't have a value that meets the filter condition, Django will treat -it as if there is an empty (all values are ``NULL``), but valid, object there. -All this means is that no error will be raised. For example, in this filter:: - - Blog.objects.filter(entry__authors__name='Lennon') - -(if there was a related ``Author`` model), if there was no ``author`` -associated with an entry, it would be treated as if there was also no ``name`` -attached, rather than raising an error because of the missing ``author``. -Usually this is exactly what you want to have happen. The only case where it -might be confusing is if you are using ``isnull``. Thus:: - - Blog.objects.filter(entry__authors__name__isnull=True) - -will return ``Blog`` objects that have an empty ``name`` on the ``author`` and -also those which have an empty ``author`` on the ``entry``. If you don't want -those latter objects, you could write:: - - Blog.objects.filter(entry__authors__isnull=False, - entry__authors__name__isnull=True) - -Spanning multi-valued relationships -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -When you are filtering an object based on a ``ManyToManyField`` or a reverse -``ForeignKey``, there are two different sorts of filter you may be -interested in. Consider the ``Blog``/``Entry`` relationship (``Blog`` to -``Entry`` is a one-to-many relation). We might be interested in finding blogs -that have an entry which has both *"Lennon"* in the headline and was published -in 2008. Or we might want to find blogs that have an entry with *"Lennon"* in -the headline as well as an entry that was published in 2008. Since there are -multiple entries associated with a single ``Blog``, both of these queries are -possible and make sense in some situations. - -The same type of situation arises with a ``ManyToManyField``. For example, if -an ``Entry`` has a ``ManyToManyField`` called ``tags``, we might want to find -entries linked to tags called *"music"* and *"bands"* or we might want an -entry that contains a tag with a name of *"music"* and a status of *"public"*. - -To handle both of these situations, Django has a consistent way of processing -``filter()`` and ``exclude()`` calls. Everything inside a single ``filter()`` -call is applied simultaneously to filter out items matching all those -requirements. Successive ``filter()`` calls further restrict the set of -objects, but for multi-valued relations, they apply to any object linked to -the primary model, not necessarily those objects that were selected by an -earlier ``filter()`` call. - -That may sound a bit confusing, so hopefully an example will clarify. To -select all blogs that contain entries with both *"Lennon"* in the headline -and that were published in 2008 (the same entry satisfying both conditions), -we would write:: - - Blog.objects.filter(entry__headline__contains='Lennon', - entry__pub_date__year=2008) - -To select all blogs that contain an entry with *"Lennon"* in the headline -**as well as** an entry that was published in 2008, we would write:: - - Blog.objects.filter(entry__headline__contains='Lennon').filter( - entry__pub_date__year=2008) - -In this second example, the first filter restricted the queryset to all those -blogs linked to that particular type of entry. The second filter restricted -the set of blogs *further* to those that are also linked to the second type of -entry. The entries select by the second filter may or may not be the same as -the entries in the first filter. We are filtering the ``Blog`` items with each -filter statement, not the ``Entry`` items. - -All of this behavior also applies to ``exclude()``: all the conditions in a -single ``exclude()`` statement apply to a single instance (if those conditions -are talking about the same multi-valued relation). Conditions in subsequent -``filter()`` or ``exclude()`` calls that refer to the same relation may end up -filtering on different linked objects. - -.. _query-expressions: - -Filters can reference fields on the model ------------------------------------------ - -.. versionadded:: 1.1 - -In the examples given so far, we have constructed filters that compare -the value of a model field with a constant. But what if you want to compare -the value of a model field with another field on the same model? - -Django provides the ``F()`` object to allow such comparisons. Instances -of ``F()`` act as a reference to a model field within a query. These -references can then be used in query filters to compare the values of two -different fields on the same model instance. - -For example, to find a list of all blog entries that have had more comments -than pingbacks, we construct an ``F()`` object to reference the comment count, -and use that ``F()`` object in the query:: - - >>> from django.db.models import F - >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks')) - -Django supports the use of addition, subtraction, multiplication, -division and modulo arithmetic with ``F()`` objects, both with constants -and with other ``F()`` objects. To find all the blog entries with more than -*twice* as many comments as pingbacks, we modify the query:: - - >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2) - -To find all the entries where the rating of the entry is less than the -sum of the pingback count and comment count, we would issue the -query:: - - >>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks')) - -You can also use the double underscore notation to span relationships in -an ``F()`` object. An ``F()`` object with a double underscore will introduce -any joins needed to access the related object. For example, to retrieve all -the entries where the author's name is the same as the blog name, we could -issue the query: - - >>> Entry.objects.filter(authors__name=F('blog__name')) - -The pk lookup shortcut ----------------------- - -For convenience, Django provides a ``pk`` lookup shortcut, which stands for -"primary key". - -In the example ``Blog`` model, the primary key is the ``id`` field, so these -three statements are equivalent:: - - >>> Blog.objects.get(id__exact=14) # Explicit form - >>> Blog.objects.get(id=14) # __exact is implied - >>> Blog.objects.get(pk=14) # pk implies id__exact - -The use of ``pk`` isn't limited to ``__exact`` queries -- any query term -can be combined with ``pk`` to perform a query on the primary key of a model:: - - # Get blogs entries with id 1, 4 and 7 - >>> Blog.objects.filter(pk__in=[1,4,7]) - - # Get all blog entries with id > 14 - >>> Blog.objects.filter(pk__gt=14) - -``pk`` lookups also work across joins. For example, these three statements are -equivalent:: - - >>> Entry.objects.filter(blog__id__exact=3) # Explicit form - >>> Entry.objects.filter(blog__id=3) # __exact is implied - >>> Entry.objects.filter(blog__pk=3) # __pk implies __id__exact - -Escaping percent signs and underscores in LIKE statements ---------------------------------------------------------- - -The field lookups that equate to ``LIKE`` SQL statements (``iexact``, -``contains``, ``icontains``, ``startswith``, ``istartswith``, ``endswith`` -and ``iendswith``) will automatically escape the two special characters used in -``LIKE`` statements -- the percent sign and the underscore. (In a ``LIKE`` -statement, the percent sign signifies a multiple-character wildcard and the -underscore signifies a single-character wildcard.) - -This means things should work intuitively, so the abstraction doesn't leak. -For example, to retrieve all the entries that contain a percent sign, just use -the percent sign as any other character:: - - >>> Entry.objects.filter(headline__contains='%') - -Django takes care of the quoting for you; the resulting SQL will look something -like this: - -.. code-block:: sql - - SELECT ... WHERE headline LIKE '%\%%'; - -Same goes for underscores. Both percentage signs and underscores are handled -for you transparently. - -.. _caching-and-querysets: - -Caching and QuerySets ---------------------- - -Each ``QuerySet`` contains a cache, to minimize database access. It's important -to understand how it works, in order to write the most efficient code. - -In a newly created ``QuerySet``, the cache is empty. The first time a -``QuerySet`` is evaluated -- and, hence, a database query happens -- Django -saves the query results in the ``QuerySet``'s cache and returns the results -that have been explicitly requested (e.g., the next element, if the -``QuerySet`` is being iterated over). Subsequent evaluations of the -``QuerySet`` reuse the cached results. - -Keep this caching behavior in mind, because it may bite you if you don't use -your ``QuerySet``\s correctly. For example, the following will create two -``QuerySet``\s, evaluate them, and throw them away:: - - >>> print [e.headline for e in Entry.objects.all()] - >>> print [e.pub_date for e in Entry.objects.all()] - -That means the same database query will be executed twice, effectively doubling -your database load. Also, there's a possibility the two lists may not include -the same database records, because an ``Entry`` may have been added or deleted -in the split second between the two requests. - -To avoid this problem, simply save the ``QuerySet`` and reuse it:: - - >>> queryset = Entry.objects.all() - >>> print [p.headline for p in queryset] # Evaluate the query set. - >>> print [p.pub_date for p in queryset] # Re-use the cache from the evaluation. - -.. _complex-lookups-with-q: - -Complex lookups with Q objects -============================== - -Keyword argument queries -- in ``filter()``, etc. -- are "AND"ed together. If -you need to execute more complex queries (for example, queries with ``OR`` -statements), you can use ``Q`` objects. - -A ``Q`` object (``django.db.models.Q``) is an object used to encapsulate a -collection of keyword arguments. These keyword arguments are specified as in -"Field lookups" above. - -For example, this ``Q`` object encapsulates a single ``LIKE`` query:: - - Q(question__startswith='What') - -``Q`` objects can be combined using the ``&`` and ``|`` operators. When an -operator is used on two ``Q`` objects, it yields a new ``Q`` object. - -For example, this statement yields a single ``Q`` object that represents the -"OR" of two ``"question__startswith"`` queries:: - - Q(question__startswith='Who') | Q(question__startswith='What') - -This is equivalent to the following SQL ``WHERE`` clause:: - - WHERE question LIKE 'Who%' OR question LIKE 'What%' - -You can compose statements of arbitrary complexity by combining ``Q`` objects -with the ``&`` and ``|`` operators and use parenthetical grouping. Also, ``Q`` -objects can be negated using the ``~`` operator, allowing for combined lookups -that combine both a normal query and a negated (``NOT``) query:: - - Q(question__startswith='Who') | ~Q(pub_date__year=2005) - -Each lookup function that takes keyword-arguments (e.g. ``filter()``, -``exclude()``, ``get()``) can also be passed one or more ``Q`` objects as -positional (not-named) arguments. If you provide multiple ``Q`` object -arguments to a lookup function, the arguments will be "AND"ed together. For -example:: - - Poll.objects.get( - Q(question__startswith='Who'), - Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) - ) - -... roughly translates into the SQL:: - - SELECT * from polls WHERE question LIKE 'Who%' - AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06') - -Lookup functions can mix the use of ``Q`` objects and keyword arguments. All -arguments provided to a lookup function (be they keyword arguments or ``Q`` -objects) are "AND"ed together. However, if a ``Q`` object is provided, it must -precede the definition of any keyword arguments. For example:: - - Poll.objects.get( - Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)), - question__startswith='Who') - -... would be a valid query, equivalent to the previous example; but:: - - # INVALID QUERY - Poll.objects.get( - question__startswith='Who', - Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))) - -... would not be valid. - -.. seealso:: - - The `OR lookups examples`_ in the Django unit tests show some possible uses - of ``Q``. - - .. _OR lookups examples: http://code.djangoproject.com/browser/django/trunk/tests/modeltests/or_lookups/tests.py - -Comparing objects -================= - -To compare two model instances, just use the standard Python comparison operator, -the double equals sign: ``==``. Behind the scenes, that compares the primary -key values of two models. - -Using the ``Entry`` example above, the following two statements are equivalent:: - - >>> some_entry == other_entry - >>> some_entry.id == other_entry.id - -If a model's primary key isn't called ``id``, no problem. Comparisons will -always use the primary key, whatever it's called. For example, if a model's -primary key field is called ``name``, these two statements are equivalent:: - - >>> some_obj == other_obj - >>> some_obj.name == other_obj.name - -.. _topics-db-queries-delete: - -Deleting objects -================ - -The delete method, conveniently, is named ``delete()``. This method immediately -deletes the object and has no return value. Example:: - - e.delete() - -You can also delete objects in bulk. Every ``QuerySet`` has a ``delete()`` -method, which deletes all members of that ``QuerySet``. - -For example, this deletes all ``Entry`` objects with a ``pub_date`` year of -2005:: - - Entry.objects.filter(pub_date__year=2005).delete() - -Keep in mind that this will, whenever possible, be executed purely in -SQL, and so the ``delete()`` methods of individual object instances -will not necessarily be called during the process. If you've provided -a custom ``delete()`` method on a model class and want to ensure that -it is called, you will need to "manually" delete instances of that -model (e.g., by iterating over a ``QuerySet`` and calling ``delete()`` -on each object individually) rather than using the bulk ``delete()`` -method of a ``QuerySet``. - -When Django deletes an object, it emulates the behavior of the SQL -constraint ``ON DELETE CASCADE`` -- in other words, any objects which -had foreign keys pointing at the object to be deleted will be deleted -along with it. For example:: - - b = Blog.objects.get(pk=1) - # This will delete the Blog and all of its Entry objects. - b.delete() - -Note that ``delete()`` is the only ``QuerySet`` method that is not exposed on a -``Manager`` itself. This is a safety mechanism to prevent you from accidentally -requesting ``Entry.objects.delete()``, and deleting *all* the entries. If you -*do* want to delete all the objects, then you have to explicitly request a -complete query set:: - - Entry.objects.all().delete() - -.. _topics-db-queries-update: - -Updating multiple objects at once -================================= - -.. versionadded:: 1.0 - -Sometimes you want to set a field to a particular value for all the objects in -a ``QuerySet``. You can do this with the ``update()`` method. For example:: - - # Update all the headlines with pub_date in 2007. - Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same') - -You can only set non-relation fields and ``ForeignKey`` fields using this -method. To update a non-relation field, provide the new value as a constant. -To update ``ForeignKey`` fields, set the new value to be the new model -instance you want to point to. For example:: - - >>> b = Blog.objects.get(pk=1) - - # Change every Entry so that it belongs to this Blog. - >>> Entry.objects.all().update(blog=b) - -The ``update()`` method is applied instantly and returns the number of rows -affected by the query. The only restriction on the ``QuerySet`` that is -updated is that it can only access one database table, the model's main -table. You can filter based on related fields, but you can only update columns -in the model's main table. Example:: - - >>> b = Blog.objects.get(pk=1) - - # Update all the headlines belonging to this Blog. - >>> Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same') - -Be aware that the ``update()`` method is converted directly to an SQL -statement. It is a bulk operation for direct updates. It doesn't run any -``save()`` methods on your models, or emit the ``pre_save`` or ``post_save`` -signals (which are a consequence of calling ``save()``). If you want to save -every item in a ``QuerySet`` and make sure that the ``save()`` method is -called on each instance, you don't need any special function to handle that. -Just loop over them and call ``save()``:: - - for item in my_queryset: - item.save() - -.. versionadded:: 1.1 - -Calls to update can also use :ref:`F() objects <query-expressions>` to update -one field based on the value of another field in the model. This is especially -useful for incrementing counters based upon their current value. For example, to -increment the pingback count for every entry in the blog:: - - >>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1) - -However, unlike ``F()`` objects in filter and exclude clauses, you can't -introduce joins when you use ``F()`` objects in an update -- you can only -reference fields local to the model being updated. If you attempt to introduce -a join with an ``F()`` object, a ``FieldError`` will be raised:: - - # THIS WILL RAISE A FieldError - >>> Entry.objects.update(headline=F('blog__name')) - -Related objects -=============== - -When you define a relationship in a model (i.e., a ``ForeignKey``, -``OneToOneField``, or ``ManyToManyField``), instances of that model will have -a convenient API to access the related object(s). - -Using the models at the top of this page, for example, an ``Entry`` object ``e`` -can get its associated ``Blog`` object by accessing the ``blog`` attribute: -``e.blog``. - -(Behind the scenes, this functionality is implemented by Python descriptors_. -This shouldn't really matter to you, but we point it out here for the curious.) - -Django also creates API accessors for the "other" side of the relationship -- -the link from the related model to the model that defines the relationship. -For example, a ``Blog`` object ``b`` has access to a list of all related -``Entry`` objects via the ``entry_set`` attribute: ``b.entry_set.all()``. - -All examples in this section use the sample ``Blog``, ``Author`` and ``Entry`` -models defined at the top of this page. - -.. _descriptors: http://users.rcn.com/python/download/Descriptor.htm - -One-to-many relationships -------------------------- - -Forward -~~~~~~~ - -If a model has a ``ForeignKey``, instances of that model will have access to -the related (foreign) object via a simple attribute of the model. - -Example:: - - >>> e = Entry.objects.get(id=2) - >>> e.blog # Returns the related Blog object. - -You can get and set via a foreign-key attribute. As you may expect, changes to -the foreign key aren't saved to the database until you call ``save()``. -Example:: - - >>> e = Entry.objects.get(id=2) - >>> e.blog = some_blog - >>> e.save() - -If a ``ForeignKey`` field has ``null=True`` set (i.e., it allows ``NULL`` -values), you can assign ``None`` to it. Example:: - - >>> e = Entry.objects.get(id=2) - >>> e.blog = None - >>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;" - -Forward access to one-to-many relationships is cached the first time the -related object is accessed. Subsequent accesses to the foreign key on the same -object instance are cached. Example:: - - >>> e = Entry.objects.get(id=2) - >>> print e.blog # Hits the database to retrieve the associated Blog. - >>> print e.blog # Doesn't hit the database; uses cached version. - -Note that the ``select_related()`` ``QuerySet`` method recursively prepopulates -the cache of all one-to-many relationships ahead of time. Example:: - - >>> e = Entry.objects.select_related().get(id=2) - >>> print e.blog # Doesn't hit the database; uses cached version. - >>> print e.blog # Doesn't hit the database; uses cached version. - -.. _backwards-related-objects: - -Following relationships "backward" -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If a model has a ``ForeignKey``, instances of the foreign-key model will have -access to a ``Manager`` that returns all instances of the first model. By -default, this ``Manager`` is named ``FOO_set``, where ``FOO`` is the source -model name, lowercased. This ``Manager`` returns ``QuerySets``, which can be -filtered and manipulated as described in the "Retrieving objects" section -above. - -Example:: - - >>> b = Blog.objects.get(id=1) - >>> b.entry_set.all() # Returns all Entry objects related to Blog. - - # b.entry_set is a Manager that returns QuerySets. - >>> b.entry_set.filter(headline__contains='Lennon') - >>> b.entry_set.count() - -You can override the ``FOO_set`` name by setting the ``related_name`` -parameter in the ``ForeignKey()`` definition. For example, if the ``Entry`` -model was altered to ``blog = ForeignKey(Blog, related_name='entries')``, the -above example code would look like this:: - - >>> b = Blog.objects.get(id=1) - >>> b.entries.all() # Returns all Entry objects related to Blog. - - # b.entries is a Manager that returns QuerySets. - >>> b.entries.filter(headline__contains='Lennon') - >>> b.entries.count() - -You cannot access a reverse ``ForeignKey`` ``Manager`` from the class; it must -be accessed from an instance:: - - >>> Blog.entry_set - Traceback: - ... - AttributeError: "Manager must be accessed via instance". - -In addition to the ``QuerySet`` methods defined in "Retrieving objects" above, -the ``ForeignKey`` ``Manager`` has additional methods used to handle the set of -related objects. A synopsis of each is below, and complete details can be found -in the :doc:`related objects reference </ref/models/relations>`. - -``add(obj1, obj2, ...)`` - Adds the specified model objects to the related object set. - -``create(**kwargs)`` - Creates a new object, saves it and puts it in the related object set. - Returns the newly created object. - -``remove(obj1, obj2, ...)`` - Removes the specified model objects from the related object set. - -``clear()`` - Removes all objects from the related object set. - -To assign the members of a related set in one fell swoop, just assign to it -from any iterable object. The iterable can contain object instances, or just -a list of primary key values. For example:: - - b = Blog.objects.get(id=1) - b.entry_set = [e1, e2] - -In this example, ``e1`` and ``e2`` can be full Entry instances, or integer -primary key values. - -If the ``clear()`` method is available, any pre-existing objects will be -removed from the ``entry_set`` before all objects in the iterable (in this -case, a list) are added to the set. If the ``clear()`` method is *not* -available, all objects in the iterable will be added without removing any -existing elements. - -Each "reverse" operation described in this section has an immediate effect on -the database. Every addition, creation and deletion is immediately and -automatically saved to the database. - -Many-to-many relationships --------------------------- - -Both ends of a many-to-many relationship get automatic API access to the other -end. The API works just as a "backward" one-to-many relationship, above. - -The only difference is in the attribute naming: The model that defines the -``ManyToManyField`` uses the attribute name of that field itself, whereas the -"reverse" model uses the lowercased model name of the original model, plus -``'_set'`` (just like reverse one-to-many relationships). - -An example makes this easier to understand:: - - e = Entry.objects.get(id=3) - e.authors.all() # Returns all Author objects for this Entry. - e.authors.count() - e.authors.filter(name__contains='John') - - a = Author.objects.get(id=5) - a.entry_set.all() # Returns all Entry objects for this Author. - -Like ``ForeignKey``, ``ManyToManyField`` can specify ``related_name``. In the -above example, if the ``ManyToManyField`` in ``Entry`` had specified -``related_name='entries'``, then each ``Author`` instance would have an -``entries`` attribute instead of ``entry_set``. - -One-to-one relationships ------------------------- - -One-to-one relationships are very similar to many-to-one relationships. If you -define a :class:`~django.db.models.OneToOneField` on your model, instances of -that model will have access to the related object via a simple attribute of the -model. - -For example:: - - class EntryDetail(models.Model): - entry = models.OneToOneField(Entry) - details = models.TextField() - - ed = EntryDetail.objects.get(id=2) - ed.entry # Returns the related Entry object. - -The difference comes in "reverse" queries. The related model in a one-to-one -relationship also has access to a :class:`~django.db.models.Manager` object, but -that :class:`~django.db.models.Manager` represents a single object, rather than -a collection of objects:: - - e = Entry.objects.get(id=2) - e.entrydetail # returns the related EntryDetail object - -If no object has been assigned to this relationship, Django will raise -a ``DoesNotExist`` exception. - -Instances can be assigned to the reverse relationship in the same way as -you would assign the forward relationship:: - - e.entrydetail = ed - -How are the backward relationships possible? --------------------------------------------- - -Other object-relational mappers require you to define relationships on both -sides. The Django developers believe this is a violation of the DRY (Don't -Repeat Yourself) principle, so Django only requires you to define the -relationship on one end. - -But how is this possible, given that a model class doesn't know which other -model classes are related to it until those other model classes are loaded? - -The answer lies in the :setting:`INSTALLED_APPS` setting. The first time any model is -loaded, Django iterates over every model in :setting:`INSTALLED_APPS` and creates the -backward relationships in memory as needed. Essentially, one of the functions -of :setting:`INSTALLED_APPS` is to tell Django the entire model domain. - -Queries over related objects ----------------------------- - -Queries involving related objects follow the same rules as queries involving -normal value fields. When specifying the value for a query to match, you may -use either an object instance itself, or the primary key value for the object. - -For example, if you have a Blog object ``b`` with ``id=5``, the following -three queries would be identical:: - - Entry.objects.filter(blog=b) # Query using object instance - Entry.objects.filter(blog=b.id) # Query using id from instance - Entry.objects.filter(blog=5) # Query using id directly - -Falling back to raw SQL -======================= - -If you find yourself needing to write an SQL query that is too complex for -Django's database-mapper to handle, you can fall back on writing SQL by hand. -Django has a couple of options for writing raw SQL queries; see -:doc:`/topics/db/sql`. - -Finally, it's important to note that the Django database layer is merely an -interface to your database. You can access your database via other tools, -programming languages or database frameworks; there's nothing Django-specific -about your database. diff --git a/parts/django/docs/topics/db/sql.txt b/parts/django/docs/topics/db/sql.txt deleted file mode 100644 index cac9a72..0000000 --- a/parts/django/docs/topics/db/sql.txt +++ /dev/null @@ -1,279 +0,0 @@ -========================== -Performing raw SQL queries -========================== - -.. currentmodule:: django.db.models - -When the :doc:`model query APIs </topics/db/queries>` don't go far enough, you -can fall back to writing raw SQL. Django gives you two ways of performing raw -SQL queries: you can use :meth:`Manager.raw()` to `perform raw queries and -return model instances`__, or you can avoid the model layer entirely and -`execute custom SQL directly`__. - -__ `performing raw queries`_ -__ `executing custom SQL directly`_ - -Performing raw queries -====================== - -.. versionadded:: 1.2 - -The ``raw()`` manager method can be used to perform raw SQL queries that -return model instances: - -.. method:: Manager.raw(raw_query, params=None, translations=None) - -This method method takes a raw SQL query, executes it, and returns a -:class:`~django.db.models.query.RawQuerySet` instance. This -:class:`~django.db.models.query.RawQuerySet` instance can be iterated -over just like an normal QuerySet to provide object instances. - -This is best illustrated with an example. Suppose you've got the following model:: - - class Person(models.Model): - first_name = models.CharField(...) - last_name = models.CharField(...) - birth_date = models.DateField(...) - -You could then execute custom SQL like so:: - - >>> for p in Person.objects.raw('SELECT * FROM myapp_person'): - ... print p - John Smith - Jane Jones - -.. admonition:: Model table names - - Where'd the name of the ``Person`` table come from in that example? - - By default, Django figures out a database table name by joining the - model's "app label" -- the name you used in ``manage.py startapp`` -- to - the model's class name, with an underscore between them. In the example - we've assumed that the ``Person`` model lives in an app named ``myapp``, - so its table would be ``myapp_person``. - - For more details check out the documentation for the - :attr:`~Options.db_table` option, which also lets you manually set the - database table name. - -Of course, this example isn't very exciting -- it's exactly the same as -running ``Person.objects.all()``. However, ``raw()`` has a bunch of other -options that make it very powerful. - -Mapping query fields to model fields ------------------------------------- - -``raw()`` automatically maps fields in the query to fields on the model. - -The order of fields in your query doesn't matter. In other words, both -of the following queries work identically:: - - >>> Person.objects.raw('SELECT id, first_name, last_name, birth_date FROM myapp_person') - ... - >>> Person.objects.raw('SELECT last_name, birth_date, first_name, id FROM myapp_person') - ... - -Matching is done by name. This means that you can use SQL's ``AS`` clauses to -map fields in the query to model fields. So if you had some other table that -had ``Person`` data in it, you could easily map it into ``Person`` instances:: - - >>> Person.objects.raw('''SELECT first AS first_name, - ... last AS last_name, - ... bd AS birth_date, - ... pk as id, - ... FROM some_other_table''') - -As long as the names match, the model instances will be created correctly. - -Alternatively, you can map fields in the query to model fields using the -``translations`` argument to ``raw()``. This is a dictionary mapping names of -fields in the query to names of fields on the model. For example, the above -query could also be written:: - - >>> name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'} - >>> Person.objects.raw('SELECT * FROM some_other_table', translations=name_map) - -Index lookups -------------- - -``raw()`` supports indexing, so if you need only the first result you can -write:: - - >>> first_person = Person.objects.raw('SELECT * from myapp_person')[0] - -However, the indexing and slicing are not performed at the database level. If -you have a big amount of ``Person`` objects in your database, it is more -efficient to limit the query at the SQL level:: - - >>> first_person = Person.objects.raw('SELECT * from myapp_person LIMIT 1')[0] - -Deferring model fields ----------------------- - -Fields may also be left out:: - - >>> people = Person.objects.raw('SELECT id, first_name FROM myapp_person') - -The ``Person`` objects returned by this query will be deferred model instances -(see :meth:`~django.db.models.QuerySet.defer()`). This means that the fields -that are omitted from the query will be loaded on demand. For example:: - - >>> for p in Person.objects.raw('SELECT id, first_name FROM myapp_person'): - ... print p.first_name, # This will be retrieved by the original query - ... print p.last_name # This will be retrieved on demand - ... - John Smith - Jane Jones - -From outward appearances, this looks like the query has retrieved both -the first name and last name. However, this example actually issued 3 -queries. Only the first names were retrieved by the raw() query -- the -last names were both retrieved on demand when they were printed. - -There is only one field that you can't leave out - the primary key -field. Django uses the primary key to identify model instances, so it -must always be included in a raw query. An ``InvalidQuery`` exception -will be raised if you forget to include the primary key. - -Adding annotations ------------------- - -You can also execute queries containing fields that aren't defined on the -model. For example, we could use `PostgreSQL's age() function`__ to get a list -of people with their ages calculated by the database:: - - >>> people = Person.objects.raw('SELECT *, age(birth_date) AS age FROM myapp_person') - >>> for p in people: - ... print "%s is %s." % (p.first_name, p.age) - John is 37. - Jane is 42. - ... - -__ http://www.postgresql.org/docs/8.4/static/functions-datetime.html - -Passing parameters into ``raw()`` ---------------------------------- - -If you need to perform parameterized queries, you can use the ``params`` -argument to ``raw()``:: - - >>> lname = 'Doe' - >>> Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname]) - -``params`` is a list of parameters. You'll use ``%s`` placeholders in the -query string (regardless of your database engine); they'll be replaced with -parameters from the ``params`` list. - -.. warning:: - - **Do not use string formatting on raw queries!** - - It's tempting to write the above query as:: - - >>> query = 'SELECT * FROM myapp_person WHERE last_name = %s' % lname - >>> Person.objects.raw(query) - - **Don't.** - - Using the ``params`` list completely protects you from `SQL injection - attacks`__, a common exploit where attackers inject arbitrary SQL into - your database. If you use string interpolation, sooner or later you'll - fall victim to SQL injection. As long as you remember to always use the - ``params`` list you'll be protected. - -__ http://en.wikipedia.org/wiki/SQL_injection - -Executing custom SQL directly -============================= - -Sometimes even :meth:`Manager.raw` isn't quite enough: you might need to -perform queries that don't map cleanly to models, or directly execute -``UPDATE``, ``INSERT``, or ``DELETE`` queries. - -In these cases, you can always access the database directly, routing around -the model layer entirely. - -The object ``django.db.connection`` represents the -default database connection, and ``django.db.transaction`` represents the -default database transaction. To use the database connection, call -``connection.cursor()`` to get a cursor object. Then, call -``cursor.execute(sql, [params])`` to execute the SQL and ``cursor.fetchone()`` -or ``cursor.fetchall()`` to return the resulting rows. After performing a data -changing operation, you should then call -``transaction.commit_unless_managed()`` to ensure your changes are committed -to the database. If your query is purely a data retrieval operation, no commit -is required. For example:: - - def my_custom_sql(): - from django.db import connection, transaction - cursor = connection.cursor() - - # Data modifying operation - commit required - cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz]) - transaction.commit_unless_managed() - - # Data retrieval operation - no commit required - cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz]) - row = cursor.fetchone() - - return row - -If you are using more than one database you can use -``django.db.connections`` to obtain the connection (and cursor) for a -specific database. ``django.db.connections`` is a dictionary-like -object that allows you to retrieve a specific connection using it's -alias:: - - from django.db import connections - cursor = connections['my_db_alias'].cursor() - -.. _transactions-and-raw-sql: - -Transactions and raw SQL ------------------------- -If you are using transaction decorators (such as ``commit_on_success``) to -wrap your views and provide transaction control, you don't have to make a -manual call to ``transaction.commit_unless_managed()`` -- you can manually -commit if you want to, but you aren't required to, since the decorator will -commit for you. However, if you don't manually commit your changes, you will -need to manually mark the transaction as dirty, using -``transaction.set_dirty()``:: - - @commit_on_success - def my_custom_sql_view(request, value): - from django.db import connection, transaction - cursor = connection.cursor() - - # Data modifying operation - cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [value]) - - # Since we modified data, mark the transaction as dirty - transaction.set_dirty() - - # Data retrieval operation. This doesn't dirty the transaction, - # so no call to set_dirty() is required. - cursor.execute("SELECT foo FROM bar WHERE baz = %s", [value]) - row = cursor.fetchone() - - return render_to_response('template.html', {'row': row}) - -The call to ``set_dirty()`` is made automatically when you use the Django ORM -to make data modifying database calls. However, when you use raw SQL, Django -has no way of knowing if your SQL modifies data or not. The manual call to -``set_dirty()`` ensures that Django knows that there are modifications that -must be committed. - -Connections and cursors ------------------------ - -``connection`` and ``cursor`` mostly implement the standard `Python DB-API`_ -(except when it comes to :doc:`transaction handling </topics/db/transactions>`). -If you're not familiar with the Python DB-API, note that the SQL statement in -``cursor.execute()`` uses placeholders, ``"%s"``, rather than adding parameters -directly within the SQL. If you use this technique, the underlying database -library will automatically add quotes and escaping to your parameter(s) as -necessary. (Also note that Django expects the ``"%s"`` placeholder, *not* the -``"?"`` placeholder, which is used by the SQLite Python bindings. This is for -the sake of consistency and sanity.) - -.. _Python DB-API: http://www.python.org/dev/peps/pep-0249/ diff --git a/parts/django/docs/topics/db/transactions.txt b/parts/django/docs/topics/db/transactions.txt deleted file mode 100644 index be9d9a8..0000000 --- a/parts/django/docs/topics/db/transactions.txt +++ /dev/null @@ -1,328 +0,0 @@ -============================== -Managing database transactions -============================== - -.. currentmodule:: django.db - -Django gives you a few ways to control how database transactions are managed, -if you're using a database that supports transactions. - -Django's default transaction behavior -===================================== - -Django's default behavior is to run with an open transaction which it -commits automatically when any built-in, data-altering model function is -called. For example, if you call ``model.save()`` or ``model.delete()``, the -change will be committed immediately. - -This is much like the auto-commit setting for most databases. As soon as you -perform an action that needs to write to the database, Django produces the -``INSERT``/``UPDATE``/``DELETE`` statements and then does the ``COMMIT``. -There's no implicit ``ROLLBACK``. - -Tying transactions to HTTP requests -=================================== - -The recommended way to handle transactions in Web requests is to tie them to -the request and response phases via Django's ``TransactionMiddleware``. - -It works like this: When a request starts, Django starts a transaction. If the -response is produced without problems, Django commits any pending transactions. -If the view function produces an exception, Django rolls back any pending -transactions. - -To activate this feature, just add the ``TransactionMiddleware`` middleware to -your :setting:`MIDDLEWARE_CLASSES` setting:: - - MIDDLEWARE_CLASSES = ( - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.transaction.TransactionMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware', - ) - -The order is quite important. The transaction middleware applies not only to -view functions, but also for all middleware modules that come after it. So if -you use the session middleware after the transaction middleware, session -creation will be part of the transaction. - -The various cache middlewares are an exception: -:class:`~django.middleware.cache.CacheMiddleware`, -:class:`~django.middleware.cache.UpdateCacheMiddleware`, and -:class:`~django.middleware.cache.FetchFromCacheMiddleware` are never affected. -Even when using database caching, Django's cache backend uses its own -database cursor (which is mapped to its own database connection internally). - -Controlling transaction management in views -=========================================== - -For most people, implicit request-based transactions work wonderfully. However, -if you need more fine-grained control over how transactions are managed, you -can use Python decorators to change the way transactions are handled by a -particular view function. All of the decorators take an option ``using`` -parameter which should be the alias for a database connection for which the -behavior applies to. If no alias is specified then the ``"default"`` database -is used. - -.. note:: - - Although the examples below use view functions as examples, these - decorators can be applied to non-view functions as well. - -.. _topics-db-transactions-autocommit: - -``django.db.transaction.autocommit`` ------------------------------------- - -Use the ``autocommit`` decorator to switch a view function to Django's default -commit behavior, regardless of the global transaction setting. - -Example:: - - from django.db import transaction - - @transaction.autocommit - def viewfunc(request): - .... - - @transaction.autocommit(using="my_other_database") - def viewfunc2(request): - .... - -Within ``viewfunc()``, transactions will be committed as soon as you call -``model.save()``, ``model.delete()``, or any other function that writes to the -database. ``viewfunc2()`` will have this same behavior, but for the -``"my_other_database"`` connection. - -``django.db.transaction.commit_on_success`` -------------------------------------------- - -Use the ``commit_on_success`` decorator to use a single transaction for -all the work done in a function:: - - from django.db import transaction - - @transaction.commit_on_success - def viewfunc(request): - .... - - @transaction.commit_on_success(using="my_other_database") - def viewfunc2(request): - .... - -If the function returns successfully, then Django will commit all work done -within the function at that point. If the function raises an exception, though, -Django will roll back the transaction. - -``django.db.transaction.commit_manually`` ------------------------------------------ - -Use the ``commit_manually`` decorator if you need full control over -transactions. It tells Django you'll be managing the transaction on your own. - -If your view changes data and doesn't ``commit()`` or ``rollback()``, Django -will raise a ``TransactionManagementError`` exception. - -Manual transaction management looks like this:: - - from django.db import transaction - - @transaction.commit_manually - def viewfunc(request): - ... - # You can commit/rollback however and whenever you want - transaction.commit() - ... - - # But you've got to remember to do it yourself! - try: - ... - except: - transaction.rollback() - else: - transaction.commit() - - @transaction.commit_manually(using="my_other_database") - def viewfunc2(request): - .... - -.. admonition:: An important note to users of earlier Django releases: - - The database ``connection.commit()`` and ``connection.rollback()`` methods - (called ``db.commit()`` and ``db.rollback()`` in 0.91 and earlier) no - longer exist. They've been replaced by ``transaction.commit()`` and - ``transaction.rollback()``. - -How to globally deactivate transaction management -================================================= - -Control freaks can totally disable all transaction management by setting -``DISABLE_TRANSACTION_MANAGEMENT`` to ``True`` in the Django settings file. - -If you do this, Django won't provide any automatic transaction management -whatsoever. Middleware will no longer implicitly commit transactions, and -you'll need to roll management yourself. This even requires you to commit -changes done by middleware somewhere else. - -Thus, this is best used in situations where you want to run your own -transaction-controlling middleware or do something really strange. In almost -all situations, you'll be better off using the default behavior, or the -transaction middleware, and only modify selected functions as needed. - -.. _topics-db-transactions-savepoints: - -Savepoints -========== - -A savepoint is a marker within a transaction that enables you to roll back -part of a transaction, rather than the full transaction. Savepoints are -available to the PostgreSQL 8 and Oracle backends. Other backends will -provide the savepoint functions, but they are empty operations - they won't -actually do anything. - -Savepoints aren't especially useful if you are using the default -``autocommit`` behaviour of Django. However, if you are using -``commit_on_success`` or ``commit_manually``, each open transaction will build -up a series of database operations, awaiting a commit or rollback. If you -issue a rollback, the entire transaction is rolled back. Savepoints provide -the ability to perform a fine-grained rollback, rather than the full rollback -that would be performed by ``transaction.rollback()``. - -Each of these functions takes a ``using`` argument which should be the name of -a database for which the behavior applies. If no ``using`` argument is -provided then the ``"default"`` database is used. - -Savepoints are controlled by three methods on the transaction object: - -.. method:: transaction.savepoint(using=None) - - Creates a new savepoint. This marks a point in the transaction that - is known to be in a "good" state. - - Returns the savepoint ID (sid). - -.. method:: transaction.savepoint_commit(sid, using=None) - - Updates the savepoint to include any operations that have been performed - since the savepoint was created, or since the last commit. - -.. method:: transaction.savepoint_rollback(sid, using=None) - - Rolls the transaction back to the last point at which the savepoint was - committed. - -The following example demonstrates the use of savepoints:: - - from django.db import transaction - - @transaction.commit_manually - def viewfunc(request): - - a.save() - # open transaction now contains a.save() - sid = transaction.savepoint() - - b.save() - # open transaction now contains a.save() and b.save() - - if want_to_keep_b: - transaction.savepoint_commit(sid) - # open transaction still contains a.save() and b.save() - else: - transaction.savepoint_rollback(sid) - # open transaction now contains only a.save() - - transaction.commit() - -Transactions in MySQL -===================== - -If you're using MySQL, your tables may or may not support transactions; it -depends on your MySQL version and the table types you're using. (By -"table types," we mean something like "InnoDB" or "MyISAM".) MySQL transaction -peculiarities are outside the scope of this article, but the MySQL site has -`information on MySQL transactions`_. - -If your MySQL setup does *not* support transactions, then Django will function -in auto-commit mode: Statements will be executed and committed as soon as -they're called. If your MySQL setup *does* support transactions, Django will -handle transactions as explained in this document. - -.. _information on MySQL transactions: http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html - -Handling exceptions within PostgreSQL transactions -================================================== - -When a call to a PostgreSQL cursor raises an exception (typically -``IntegrityError``), all subsequent SQL in the same transaction will fail with -the error "current transaction is aborted, queries ignored until end of -transaction block". Whilst simple use of ``save()`` is unlikely to raise an -exception in PostgreSQL, there are more advanced usage patterns which -might, such as saving objects with unique fields, saving using the -force_insert/force_update flag, or invoking custom SQL. - -There are several ways to recover from this sort of error. - -Transaction rollback --------------------- - -The first option is to roll back the entire transaction. For example:: - - a.save() # Succeeds, but may be undone by transaction rollback - try: - b.save() # Could throw exception - except IntegrityError: - transaction.rollback() - c.save() # Succeeds, but a.save() may have been undone - -Calling ``transaction.rollback()`` rolls back the entire transaction. Any -uncommitted database operations will be lost. In this example, the changes -made by ``a.save()`` would be lost, even though that operation raised no error -itself. - -Savepoint rollback ------------------- - -If you are using PostgreSQL 8 or later, you can use :ref:`savepoints -<topics-db-transactions-savepoints>` to control the extent of a rollback. -Before performing a database operation that could fail, you can set or update -the savepoint; that way, if the operation fails, you can roll back the single -offending operation, rather than the entire transaction. For example:: - - a.save() # Succeeds, and never undone by savepoint rollback - try: - sid = transaction.savepoint() - b.save() # Could throw exception - transaction.savepoint_commit(sid) - except IntegrityError: - transaction.savepoint_rollback(sid) - c.save() # Succeeds, and a.save() is never undone - -In this example, ``a.save()`` will not be undone in the case where -``b.save()`` raises an exception. - -Database-level autocommit -------------------------- - -.. versionadded:: 1.1 - -With PostgreSQL 8.2 or later, there is an advanced option to run PostgreSQL -with :doc:`database-level autocommit </ref/databases>`. If you use this option, -there is no constantly open transaction, so it is always possible to continue -after catching an exception. For example:: - - a.save() # succeeds - try: - b.save() # Could throw exception - except IntegrityError: - pass - c.save() # succeeds - -.. note:: - - This is not the same as the :ref:`autocommit decorator - <topics-db-transactions-autocommit>`. When using database level autocommit - there is no database transaction at all. The ``autocommit`` decorator - still uses transactions, automatically committing each transaction when - a database modifying operation occurs. diff --git a/parts/django/docs/topics/email.txt b/parts/django/docs/topics/email.txt deleted file mode 100644 index 36bebfb..0000000 --- a/parts/django/docs/topics/email.txt +++ /dev/null @@ -1,618 +0,0 @@ -============== -Sending e-mail -============== - -.. module:: django.core.mail - :synopsis: Helpers to easily send e-mail. - -Although Python makes sending e-mail relatively easy via the `smtplib -library`_, Django provides a couple of light wrappers over it. These wrappers -are provided to make sending e-mail extra quick, to make it easy to test -e-mail sending during development, and to provide support for platforms that -can't use SMTP. - -The code lives in the ``django.core.mail`` module. - -.. _smtplib library: http://docs.python.org/library/smtplib.html - -Quick example -============= - -In two lines:: - - from django.core.mail import send_mail - - send_mail('Subject here', 'Here is the message.', 'from@example.com', - ['to@example.com'], fail_silently=False) - -Mail is sent using the SMTP host and port specified in the -:setting:`EMAIL_HOST` and :setting:`EMAIL_PORT` settings. The -:setting:`EMAIL_HOST_USER` and :setting:`EMAIL_HOST_PASSWORD` settings, if -set, are used to authenticate to the SMTP server, and the -:setting:`EMAIL_USE_TLS` setting controls whether a secure connection is used. - -.. note:: - - The character set of e-mail sent with ``django.core.mail`` will be set to - the value of your :setting:`DEFAULT_CHARSET` setting. - -send_mail() -=========== - -.. function:: send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None) - -The simplest way to send e-mail is using -``django.core.mail.send_mail()``. - -The ``subject``, ``message``, ``from_email`` and ``recipient_list`` parameters -are required. - - * ``subject``: A string. - * ``message``: A string. - * ``from_email``: A string. - * ``recipient_list``: A list of strings, each an e-mail address. Each - member of ``recipient_list`` will see the other recipients in the "To:" - field of the e-mail message. - * ``fail_silently``: A boolean. If it's ``False``, ``send_mail`` will raise - an ``smtplib.SMTPException``. See the `smtplib docs`_ for a list of - possible exceptions, all of which are subclasses of ``SMTPException``. - * ``auth_user``: The optional username to use to authenticate to the SMTP - server. If this isn't provided, Django will use the value of the - :setting:`EMAIL_HOST_USER` setting. - * ``auth_password``: The optional password to use to authenticate to the - SMTP server. If this isn't provided, Django will use the value of the - :setting:`EMAIL_HOST_PASSWORD` setting. - * ``connection``: The optional e-mail backend to use to send the mail. - If unspecified, an instance of the default backend will be used. - See the documentation on :ref:`E-mail backends <topic-email-backends>` - for more details. - -.. _smtplib docs: http://docs.python.org/library/smtplib.html - -send_mass_mail() -================ - -.. function:: send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None) - -``django.core.mail.send_mass_mail()`` is intended to handle mass e-mailing. - -``datatuple`` is a tuple in which each element is in this format:: - - (subject, message, from_email, recipient_list) - -``fail_silently``, ``auth_user`` and ``auth_password`` have the same functions -as in :meth:`~django.core.mail.send_mail()`. - -Each separate element of ``datatuple`` results in a separate e-mail message. -As in :meth:`~django.core.mail.send_mail()`, recipients in the same -``recipient_list`` will all see the other addresses in the e-mail messages' -"To:" field. - -For example, the following code would send two different messages to -two different sets of recipients; however, only one connection to the -mail server would be opened:: - - message1 = ('Subject here', 'Here is the message', 'from@example.com, ['first@example.com', 'other@example.com']) - message2 = ('Another Subject', 'Here is another message', 'from@example.com', ['second@test.com']) - send_mass_mail((message1, message2), fail_silently=False) - -send_mass_mail() vs. send_mail() --------------------------------- - -The main difference between :meth:`~django.core.mail.send_mass_mail()` and -:meth:`~django.core.mail.send_mail()` is that -:meth:`~django.core.mail.send_mail()` opens a connection to the mail server -each time it's executed, while :meth:`~django.core.mail.send_mass_mail()` uses -a single connection for all of its messages. This makes -:meth:`~django.core.mail.send_mass_mail()` slightly more efficient. - -mail_admins() -============= - -.. function:: mail_admins(subject, message, fail_silently=False, connection=None) - -``django.core.mail.mail_admins()`` is a shortcut for sending an e-mail to the -site admins, as defined in the :setting:`ADMINS` setting. - -``mail_admins()`` prefixes the subject with the value of the -:setting:`EMAIL_SUBJECT_PREFIX` setting, which is ``"[Django] "`` by default. - -The "From:" header of the e-mail will be the value of the -:setting:`SERVER_EMAIL` setting. - -This method exists for convenience and readability. - -mail_managers() -=============== - -.. function:: mail_managers(subject, message, fail_silently=False, connection=None) - -``django.core.mail.mail_managers()`` is just like ``mail_admins()``, except it -sends an e-mail to the site managers, as defined in the :setting:`MANAGERS` -setting. - -Examples -======== - -This sends a single e-mail to john@example.com and jane@example.com, with them -both appearing in the "To:":: - - send_mail('Subject', 'Message.', 'from@example.com', - ['john@example.com', 'jane@example.com']) - -This sends a message to john@example.com and jane@example.com, with them both -receiving a separate e-mail:: - - datatuple = ( - ('Subject', 'Message.', 'from@example.com', ['john@example.com']), - ('Subject', 'Message.', 'from@example.com', ['jane@example.com']), - ) - send_mass_mail(datatuple) - -Preventing header injection -=========================== - -`Header injection`_ is a security exploit in which an attacker inserts extra -e-mail headers to control the "To:" and "From:" in e-mail messages that your -scripts generate. - -The Django e-mail functions outlined above all protect against header injection -by forbidding newlines in header values. If any ``subject``, ``from_email`` or -``recipient_list`` contains a newline (in either Unix, Windows or Mac style), -the e-mail function (e.g. :meth:`~django.core.mail.send_mail()`) will raise -``django.core.mail.BadHeaderError`` (a subclass of ``ValueError``) and, hence, -will not send the e-mail. It's your responsibility to validate all data before -passing it to the e-mail functions. - -If a ``message`` contains headers at the start of the string, the headers will -simply be printed as the first bit of the e-mail message. - -Here's an example view that takes a ``subject``, ``message`` and ``from_email`` -from the request's POST data, sends that to admin@example.com and redirects to -"/contact/thanks/" when it's done:: - - from django.core.mail import send_mail, BadHeaderError - - def send_email(request): - subject = request.POST.get('subject', '') - message = request.POST.get('message', '') - from_email = request.POST.get('from_email', '') - if subject and message and from_email: - try: - send_mail(subject, message, from_email, ['admin@example.com']) - except BadHeaderError: - return HttpResponse('Invalid header found.') - return HttpResponseRedirect('/contact/thanks/') - else: - # In reality we'd use a form class - # to get proper validation errors. - return HttpResponse('Make sure all fields are entered and valid.') - -.. _Header injection: http://www.nyphp.org/phundamentals/email_header_injection.php - -.. _emailmessage-and-smtpconnection: - -The EmailMessage class -====================== - -.. versionadded:: 1.0 - -Django's :meth:`~django.core.mail.send_mail()` and -:meth:`~django.core.mail.send_mass_mail()` functions are actually thin -wrappers that make use of the :class:`~django.core.mail.EmailMessage` class. - -Not all features of the :class:`~django.core.mail.EmailMessage` class are -available through the :meth:`~django.core.mail.send_mail()` and related -wrapper functions. If you wish to use advanced features, such as BCC'ed -recipients, file attachments, or multi-part e-mail, you'll need to create -:class:`~django.core.mail.EmailMessage` instances directly. - -.. note:: - This is a design feature. :meth:`~django.core.mail.send_mail()` and - related functions were originally the only interface Django provided. - However, the list of parameters they accepted was slowly growing over - time. It made sense to move to a more object-oriented design for e-mail - messages and retain the original functions only for backwards - compatibility. - -:class:`~django.core.mail.EmailMessage` is responsible for creating the e-mail -message itself. The :ref:`e-mail backend <topic-email-backends>` is then -responsible for sending the e-mail. - -For convenience, :class:`~django.core.mail.EmailMessage` provides a simple -``send()`` method for sending a single e-mail. If you need to send multiple -messages, the e-mail backend API :ref:`provides an alternative -<topics-sending-multiple-emails>`. - -EmailMessage Objects --------------------- - -.. class:: EmailMessage - -The :class:`~django.core.mail.EmailMessage` class is initialized with the -following parameters (in the given order, if positional arguments are used). -All parameters are optional and can be set at any time prior to calling the -``send()`` method. - - * ``subject``: The subject line of the e-mail. - - * ``body``: The body text. This should be a plain text message. - - * ``from_email``: The sender's address. Both ``fred@example.com`` and - ``Fred <fred@example.com>`` forms are legal. If omitted, the - :setting:`DEFAULT_FROM_EMAIL` setting is used. - - * ``to``: A list or tuple of recipient addresses. - - * ``bcc``: A list or tuple of addresses used in the "Bcc" header when - sending the e-mail. - - * ``connection``: An e-mail backend instance. Use this parameter if - you want to use the same connection for multiple messages. If omitted, a - new connection is created when ``send()`` is called. - - * ``attachments``: A list of attachments to put on the message. These can - be either ``email.MIMEBase.MIMEBase`` instances, or ``(filename, - content, mimetype)`` triples. - - * ``headers``: A dictionary of extra headers to put on the message. The - keys are the header name, values are the header values. It's up to the - caller to ensure header names and values are in the correct format for - an e-mail message. - -For example:: - - email = EmailMessage('Hello', 'Body goes here', 'from@example.com', - ['to1@example.com', 'to2@example.com'], ['bcc@example.com'], - headers = {'Reply-To': 'another@example.com'}) - -The class has the following methods: - - * ``send(fail_silently=False)`` sends the message. If a connection was - specified when the e-mail was constructed, that connection will be used. - Otherwise, an instance of the default backend will be instantiated and - used. If the keyword argument ``fail_silently`` is ``True``, exceptions - raised while sending the message will be quashed. - - * ``message()`` constructs a ``django.core.mail.SafeMIMEText`` object (a - subclass of Python's ``email.MIMEText.MIMEText`` class) or a - ``django.core.mail.SafeMIMEMultipart`` object holding the message to be - sent. If you ever need to extend the - :class:`~django.core.mail.EmailMessage` class, you'll probably want to - override this method to put the content you want into the MIME object. - - * ``recipients()`` returns a list of all the recipients of the message, - whether they're recorded in the ``to`` or ``bcc`` attributes. This is - another method you might need to override when subclassing, because the - SMTP server needs to be told the full list of recipients when the message - is sent. If you add another way to specify recipients in your class, they - need to be returned from this method as well. - - * ``attach()`` creates a new file attachment and adds it to the message. - There are two ways to call ``attach()``: - - * You can pass it a single argument that is an - ``email.MIMEBase.MIMEBase`` instance. This will be inserted directly - into the resulting message. - - * Alternatively, you can pass ``attach()`` three arguments: - ``filename``, ``content`` and ``mimetype``. ``filename`` is the name - of the file attachment as it will appear in the e-mail, ``content`` is - the data that will be contained inside the attachment and - ``mimetype`` is the optional MIME type for the attachment. If you - omit ``mimetype``, the MIME content type will be guessed from the - filename of the attachment. - - For example:: - - message.attach('design.png', img_data, 'image/png') - - * ``attach_file()`` creates a new attachment using a file from your - filesystem. Call it with the path of the file to attach and, optionally, - the MIME type to use for the attachment. If the MIME type is omitted, it - will be guessed from the filename. The simplest use would be:: - - message.attach_file('/images/weather_map.png') - -.. _DEFAULT_FROM_EMAIL: ../settings/#default-from-email - -Sending alternative content types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -It can be useful to include multiple versions of the content in an e-mail; the -classic example is to send both text and HTML versions of a message. With -Django's e-mail library, you can do this using the ``EmailMultiAlternatives`` -class. This subclass of :class:`~django.core.mail.EmailMessage` has an -``attach_alternative()`` method for including extra versions of the message -body in the e-mail. All the other methods (including the class initialization) -are inherited directly from :class:`~django.core.mail.EmailMessage`. - -To send a text and HTML combination, you could write:: - - from django.core.mail import EmailMultiAlternatives - - subject, from_email, to = 'hello', 'from@example.com', 'to@example.com' - text_content = 'This is an important message.' - html_content = '<p>This is an <strong>important</strong> message.</p>' - msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) - msg.attach_alternative(html_content, "text/html") - msg.send() - -By default, the MIME type of the ``body`` parameter in an -:class:`~django.core.mail.EmailMessage` is ``"text/plain"``. It is good -practice to leave this alone, because it guarantees that any recipient will be -able to read the e-mail, regardless of their mail client. However, if you are -confident that your recipients can handle an alternative content type, you can -use the ``content_subtype`` attribute on the -:class:`~django.core.mail.EmailMessage` class to change the main content type. -The major type will always be ``"text"``, but you can change the -subtype. For example:: - - msg = EmailMessage(subject, html_content, from_email, [to]) - msg.content_subtype = "html" # Main content is now text/html - msg.send() - -.. _topic-email-backends: - -E-Mail Backends -=============== - -.. versionadded:: 1.2 - -The actual sending of an e-mail is handled by the e-mail backend. - -The e-mail backend class has the following methods: - - * ``open()`` instantiates an long-lived e-mail-sending connection. - - * ``close()`` closes the current e-mail-sending connection. - - * ``send_messages(email_messages)`` sends a list of - :class:`~django.core.mail.EmailMessage` objects. If the connection is - not open, this call will implicitly open the connection, and close the - connection afterwards. If the connection is already open, it will be - left open after mail has been sent. - -Obtaining an instance of an e-mail backend ------------------------------------------- - -The :meth:`get_connection` function in ``django.core.mail`` returns an -instance of the e-mail backend that you can use. - -.. currentmodule:: django.core.mail - -.. function:: get_connection(backend=None, fail_silently=False, *args, **kwargs) - -By default, a call to ``get_connection()`` will return an instance of the -e-mail backend specified in :setting:`EMAIL_BACKEND`. If you specify the -``backend`` argument, an instance of that backend will be instantiated. - -The ``fail_silently`` argument controls how the backend should handle errors. -If ``fail_silently`` is True, exceptions during the e-mail sending process -will be silently ignored. - -All other arguments are passed directly to the constructor of the -e-mail backend. - -Django ships with several e-mail sending backends. With the exception of the -SMTP backend (which is the default), these backends are only useful during -testing and development. If you have special e-mail sending requirements, you -can :ref:`write your own e-mail backend <topic-custom-email-backend>`. - -.. _topic-email-smtp-backend: - -SMTP backend -~~~~~~~~~~~~ - -This is the default backend. E-mail will be sent through a SMTP server. -The server address and authentication credentials are set in the -:setting:`EMAIL_HOST`, :setting:`EMAIL_PORT`, :setting:`EMAIL_HOST_USER`, -:setting:`EMAIL_HOST_PASSWORD` and :setting:`EMAIL_USE_TLS` settings in your -settings file. - -The SMTP backend is the default configuration inherited by Django. If you -want to specify it explicitly, put the following in your settings:: - - EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' - -.. admonition:: SMTPConnection objects - - Prior to version 1.2, Django provided a - :class:`~django.core.mail.SMTPConnection` class. This class provided a way - to directly control the use of SMTP to send e-mail. This class has been - deprecated in favor of the generic e-mail backend API. - - For backwards compatibility :class:`~django.core.mail.SMTPConnection` is - still available in ``django.core.mail`` as an alias for the SMTP backend. - New code should use :meth:`~django.core.mail.get_connection` instead. - -.. _topic-email-console-backend: - -Console backend -~~~~~~~~~~~~~~~ - -Instead of sending out real e-mails the console backend just writes the -e-mails that would be send to the standard output. By default, the console -backend writes to ``stdout``. You can use a different stream-like object by -providing the ``stream`` keyword argument when constructing the connection. - -To specify this backend, put the following in your settings:: - - EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' - -This backend is not intended for use in production -- it is provided as a -convenience that can be used during development. - -.. _topic-email-file-backend: - -File backend -~~~~~~~~~~~~ - -The file backend writes e-mails to a file. A new file is created for each new -session that is opened on this backend. The directory to which the files are -written is either taken from the :setting:`EMAIL_FILE_PATH` setting or from -the ``file_path`` keyword when creating a connection with -:meth:`~django.core.mail.get_connection`. - -To specify this backend, put the following in your settings:: - - EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend' - EMAIL_FILE_PATH = '/tmp/app-messages' # change this to a proper location - -This backend is not intended for use in production -- it is provided as a -convenience that can be used during development. - -.. _topic-email-memory-backend: - -In-memory backend -~~~~~~~~~~~~~~~~~ - -The ``'locmem'`` backend stores messages in a special attribute of the -``django.core.mail`` module. The ``outbox`` attribute is created when the -first message is sent. It's a list with an -:class:`~django.core.mail.EmailMessage` instance for each message that would -be send. - -To specify this backend, put the following in your settings:: - - EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' - -This backend is not intended for use in production -- it is provided as a -convenience that can be used during development and testing. - -.. _topic-email-dummy-backend: - -Dummy backend -~~~~~~~~~~~~~ - -As the name suggests the dummy backend does nothing with your messages. To -specify this backend, put the following in your settings:: - - EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' - -This backend is not intended for use in production -- it is provided as a -convenience that can be used during development. - -.. _topic-custom-email-backend: - -Defining a custom e-mail backend --------------------------------- - -If you need to change how e-mails are sent you can write your own e-mail -backend. The ``EMAIL_BACKEND`` setting in your settings file is then the -Python import path for your backend class. - -Custom e-mail backends should subclass ``BaseEmailBackend`` that is located in -the ``django.core.mail.backends.base`` module. A custom e-mail backend must -implement the ``send_messages(email_messages)`` method. This method receives a -list of :class:`~django.core.mail.EmailMessage` instances and returns the -number of successfully delivered messages. If your backend has any concept of -a persistent session or connection, you should also implement the ``open()`` -and ``close()`` methods. Refer to ``smtp.EmailBackend`` for a reference -implementation. - -.. _topics-sending-multiple-emails: - -Sending multiple e-mails ------------------------- - -Establishing and closing an SMTP connection (or any other network connection, -for that matter) is an expensive process. If you have a lot of e-mails to send, -it makes sense to reuse an SMTP connection, rather than creating and -destroying a connection every time you want to send an e-mail. - -There are two ways you tell an e-mail backend to reuse a connection. - -Firstly, you can use the ``send_messages()`` method. ``send_messages()`` takes -a list of :class:`~django.core.mail.EmailMessage` instances (or subclasses), -and sends them all using a single connection. - -For example, if you have a function called ``get_notification_email()`` that -returns a list of :class:`~django.core.mail.EmailMessage` objects representing -some periodic e-mail you wish to send out, you could send these e-mails using -a single call to send_messages:: - - from django.core import mail - connection = mail.get_connection() # Use default e-mail connection - messages = get_notification_email() - connection.send_messages(messages) - -In this example, the call to ``send_messages()`` opens a connection on the -backend, sends the list of messages, and then closes the connection again. - -The second approach is to use the ``open()`` and ``close()`` methods on the -e-mail backend to manually control the connection. ``send_messages()`` will not -manually open or close the connection if it is already open, so if you -manually open the connection, you can control when it is closed. For example:: - - from django.core import mail - connection = mail.get_connection() - - # Manually open the connection - connection.open() - - # Construct an e-mail message that uses the connection - email1 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com', - ['to1@example.com'], connection=connection) - email1.send() # Send the e-mail - - # Construct two more messages - email2 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com', - ['to2@example.com']) - email3 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com', - ['to3@example.com']) - - # Send the two e-mails in a single call - - connection.send_messages([email2, email3]) - # The connection was already open so send_messages() doesn't close it. - # We need to manually close the connection. - connection.close() - - -Testing e-mail sending -====================== - -There are times when you do not want Django to send e-mails at -all. For example, while developing a Web site, you probably don't want -to send out thousands of e-mails -- but you may want to validate that -e-mails will be sent to the right people under the right conditions, -and that those e-mails will contain the correct content. - -The easiest way to test your project's use of e-mail is to use the ``console`` -e-mail backend. This backend redirects all e-mail to stdout, allowing you to -inspect the content of mail. - -The ``file`` e-mail backend can also be useful during development -- this backend -dumps the contents of every SMTP connection to a file that can be inspected -at your leisure. - -Another approach is to use a "dumb" SMTP server that receives the e-mails -locally and displays them to the terminal, but does not actually send -anything. Python has a built-in way to accomplish this with a single command:: - - python -m smtpd -n -c DebuggingServer localhost:1025 - -This command will start a simple SMTP server listening on port 1025 of -localhost. This server simply prints to standard output all e-mail headers and -the e-mail body. You then only need to set the :setting:`EMAIL_HOST` and -:setting:`EMAIL_PORT` accordingly, and you are set. - -For a more detailed discussion of testing and processing of e-mails locally, -see the Python documentation on the `SMTP Server`_. - -.. _SMTP Server: http://docs.python.org/library/smtpd.html - -SMTPConnection -============== - -.. class:: SMTPConnection - -.. deprecated:: 1.2 - -The ``SMTPConnection`` class has been deprecated in favor of the generic e-mail -backend API. - -For backwards compatibility ``SMTPConnection`` is still available in -``django.core.mail`` as an alias for the :ref:`SMTP backend -<topic-email-smtp-backend>`. New code should use -:meth:`~django.core.mail.get_connection` instead. diff --git a/parts/django/docs/topics/files.txt b/parts/django/docs/topics/files.txt deleted file mode 100644 index d1926c6..0000000 --- a/parts/django/docs/topics/files.txt +++ /dev/null @@ -1,147 +0,0 @@ -============== -Managing files -============== - -.. versionadded:: 1.0 - -This document describes Django's file access APIs. - -By default, Django stores files locally, using the :setting:`MEDIA_ROOT` and -:setting:`MEDIA_URL` settings. The examples below assume that you're using these -defaults. - -However, Django provides ways to write custom `file storage systems`_ that -allow you to completely customize where and how Django stores files. The -second half of this document describes how these storage systems work. - -.. _file storage systems: `File storage`_ - -Using files in models -===================== - -When you use a :class:`~django.db.models.FileField` or -:class:`~django.db.models.ImageField`, Django provides a set of APIs you can use -to deal with that file. - -Consider the following model, using an :class:`~django.db.models.ImageField` to -store a photo:: - - class Car(models.Model): - name = models.CharField(max_length=255) - price = models.DecimalField(max_digits=5, decimal_places=2) - photo = models.ImageField(upload_to='cars') - -Any ``Car`` instance will have a ``photo`` attribute that you can use to get at -the details of the attached photo:: - - >>> car = Car.objects.get(name="57 Chevy") - >>> car.photo - <ImageFieldFile: chevy.jpg> - >>> car.photo.name - u'cars/chevy.jpg' - >>> car.photo.path - u'/media/cars/chevy.jpg' - >>> car.photo.url - u'http://media.example.com/cars/chevy.jpg' - -This object -- ``car.photo`` in the example -- is a ``File`` object, which means -it has all the methods and attributes described below. - -The ``File`` object -=================== - -Internally, Django uses a :class:`django.core.files.File` instance any time it -needs to represent a file. This object is a thin wrapper around Python's -`built-in file object`_ with some Django-specific additions. - -.. _built-in file object: http://docs.python.org/library/stdtypes.html#bltin-file-objects - -Most of the time you'll simply use a ``File`` that Django's given you (i.e. a -file attached to a model as above, or perhaps an uploaded file). - -If you need to construct a ``File`` yourself, the easiest way is to create one -using a Python built-in ``file`` object:: - - >>> from django.core.files import File - - # Create a Python file object using open() - >>> f = open('/tmp/hello.world', 'w') - >>> myfile = File(f) - -Now you can use any of the documented attributes and methods -of the :class:`~django.core.files.File` class. - -File storage -============ - -Behind the scenes, Django delegates decisions about how and where to store files -to a file storage system. This is the object that actually understands things -like file systems, opening and reading files, etc. - -Django's default file storage is given by the :setting:`DEFAULT_FILE_STORAGE` -setting; if you don't explicitly provide a storage system, this is the one that -will be used. - -See below for details of the built-in default file storage system, and see -:doc:`/howto/custom-file-storage` for information on writing your own file -storage system. - -Storage objects ---------------- - -Though most of the time you'll want to use a ``File`` object (which delegates to -the proper storage for that file), you can use file storage systems directly. -You can create an instance of some custom file storage class, or -- often more -useful -- you can use the global default storage system:: - - >>> from django.core.files.storage import default_storage - >>> from django.core.files.base import ContentFile - - >>> path = default_storage.save('/path/to/file', ContentFile('new content')) - >>> path - u'/path/to/file' - - >>> default_storage.size(path) - 11 - >>> default_storage.open(path).read() - 'new content' - - >>> default_storage.delete(path) - >>> default_storage.exists(path) - False - -See :doc:`/ref/files/storage` for the file storage API. - -The built-in filesystem storage class -------------------------------------- - -Django ships with a built-in ``FileSystemStorage`` class (defined in -``django.core.files.storage``) which implements basic local filesystem file -storage. Its initializer takes two arguments: - -====================== =================================================== -Argument Description -====================== =================================================== -``location`` Optional. Absolute path to the directory that will - hold the files. If omitted, it will be set to the - value of your :setting:`MEDIA_ROOT` setting. -``base_url`` Optional. URL that serves the files stored at this - location. If omitted, it will default to the value - of your :setting:`MEDIA_URL` setting. -====================== =================================================== - -For example, the following code will store uploaded files under -``/media/photos`` regardless of what your :setting:`MEDIA_ROOT` setting is:: - - from django.db import models - from django.core.files.storage import FileSystemStorage - - fs = FileSystemStorage(location='/media/photos') - - class Car(models.Model): - ... - photo = models.ImageField(storage=fs) - -:doc:`Custom storage systems </howto/custom-file-storage>` work the same way: -you can pass them in as the ``storage`` argument to a -:class:`~django.db.models.FileField`. diff --git a/parts/django/docs/topics/forms/formsets.txt b/parts/django/docs/topics/forms/formsets.txt deleted file mode 100644 index 72296bc..0000000 --- a/parts/django/docs/topics/forms/formsets.txt +++ /dev/null @@ -1,440 +0,0 @@ -.. _formsets: - -Formsets -======== - -A formset is a layer of abstraction to working with multiple forms on the same -page. It can be best compared to a data grid. Let's say you have the following -form:: - - >>> from django import forms - >>> class ArticleForm(forms.Form): - ... title = forms.CharField() - ... pub_date = forms.DateField() - -You might want to allow the user to create several articles at once. To create -a formset out of an ``ArticleForm`` you would do:: - - >>> from django.forms.formsets import formset_factory - >>> ArticleFormSet = formset_factory(ArticleForm) - -You now have created a formset named ``ArticleFormSet``. The formset gives you -the ability to iterate over the forms in the formset and display them as you -would with a regular form:: - - >>> formset = ArticleFormSet() - >>> for form in formset.forms: - ... print form.as_table() - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr> - -As you can see it only displayed one empty form. The number of empty forms -that is displayed is controlled by the ``extra`` parameter. By default, -``formset_factory`` defines one extra form; the following example will -display two blank forms:: - - >>> ArticleFormSet = formset_factory(ArticleForm, extra=2) - -Using initial data with a formset ---------------------------------- - -Initial data is what drives the main usability of a formset. As shown above -you can define the number of extra forms. What this means is that you are -telling the formset how many additional forms to show in addition to the -number of forms it generates from the initial data. Lets take a look at an -example:: - - >>> ArticleFormSet = formset_factory(ArticleForm, extra=2) - >>> formset = ArticleFormSet(initial=[ - ... {'title': u'Django is now open source', - ... 'pub_date': datetime.date.today()}, - ... ]) - - >>> for form in formset.forms: - ... print form.as_table() - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-12" id="id_form-0-pub_date" /></td></tr> - <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" id="id_form-1-title" /></td></tr> - <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" id="id_form-1-pub_date" /></td></tr> - <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr> - <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr> - -There are now a total of three forms showing above. One for the initial data -that was passed in and two extra forms. Also note that we are passing in a -list of dictionaries as the initial data. - -.. seealso:: - - :ref:`Creating formsets from models with model formsets <model-formsets>`. - -.. _formsets-max-num: - -Limiting the maximum number of forms ------------------------------------- - -The ``max_num`` parameter to ``formset_factory`` gives you the ability to -limit the maximum number of empty forms the formset will display:: - - >>> ArticleFormSet = formset_factory(ArticleForm, extra=2, max_num=1) - >>> formset = ArticleFormset() - >>> for form in formset.forms: - ... print form.as_table() - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr> - -.. versionchanged:: 1.2 - -If the value of ``max_num`` is greater than the number of existing -objects, up to ``extra`` additional blank forms will be added to the formset, -so long as the total number of forms does not exceed ``max_num``. - -A ``max_num`` value of ``None`` (the default) puts no limit on the number of -forms displayed. Please note that the default value of ``max_num`` was changed -from ``0`` to ``None`` in version 1.2 to allow ``0`` as a valid value. - -Formset validation ------------------- - -Validation with a formset is almost identical to a regular ``Form``. There is -an ``is_valid`` method on the formset to provide a convenient way to validate -all forms in the formset:: - - >>> ArticleFormSet = formset_factory(ArticleForm) - >>> formset = ArticleFormSet({}) - >>> formset.is_valid() - True - -We passed in no data to the formset which is resulting in a valid form. The -formset is smart enough to ignore extra forms that were not changed. If we -provide an invalid article:: - - >>> data = { - ... 'form-TOTAL_FORMS': u'2', - ... 'form-INITIAL_FORMS': u'0', - ... 'form-MAX_NUM_FORMS': u'', - ... 'form-0-title': u'Test', - ... 'form-0-pub_date': u'16 June 1904', - ... 'form-1-title': u'Test', - ... 'form-1-pub_date': u'', # <-- this date is missing but required - ... } - >>> formset = ArticleFormSet(data) - >>> formset.is_valid() - False - >>> formset.errors - [{}, {'pub_date': [u'This field is required.']}] - -As we can see, ``formset.errors`` is a list whose entries correspond to the -forms in the formset. Validation was performed for each of the two forms, and -the expected error message appears for the second item. - -.. _understanding-the-managementform: - -Understanding the ManagementForm -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You may have noticed the additional data (``form-TOTAL_FORMS``, -``form-INITIAL_FORMS`` and ``form-MAX_NUM_FORMS``) that was required -in the formset's data above. This data is required for the -``ManagementForm``. This form is used by the formset to manage the -collection of forms contained in the formset. If you don't provide -this management data, an exception will be raised:: - - >>> data = { - ... 'form-0-title': u'Test', - ... 'form-0-pub_date': u'', - ... } - >>> formset = ArticleFormSet(data) - Traceback (most recent call last): - ... - django.forms.util.ValidationError: [u'ManagementForm data is missing or has been tampered with'] - -It is used to keep track of how many form instances are being displayed. If -you are adding new forms via JavaScript, you should increment the count fields -in this form as well. - -The management form is available as an attribute of the formset -itself. When rendering a formset in a template, you can include all -the management data by rendering ``{{ my_formset.management_form }}`` -(substituting the name of your formset as appropriate). - -.. versionadded:: 1.1 - -``total_form_count`` and ``initial_form_count`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``BaseFormSet`` has a couple of methods that are closely related to the -``ManagementForm``, ``total_form_count`` and ``initial_form_count``. - -``total_form_count`` returns the total number of forms in this formset. -``initial_form_count`` returns the number of forms in the formset that were -pre-filled, and is also used to determine how many forms are required. You -will probably never need to override either of these methods, so please be -sure you understand what they do before doing so. - -.. versionadded:: 1.2 - -``empty_form`` -~~~~~~~~~~~~~~ - -``BaseFormSet`` provides an additional attribute ``empty_form`` which returns -a form instance with a prefix of ``__prefix__`` for easier use in dynamic -forms with JavaScript. - -Custom formset validation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -A formset has a ``clean`` method similar to the one on a ``Form`` class. This -is where you define your own validation that works at the formset level:: - - >>> from django.forms.formsets import BaseFormSet - - >>> class BaseArticleFormSet(BaseFormSet): - ... def clean(self): - ... """Checks that no two articles have the same title.""" - ... if any(self.errors): - ... # Don't bother validating the formset unless each form is valid on its own - ... return - ... titles = [] - ... for i in range(0, self.total_form_count()): - ... form = self.forms[i] - ... title = form.cleaned_data['title'] - ... if title in titles: - ... raise forms.ValidationError, "Articles in a set must have distinct titles." - ... titles.append(title) - - >>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet) - >>> data = { - ... 'form-TOTAL_FORMS': u'2', - ... 'form-INITIAL_FORMS': u'0', - ... 'form-MAX_NUM_FORMS': u'', - ... 'form-0-title': u'Test', - ... 'form-0-pub_date': u'16 June 1904', - ... 'form-1-title': u'Test', - ... 'form-1-pub_date': u'23 June 1912', - ... } - >>> formset = ArticleFormSet(data) - >>> formset.is_valid() - False - >>> formset.errors - [{}, {}] - >>> formset.non_form_errors() - [u'Articles in a set must have distinct titles.'] - -The formset ``clean`` method is called after all the ``Form.clean`` methods -have been called. The errors will be found using the ``non_form_errors()`` -method on the formset. - -Dealing with ordering and deletion of forms -------------------------------------------- - -Common use cases with a formset is dealing with ordering and deletion of the -form instances. This has been dealt with for you. The ``formset_factory`` -provides two optional parameters ``can_order`` and ``can_delete`` that will do -the extra work of adding the extra fields and providing simpler ways of -getting to that data. - -``can_order`` -~~~~~~~~~~~~~ - -Default: ``False`` - -Lets create a formset with the ability to order:: - - >>> ArticleFormSet = formset_factory(ArticleForm, can_order=True) - >>> formset = ArticleFormSet(initial=[ - ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, - ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, - ... ]) - >>> for form in formset.forms: - ... print form.as_table() - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date" /></td></tr> - <tr><th><label for="id_form-0-ORDER">Order:</label></th><td><input type="text" name="form-0-ORDER" value="1" id="id_form-0-ORDER" /></td></tr> - <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title" /></td></tr> - <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date" /></td></tr> - <tr><th><label for="id_form-1-ORDER">Order:</label></th><td><input type="text" name="form-1-ORDER" value="2" id="id_form-1-ORDER" /></td></tr> - <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr> - <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr> - <tr><th><label for="id_form-2-ORDER">Order:</label></th><td><input type="text" name="form-2-ORDER" id="id_form-2-ORDER" /></td></tr> - -This adds an additional field to each form. This new field is named ``ORDER`` -and is an ``forms.IntegerField``. For the forms that came from the initial -data it automatically assigned them a numeric value. Lets look at what will -happen when the user changes these values:: - - >>> data = { - ... 'form-TOTAL_FORMS': u'3', - ... 'form-INITIAL_FORMS': u'2', - ... 'form-MAX_NUM_FORMS': u'', - ... 'form-0-title': u'Article #1', - ... 'form-0-pub_date': u'2008-05-10', - ... 'form-0-ORDER': u'2', - ... 'form-1-title': u'Article #2', - ... 'form-1-pub_date': u'2008-05-11', - ... 'form-1-ORDER': u'1', - ... 'form-2-title': u'Article #3', - ... 'form-2-pub_date': u'2008-05-01', - ... 'form-2-ORDER': u'0', - ... } - - >>> formset = ArticleFormSet(data, initial=[ - ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, - ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, - ... ]) - >>> formset.is_valid() - True - >>> for form in formset.ordered_forms: - ... print form.cleaned_data - {'pub_date': datetime.date(2008, 5, 1), 'ORDER': 0, 'title': u'Article #3'} - {'pub_date': datetime.date(2008, 5, 11), 'ORDER': 1, 'title': u'Article #2'} - {'pub_date': datetime.date(2008, 5, 10), 'ORDER': 2, 'title': u'Article #1'} - -``can_delete`` -~~~~~~~~~~~~~~ - -Default: ``False`` - -Lets create a formset with the ability to delete:: - - >>> ArticleFormSet = formset_factory(ArticleForm, can_delete=True) - >>> formset = ArticleFormSet(initial=[ - ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, - ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, - ... ]) - >>> for form in formset.forms: - .... print form.as_table() - <input type="hidden" name="form-TOTAL_FORMS" value="3" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="2" id="id_form-INITIAL_FORMS" /><input type="hidden" name="form-MAX_NUM_FORMS" id="id_form-MAX_NUM_FORMS" /> - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date" /></td></tr> - <tr><th><label for="id_form-0-DELETE">Delete:</label></th><td><input type="checkbox" name="form-0-DELETE" id="id_form-0-DELETE" /></td></tr> - <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title" /></td></tr> - <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date" /></td></tr> - <tr><th><label for="id_form-1-DELETE">Delete:</label></th><td><input type="checkbox" name="form-1-DELETE" id="id_form-1-DELETE" /></td></tr> - <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr> - <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr> - <tr><th><label for="id_form-2-DELETE">Delete:</label></th><td><input type="checkbox" name="form-2-DELETE" id="id_form-2-DELETE" /></td></tr> - -Similar to ``can_order`` this adds a new field to each form named ``DELETE`` -and is a ``forms.BooleanField``. When data comes through marking any of the -delete fields you can access them with ``deleted_forms``:: - - >>> data = { - ... 'form-TOTAL_FORMS': u'3', - ... 'form-INITIAL_FORMS': u'2', - ... 'form-MAX_NUM_FORMS': u'', - ... 'form-0-title': u'Article #1', - ... 'form-0-pub_date': u'2008-05-10', - ... 'form-0-DELETE': u'on', - ... 'form-1-title': u'Article #2', - ... 'form-1-pub_date': u'2008-05-11', - ... 'form-1-DELETE': u'', - ... 'form-2-title': u'', - ... 'form-2-pub_date': u'', - ... 'form-2-DELETE': u'', - ... } - - >>> formset = ArticleFormSet(data, initial=[ - ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, - ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, - ... ]) - >>> [form.cleaned_data for form in formset.deleted_forms] - [{'DELETE': True, 'pub_date': datetime.date(2008, 5, 10), 'title': u'Article #1'}] - -Adding additional fields to a formset -------------------------------------- - -If you need to add additional fields to the formset this can be easily -accomplished. The formset base class provides an ``add_fields`` method. You -can simply override this method to add your own fields or even redefine the -default fields/attributes of the order and deletion fields:: - - >>> class BaseArticleFormSet(BaseFormSet): - ... def add_fields(self, form, index): - ... super(BaseArticleFormSet, self).add_fields(form, index) - ... form.fields["my_field"] = forms.CharField() - - >>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet) - >>> formset = ArticleFormSet() - >>> for form in formset.forms: - ... print form.as_table() - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr> - <tr><th><label for="id_form-0-my_field">My field:</label></th><td><input type="text" name="form-0-my_field" id="id_form-0-my_field" /></td></tr> - -Using a formset in views and templates --------------------------------------- - -Using a formset inside a view is as easy as using a regular ``Form`` class. -The only thing you will want to be aware of is making sure to use the -management form inside the template. Let's look at a sample view: - -.. code-block:: python - - def manage_articles(request): - ArticleFormSet = formset_factory(ArticleForm) - if request.method == 'POST': - formset = ArticleFormSet(request.POST, request.FILES) - if formset.is_valid(): - # do something with the formset.cleaned_data - pass - else: - formset = ArticleFormSet() - return render_to_response('manage_articles.html', {'formset': formset}) - -The ``manage_articles.html`` template might look like this: - -.. code-block:: html+django - - <form method="post" action=""> - {{ formset.management_form }} - <table> - {% for form in formset.forms %} - {{ form }} - {% endfor %} - </table> - </form> - -However the above can be slightly shortcutted and let the formset itself deal -with the management form: - -.. code-block:: html+django - - <form method="post" action=""> - <table> - {{ formset }} - </table> - </form> - -The above ends up calling the ``as_table`` method on the formset class. - -Using more than one formset in a view -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You are able to use more than one formset in a view if you like. Formsets -borrow much of its behavior from forms. With that said you are able to use -``prefix`` to prefix formset form field names with a given value to allow -more than one formset to be sent to a view without name clashing. Lets take -a look at how this might be accomplished: - -.. code-block:: python - - def manage_articles(request): - ArticleFormSet = formset_factory(ArticleForm) - BookFormSet = formset_factory(BookForm) - if request.method == 'POST': - article_formset = ArticleFormSet(request.POST, request.FILES, prefix='articles') - book_formset = BookFormSet(request.POST, request.FILES, prefix='books') - if article_formset.is_valid() and book_formset.is_valid(): - # do something with the cleaned_data on the formsets. - pass - else: - article_formset = ArticleFormSet(prefix='articles') - book_formset = BookFormSet(prefix='books') - return render_to_response('manage_articles.html', { - 'article_formset': article_formset, - 'book_formset': book_formset, - }) - -You would then render the formsets as normal. It is important to point out -that you need to pass ``prefix`` on both the POST and non-POST cases so that -it is rendered and processed correctly. diff --git a/parts/django/docs/topics/forms/index.txt b/parts/django/docs/topics/forms/index.txt deleted file mode 100644 index 30b09c0..0000000 --- a/parts/django/docs/topics/forms/index.txt +++ /dev/null @@ -1,402 +0,0 @@ -================== -Working with forms -================== - -.. admonition:: About this document - - This document provides an introduction to Django's form handling features. - For a more detailed look at specific areas of the forms API, see - :doc:`/ref/forms/api`, :doc:`/ref/forms/fields`, and - :doc:`/ref/forms/validation`. - -.. highlightlang:: html+django - -``django.forms`` is Django's form-handling library. - -While it is possible to process form submissions just using Django's -:class:`~django.http.HttpRequest` class, using the form library takes care of a -number of common form-related tasks. Using it, you can: - - 1. Display an HTML form with automatically generated form widgets. - 2. Check submitted data against a set of validation rules. - 3. Redisplay a form in the case of validation errors. - 4. Convert submitted form data to the relevant Python data types. - -Overview -======== - -The library deals with these concepts: - -.. glossary:: - - Widget - A class that corresponds to an HTML form widget, e.g. - ``<input type="text">`` or ``<textarea>``. This handles rendering of the - widget as HTML. - - Field - A class that is responsible for doing validation, e.g. - an ``EmailField`` that makes sure its data is a valid e-mail address. - - Form - A collection of fields that knows how to validate itself and - display itself as HTML. - - Form Media - The CSS and JavaScript resources that are required to render a form. - -The library is decoupled from the other Django components, such as the database -layer, views and templates. It relies only on Django settings, a couple of -``django.utils`` helper functions and Django's internationalization hooks (but -you're not required to be using internationalization features to use this -library). - -Form objects -============ - -A Form object encapsulates a sequence of form fields and a collection of -validation rules that must be fulfilled in order for the form to be accepted. -Form classes are created as subclasses of ``django.forms.Form`` and -make use of a declarative style that you'll be familiar with if you've used -Django's database models. - -For example, consider a form used to implement "contact me" functionality on a -personal Web site: - -.. code-block:: python - - from django import forms - - class ContactForm(forms.Form): - subject = forms.CharField(max_length=100) - message = forms.CharField() - sender = forms.EmailField() - cc_myself = forms.BooleanField(required=False) - -A form is composed of ``Field`` objects. In this case, our form has four -fields: ``subject``, ``message``, ``sender`` and ``cc_myself``. ``CharField``, -``EmailField`` and ``BooleanField`` are just three of the available field types; -a full list can be found in :doc:`/ref/forms/fields`. - -If your form is going to be used to directly add or edit a Django model, you can -use a :doc:`ModelForm </topics/forms/modelforms>` to avoid duplicating your model -description. - -Using a form in a view ----------------------- - -The standard pattern for processing a form in a view looks like this: - -.. code-block:: python - - def contact(request): - if request.method == 'POST': # If the form has been submitted... - form = ContactForm(request.POST) # A form bound to the POST data - if form.is_valid(): # All validation rules pass - # Process the data in form.cleaned_data - # ... - return HttpResponseRedirect('/thanks/') # Redirect after POST - else: - form = ContactForm() # An unbound form - - return render_to_response('contact.html', { - 'form': form, - }) - - -There are three code paths here: - - 1. If the form has not been submitted, an unbound instance of ContactForm is - created and passed to the template. - 2. If the form has been submitted, a bound instance of the form is created - using ``request.POST``. If the submitted data is valid, it is processed - and the user is re-directed to a "thanks" page. - 3. If the form has been submitted but is invalid, the bound form instance is - passed on to the template. - -.. versionchanged:: 1.0 - The ``cleaned_data`` attribute was called ``clean_data`` in earlier releases. - -The distinction between **bound** and **unbound** forms is important. An unbound -form does not have any data associated with it; when rendered to the user, it -will be empty or will contain default values. A bound form does have submitted -data, and hence can be used to tell if that data is valid. If an invalid bound -form is rendered it can include inline error messages telling the user where -they went wrong. - -See :ref:`ref-forms-api-bound-unbound` for further information on the -differences between bound and unbound forms. - -Handling file uploads with a form ---------------------------------- - -To see how to handle file uploads with your form see -:ref:`binding-uploaded-files` for more information. - -Processing the data from a form -------------------------------- - -Once ``is_valid()`` returns ``True``, you can process the form submission safe -in the knowledge that it conforms to the validation rules defined by your form. -While you could access ``request.POST`` directly at this point, it is better to -access ``form.cleaned_data``. This data has not only been validated but will -also be converted in to the relevant Python types for you. In the above example, -``cc_myself`` will be a boolean value. Likewise, fields such as ``IntegerField`` -and ``FloatField`` convert values to a Python int and float respectively. - -Extending the above example, here's how the form data could be processed: - -.. code-block:: python - - if form.is_valid(): - subject = form.cleaned_data['subject'] - message = form.cleaned_data['message'] - sender = form.cleaned_data['sender'] - cc_myself = form.cleaned_data['cc_myself'] - - recipients = ['info@example.com'] - if cc_myself: - recipients.append(sender) - - from django.core.mail import send_mail - send_mail(subject, message, sender, recipients) - return HttpResponseRedirect('/thanks/') # Redirect after POST - -For more on sending e-mail from Django, see :doc:`/topics/email`. - -Displaying a form using a template ----------------------------------- - -Forms are designed to work with the Django template language. In the above -example, we passed our ``ContactForm`` instance to the template using the -context variable ``form``. Here's a simple example template:: - - <form action="/contact/" method="post"> - {{ form.as_p }} - <input type="submit" value="Submit" /> - </form> - -The form only outputs its own fields; it is up to you to provide the surrounding -``<form>`` tags and the submit button. - -``form.as_p`` will output the form with each form field and accompanying label -wrapped in a paragraph. Here's the output for our example template:: - - <form action="/contact/" method="post"> - <p><label for="id_subject">Subject:</label> - <input id="id_subject" type="text" name="subject" maxlength="100" /></p> - <p><label for="id_message">Message:</label> - <input type="text" name="message" id="id_message" /></p> - <p><label for="id_sender">Sender:</label> - <input type="text" name="sender" id="id_sender" /></p> - <p><label for="id_cc_myself">Cc myself:</label> - <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p> - <input type="submit" value="Submit" /> - </form> - -Note that each form field has an ID attribute set to ``id_<field-name>``, which -is referenced by the accompanying label tag. This is important for ensuring -forms are accessible to assistive technology such as screen reader software. You -can also :ref:`customize the way in which labels and ids are generated -<ref-forms-api-configuring-label>`. - -You can also use ``form.as_table`` to output table rows (you'll need to provide -your own ``<table>`` tags) and ``form.as_ul`` to output list items. - -Customizing the form template ------------------------------ - -If the default generated HTML is not to your taste, you can completely customize -the way a form is presented using the Django template language. Extending the -above example:: - - <form action="/contact/" method="post"> - {{ form.non_field_errors }} - <div class="fieldWrapper"> - {{ form.subject.errors }} - <label for="id_subject">E-mail subject:</label> - {{ form.subject }} - </div> - <div class="fieldWrapper"> - {{ form.message.errors }} - <label for="id_message">Your message:</label> - {{ form.message }} - </div> - <div class="fieldWrapper"> - {{ form.sender.errors }} - <label for="id_sender">Your email address:</label> - {{ form.sender }} - </div> - <div class="fieldWrapper"> - {{ form.cc_myself.errors }} - <label for="id_cc_myself">CC yourself?</label> - {{ form.cc_myself }} - </div> - <p><input type="submit" value="Send message" /></p> - </form> - -Each named form-field can be output to the template using -``{{ form.name_of_field }}``, which will produce the HTML needed to display the -form widget. Using ``{{ form.name_of_field.errors }}`` displays a list of form -errors, rendered as an unordered list. This might look like:: - - <ul class="errorlist"> - <li>Sender is required.</li> - </ul> - -The list has a CSS class of ``errorlist`` to allow you to style its appearance. -If you wish to further customize the display of errors you can do so by looping -over them:: - - {% if form.subject.errors %} - <ol> - {% for error in form.subject.errors %} - <li><strong>{{ error|escape }}</strong></li> - {% endfor %} - </ol> - {% endif %} - -Looping over the form's fields ------------------------------- - -If you're using the same HTML for each of your form fields, you can reduce -duplicate code by looping through each field in turn using a ``{% for %}`` -loop:: - - <form action="/contact/" method="post"> - {% for field in form %} - <div class="fieldWrapper"> - {{ field.errors }} - {{ field.label_tag }}: {{ field }} - </div> - {% endfor %} - <p><input type="submit" value="Send message" /></p> - </form> - -Within this loop, ``{{ field }}`` is an instance of :class:`BoundField`. -``BoundField`` also has the following attributes, which can be useful in your -templates: - - ``{{ field.label }}`` - The label of the field, e.g. ``E-mail address``. - - ``{{ field.label_tag }}`` - The field's label wrapped in the appropriate HTML ``<label>`` tag, - e.g. ``<label for="id_email">E-mail address</label>`` - - ``{{ field.html_name }}`` - The name of the field that will be used in the input element's name - field. This takes the form prefix into account, if it has been set. - - ``{{ field.help_text }}`` - Any help text that has been associated with the field. - - ``{{ field.errors }}`` - Outputs a ``<ul class="errorlist">`` containing any validation errors - corresponding to this field. You can customize the presentation of - the errors with a ``{% for error in field.errors %}`` loop. In this - case, each object in the loop is a simple string containing the error - message. - - ``field.is_hidden`` - This attribute is ``True`` if the form field is a hidden field and - ``False`` otherwise. It's not particularly useful as a template - variable, but could be useful in conditional tests such as:: - - {% if field.is_hidden %} - {# Do something special #} - {% endif %} - -Looping over hidden and visible fields -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you're manually laying out a form in a template, as opposed to relying on -Django's default form layout, you might want to treat ``<input type="hidden">`` -fields differently than non-hidden fields. For example, because hidden fields -don't display anything, putting error messages "next to" the field could cause -confusion for your users -- so errors for those fields should be handled -differently. - -Django provides two methods on a form that allow you to loop over the hidden -and visible fields independently: ``hidden_fields()`` and -``visible_fields()``. Here's a modification of an earlier example that uses -these two methods:: - - <form action="/contact/" method="post"> - {% for field in form.visible_fields %} - <div class="fieldWrapper"> - - {# Include the hidden fields in the form #} - {% if forloop.first %} - {% for hidden in form.hidden_fields %} - {{ hidden }} - {% endfor %} - {% endif %} - - {{ field.errors }} - {{ field.label_tag }}: {{ field }} - </div> - {% endfor %} - <p><input type="submit" value="Send message" /></p> - </form> - -This example does not handle any errors in the hidden fields. Usually, an -error in a hidden field is a sign of form tampering, since normal form -interaction won't alter them. However, you could easily insert some error -displays for those form errors, as well. - -.. versionadded:: 1.1 - The ``hidden_fields`` and ``visible_fields`` methods are new in Django - 1.1. - -Reusable form templates ------------------------ - -If your site uses the same rendering logic for forms in multiple places, you -can reduce duplication by saving the form's loop in a standalone template and -using the :ttag:`include` tag to reuse it in other templates:: - - <form action="/contact/" method="post"> - {% include "form_snippet.html" %} - <p><input type="submit" value="Send message" /></p> - </form> - - # In form_snippet.html: - - {% for field in form %} - <div class="fieldWrapper"> - {{ field.errors }} - {{ field.label_tag }}: {{ field }} - </div> - {% endfor %} - -If the form object passed to a template has a different name within the -context, you can alias it using the :ttag:`with` tag:: - - <form action="/comments/add/" method="post"> - {% with comment_form as form %} - {% include "form_snippet.html" %} - {% endwith %} - <p><input type="submit" value="Submit comment" /></p> - </form> - -If you find yourself doing this often, you might consider creating a custom -:ref:`inclusion tag<howto-custom-template-tags-inclusion-tags>`. - -Further topics -============== - -This covers the basics, but forms can do a whole lot more: - -.. toctree:: - :maxdepth: 2 - - modelforms - formsets - media - -.. seealso:: - - :doc:`The Forms Reference </ref/forms/index>` - Covers the full API reference, including form fields, form widgets, - and form and field validation. diff --git a/parts/django/docs/topics/forms/media.txt b/parts/django/docs/topics/forms/media.txt deleted file mode 100644 index fe70894..0000000 --- a/parts/django/docs/topics/forms/media.txt +++ /dev/null @@ -1,309 +0,0 @@ -Form Media -========== - -Rendering an attractive and easy-to-use Web form requires more than just -HTML - it also requires CSS stylesheets, and if you want to use fancy -"Web2.0" widgets, you may also need to include some JavaScript on each -page. The exact combination of CSS and JavaScript that is required for -any given page will depend upon the widgets that are in use on that page. - -This is where Django media definitions come in. Django allows you to -associate different media files with the forms and widgets that require -that media. For example, if you want to use a calendar to render DateFields, -you can define a custom Calendar widget. This widget can then be associated -with the CSS and JavaScript that is required to render the calendar. When -the Calendar widget is used on a form, Django is able to identify the CSS and -JavaScript files that are required, and provide the list of file names -in a form suitable for easy inclusion on your Web page. - -.. admonition:: Media and Django Admin - - The Django Admin application defines a number of customized widgets - for calendars, filtered selections, and so on. These widgets define - media requirements, and the Django Admin uses the custom widgets - in place of the Django defaults. The Admin templates will only include - those media files that are required to render the widgets on any - given page. - - If you like the widgets that the Django Admin application uses, - feel free to use them in your own application! They're all stored - in ``django.contrib.admin.widgets``. - -.. admonition:: Which JavaScript toolkit? - - Many JavaScript toolkits exist, and many of them include widgets (such - as calendar widgets) that can be used to enhance your application. - Django has deliberately avoided blessing any one JavaScript toolkit. - Each toolkit has its own relative strengths and weaknesses - use - whichever toolkit suits your requirements. Django is able to integrate - with any JavaScript toolkit. - -Media as a static definition ----------------------------- - -The easiest way to define media is as a static definition. Using this method, -the media declaration is an inner class. The properties of the inner class -define the media requirements. - -Here's a simple example:: - - class CalendarWidget(forms.TextInput): - class Media: - css = { - 'all': ('pretty.css',) - } - js = ('animations.js', 'actions.js') - -This code defines a ``CalendarWidget``, which will be based on ``TextInput``. -Every time the CalendarWidget is used on a form, that form will be directed -to include the CSS file ``pretty.css``, and the JavaScript files -``animations.js`` and ``actions.js``. - -This static media definition is converted at runtime into a widget property -named ``media``. The media for a CalendarWidget instance can be retrieved -through this property:: - - >>> w = CalendarWidget() - >>> print w.media - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - -Here's a list of all possible ``Media`` options. There are no required options. - -``css`` -~~~~~~~ - -A dictionary describing the CSS files required for various forms of output -media. - -The values in the dictionary should be a tuple/list of file names. See -`the section on media paths`_ for details of how to specify paths to media -files. - -.. _the section on media paths: `Paths in media definitions`_ - -The keys in the dictionary are the output media types. These are the same -types accepted by CSS files in media declarations: 'all', 'aural', 'braille', -'embossed', 'handheld', 'print', 'projection', 'screen', 'tty' and 'tv'. If -you need to have different stylesheets for different media types, provide -a list of CSS files for each output medium. The following example would -provide two CSS options -- one for the screen, and one for print:: - - class Media: - css = { - 'screen': ('pretty.css',), - 'print': ('newspaper.css',) - } - -If a group of CSS files are appropriate for multiple output media types, -the dictionary key can be a comma separated list of output media types. -In the following example, TV's and projectors will have the same media -requirements:: - - class Media: - css = { - 'screen': ('pretty.css',), - 'tv,projector': ('lo_res.css',), - 'print': ('newspaper.css',) - } - -If this last CSS definition were to be rendered, it would become the following HTML:: - - <link href="http://media.example.com/pretty.css" type="text/css" media="screen" rel="stylesheet" /> - <link href="http://media.example.com/lo_res.css" type="text/css" media="tv,projector" rel="stylesheet" /> - <link href="http://media.example.com/newspaper.css" type="text/css" media="print" rel="stylesheet" /> - -``js`` -~~~~~~ - -A tuple describing the required JavaScript files. See -`the section on media paths`_ for details of how to specify paths to media -files. - -``extend`` -~~~~~~~~~~ - -A boolean defining inheritance behavior for media declarations. - -By default, any object using a static media definition will inherit all the -media associated with the parent widget. This occurs regardless of how the -parent defines its media requirements. For example, if we were to extend our -basic Calendar widget from the example above:: - - >>> class FancyCalendarWidget(CalendarWidget): - ... class Media: - ... css = { - ... 'all': ('fancy.css',) - ... } - ... js = ('whizbang.js',) - - >>> w = FancyCalendarWidget() - >>> print w.media - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - <script type="text/javascript" src="http://media.example.com/whizbang.js"></script> - -The FancyCalendar widget inherits all the media from it's parent widget. If -you don't want media to be inherited in this way, add an ``extend=False`` -declaration to the media declaration:: - - >>> class FancyCalendarWidget(CalendarWidget): - ... class Media: - ... extend = False - ... css = { - ... 'all': ('fancy.css',) - ... } - ... js = ('whizbang.js',) - - >>> w = FancyCalendarWidget() - >>> print w.media - <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/whizbang.js"></script> - -If you require even more control over media inheritance, define your media -using a `dynamic property`_. Dynamic properties give you complete control over -which media files are inherited, and which are not. - -.. _dynamic property: `Media as a dynamic property`_ - -Media as a dynamic property ---------------------------- - -If you need to perform some more sophisticated manipulation of media -requirements, you can define the media property directly. This is done -by defining a widget property that returns an instance of ``forms.Media``. -The constructor for ``forms.Media`` accepts ``css`` and ``js`` keyword -arguments in the same format as that used in a static media definition. - -For example, the static media definition for our Calendar Widget could -also be defined in a dynamic fashion:: - - class CalendarWidget(forms.TextInput): - def _media(self): - return forms.Media(css={'all': ('pretty.css',)}, - js=('animations.js', 'actions.js')) - media = property(_media) - -See the section on `Media objects`_ for more details on how to construct -return values for dynamic media properties. - -Paths in media definitions --------------------------- - -Paths used to specify media can be either relative or absolute. If a path -starts with '/', 'http://' or 'https://', it will be interpreted as an absolute -path, and left as-is. All other paths will be prepended with the value of -``settings.MEDIA_URL``. For example, if the MEDIA_URL for your site was -``http://media.example.com/``:: - - class CalendarWidget(forms.TextInput): - class Media: - css = { - 'all': ('/css/pretty.css',), - } - js = ('animations.js', 'http://othersite.com/actions.js') - - >>> w = CalendarWidget() - >>> print w.media - <link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://othersite.com/actions.js"></script> - -Media objects -------------- - -When you interrogate the media attribute of a widget or form, the value that -is returned is a ``forms.Media`` object. As we have already seen, the string -representation of a Media object is the HTML required to include media -in the ``<head>`` block of your HTML page. - -However, Media objects have some other interesting properties. - -Media subsets -~~~~~~~~~~~~~ - -If you only want media of a particular type, you can use the subscript operator -to filter out a medium of interest. For example:: - - >>> w = CalendarWidget() - >>> print w.media - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - - >>> print w.media['css'] - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - -When you use the subscript operator, the value that is returned is a new -Media object -- but one that only contains the media of interest. - -Combining media objects -~~~~~~~~~~~~~~~~~~~~~~~ - -Media objects can also be added together. When two media objects are added, -the resulting Media object contains the union of the media from both files:: - - >>> class CalendarWidget(forms.TextInput): - ... class Media: - ... css = { - ... 'all': ('pretty.css',) - ... } - ... js = ('animations.js', 'actions.js') - - >>> class OtherWidget(forms.TextInput): - ... class Media: - ... js = ('whizbang.js',) - - >>> w1 = CalendarWidget() - >>> w2 = OtherWidget() - >>> print w1.media + w2.media - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - <script type="text/javascript" src="http://media.example.com/whizbang.js"></script> - -Media on Forms --------------- - -Widgets aren't the only objects that can have media definitions -- forms -can also define media. The rules for media definitions on forms are the -same as the rules for widgets: declarations can be static or dynamic; -path and inheritance rules for those declarations are exactly the same. - -Regardless of whether you define a media declaration, *all* Form objects -have a media property. The default value for this property is the result -of adding the media definitions for all widgets that are part of the form:: - - >>> class ContactForm(forms.Form): - ... date = DateField(widget=CalendarWidget) - ... name = CharField(max_length=40, widget=OtherWidget) - - >>> f = ContactForm() - >>> f.media - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - <script type="text/javascript" src="http://media.example.com/whizbang.js"></script> - -If you want to associate additional media with a form -- for example, CSS for form -layout -- simply add a media declaration to the form:: - - >>> class ContactForm(forms.Form): - ... date = DateField(widget=CalendarWidget) - ... name = CharField(max_length=40, widget=OtherWidget) - ... - ... class Media: - ... css = { - ... 'all': ('layout.css',) - ... } - - >>> f = ContactForm() - >>> f.media - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <link href="http://media.example.com/layout.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - <script type="text/javascript" src="http://media.example.com/whizbang.js"></script> diff --git a/parts/django/docs/topics/forms/modelforms.txt b/parts/django/docs/topics/forms/modelforms.txt deleted file mode 100644 index 23ed9a7..0000000 --- a/parts/django/docs/topics/forms/modelforms.txt +++ /dev/null @@ -1,885 +0,0 @@ -========================== -Creating forms from models -========================== - -.. module:: django.forms.models - :synopsis: ModelForm and ModelFormset. - -.. currentmodule:: django.forms - -``ModelForm`` -============= -.. class:: ModelForm - -If you're building a database-driven app, chances are you'll have forms that -map closely to Django models. For instance, you might have a ``BlogComment`` -model, and you want to create a form that lets people submit comments. In this -case, it would be redundant to define the field types in your form, because -you've already defined the fields in your model. - -For this reason, Django provides a helper class that let you create a ``Form`` -class from a Django model. - -For example:: - - >>> from django.forms import ModelForm - - # Create the form class. - >>> class ArticleForm(ModelForm): - ... class Meta: - ... model = Article - - # Creating a form to add an article. - >>> form = ArticleForm() - - # Creating a form to change an existing article. - >>> article = Article.objects.get(pk=1) - >>> form = ArticleForm(instance=article) - -Field types ------------ - -The generated ``Form`` class will have a form field for every model field. Each -model field has a corresponding default form field. For example, a -``CharField`` on a model is represented as a ``CharField`` on a form. A -model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is -the full list of conversions: - - =============================== ======================================== - Model field Form field - =============================== ======================================== - ``AutoField`` Not represented in the form - - ``BigIntegerField`` ``IntegerField`` with ``min_value`` set - to -9223372036854775808 and ``max_value`` - set to 9223372036854775807. - - ``BooleanField`` ``BooleanField`` - - ``CharField`` ``CharField`` with ``max_length`` set to - the model field's ``max_length`` - - ``CommaSeparatedIntegerField`` ``CharField`` - - ``DateField`` ``DateField`` - - ``DateTimeField`` ``DateTimeField`` - - ``DecimalField`` ``DecimalField`` - - ``EmailField`` ``EmailField`` - - ``FileField`` ``FileField`` - - ``FilePathField`` ``CharField`` - - ``FloatField`` ``FloatField`` - - ``ForeignKey`` ``ModelChoiceField`` (see below) - - ``ImageField`` ``ImageField`` - - ``IntegerField`` ``IntegerField`` - - ``IPAddressField`` ``IPAddressField`` - - ``ManyToManyField`` ``ModelMultipleChoiceField`` (see - below) - - ``NullBooleanField`` ``CharField`` - - ``PhoneNumberField`` ``USPhoneNumberField`` - (from ``django.contrib.localflavor.us``) - - ``PositiveIntegerField`` ``IntegerField`` - - ``PositiveSmallIntegerField`` ``IntegerField`` - - ``SlugField`` ``SlugField`` - - ``SmallIntegerField`` ``IntegerField`` - - ``TextField`` ``CharField`` with - ``widget=forms.Textarea`` - - ``TimeField`` ``TimeField`` - - ``URLField`` ``URLField`` with ``verify_exists`` set - to the model field's ``verify_exists`` - - ``XMLField`` ``CharField`` with - ``widget=forms.Textarea`` - =============================== ======================================== - - -.. versionadded:: 1.0 - The ``FloatField`` form field and ``DecimalField`` model and form fields - are new in Django 1.0. - -.. versionadded:: 1.2 - The ``BigIntegerField`` is new in Django 1.2. - - -As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field -types are special cases: - - * ``ForeignKey`` is represented by ``django.forms.ModelChoiceField``, - which is a ``ChoiceField`` whose choices are a model ``QuerySet``. - - * ``ManyToManyField`` is represented by - ``django.forms.ModelMultipleChoiceField``, which is a - ``MultipleChoiceField`` whose choices are a model ``QuerySet``. - -In addition, each generated form field has attributes set as follows: - - * If the model field has ``blank=True``, then ``required`` is set to - ``False`` on the form field. Otherwise, ``required=True``. - - * The form field's ``label`` is set to the ``verbose_name`` of the model - field, with the first character capitalized. - - * The form field's ``help_text`` is set to the ``help_text`` of the model - field. - - * If the model field has ``choices`` set, then the form field's ``widget`` - will be set to ``Select``, with choices coming from the model field's - ``choices``. The choices will normally include the blank choice which is - selected by default. If the field is required, this forces the user to - make a selection. The blank choice will not be included if the model - field has ``blank=False`` and an explicit ``default`` value (the - ``default`` value will be initially selected instead). - -Finally, note that you can override the form field used for a given model -field. See `Overriding the default field types or widgets`_ below. - -A full example --------------- - -Consider this set of models:: - - from django.db import models - from django.forms import ModelForm - - TITLE_CHOICES = ( - ('MR', 'Mr.'), - ('MRS', 'Mrs.'), - ('MS', 'Ms.'), - ) - - class Author(models.Model): - name = models.CharField(max_length=100) - title = models.CharField(max_length=3, choices=TITLE_CHOICES) - birth_date = models.DateField(blank=True, null=True) - - def __unicode__(self): - return self.name - - class Book(models.Model): - name = models.CharField(max_length=100) - authors = models.ManyToManyField(Author) - - class AuthorForm(ModelForm): - class Meta: - model = Author - - class BookForm(ModelForm): - class Meta: - model = Book - -With these models, the ``ModelForm`` subclasses above would be roughly -equivalent to this (the only difference being the ``save()`` method, which -we'll discuss in a moment.):: - - class AuthorForm(forms.Form): - name = forms.CharField(max_length=100) - title = forms.CharField(max_length=3, - widget=forms.Select(choices=TITLE_CHOICES)) - birth_date = forms.DateField(required=False) - - class BookForm(forms.Form): - name = forms.CharField(max_length=100) - authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all()) - -The ``is_valid()`` method and ``errors`` ----------------------------------------- - -.. versionchanged:: 1.2 - -The first time you call ``is_valid()`` or access the ``errors`` attribute of a -``ModelForm`` has always triggered form validation, but as of Django 1.2, it -will also trigger :ref:`model validation <validating-objects>`. This has the -side-effect of cleaning the model you pass to the ``ModelForm`` constructor. -For instance, calling ``is_valid()`` on your form will convert any date fields -on your model to actual date objects. - - -The ``save()`` method ---------------------- - -Every form produced by ``ModelForm`` also has a ``save()`` -method. This method creates and saves a database object from the data -bound to the form. A subclass of ``ModelForm`` can accept an existing -model instance as the keyword argument ``instance``; if this is -supplied, ``save()`` will update that instance. If it's not supplied, -``save()`` will create a new instance of the specified model:: - - # Create a form instance from POST data. - >>> f = ArticleForm(request.POST) - - # Save a new Article object from the form's data. - >>> new_article = f.save() - - # Create a form to edit an existing Article. - >>> a = Article.objects.get(pk=1) - >>> f = ArticleForm(instance=a) - >>> f.save() - - # Create a form to edit an existing Article, but use - # POST data to populate the form. - >>> a = Article.objects.get(pk=1) - >>> f = ArticleForm(request.POST, instance=a) - >>> f.save() - -Note that ``save()`` will raise a ``ValueError`` if the data in the form -doesn't validate -- i.e., if form.errors evaluates to True. - -This ``save()`` method accepts an optional ``commit`` keyword argument, which -accepts either ``True`` or ``False``. If you call ``save()`` with -``commit=False``, then it will return an object that hasn't yet been saved to -the database. In this case, it's up to you to call ``save()`` on the resulting -model instance. This is useful if you want to do custom processing on the -object before saving it, or if you want to use one of the specialized -:ref:`model saving options <ref-models-force-insert>`. ``commit`` is ``True`` -by default. - -Another side effect of using ``commit=False`` is seen when your model has -a many-to-many relation with another model. If your model has a many-to-many -relation and you specify ``commit=False`` when you save a form, Django cannot -immediately save the form data for the many-to-many relation. This is because -it isn't possible to save many-to-many data for an instance until the instance -exists in the database. - -To work around this problem, every time you save a form using ``commit=False``, -Django adds a ``save_m2m()`` method to your ``ModelForm`` subclass. After -you've manually saved the instance produced by the form, you can invoke -``save_m2m()`` to save the many-to-many form data. For example:: - - # Create a form instance with POST data. - >>> f = AuthorForm(request.POST) - - # Create, but don't save the new author instance. - >>> new_author = f.save(commit=False) - - # Modify the author in some way. - >>> new_author.some_field = 'some_value' - - # Save the new instance. - >>> new_author.save() - - # Now, save the many-to-many data for the form. - >>> f.save_m2m() - -Calling ``save_m2m()`` is only required if you use ``save(commit=False)``. -When you use a simple ``save()`` on a form, all data -- including -many-to-many data -- is saved without the need for any additional method calls. -For example:: - - # Create a form instance with POST data. - >>> a = Author() - >>> f = AuthorForm(request.POST, instance=a) - - # Create and save the new author instance. There's no need to do anything else. - >>> new_author = f.save() - -Other than the ``save()`` and ``save_m2m()`` methods, a ``ModelForm`` works -exactly the same way as any other ``forms`` form. For example, the -``is_valid()`` method is used to check for validity, the ``is_multipart()`` -method is used to determine whether a form requires multipart file upload (and -hence whether ``request.FILES`` must be passed to the form), etc. See -:ref:`binding-uploaded-files` for more information. - -Using a subset of fields on the form ------------------------------------- - -In some cases, you may not want all the model fields to appear on the generated -form. There are three ways of telling ``ModelForm`` to use only a subset of the -model fields: - -1. Set ``editable=False`` on the model field. As a result, *any* form - created from the model via ``ModelForm`` will not include that - field. - -2. Use the ``fields`` attribute of the ``ModelForm``'s inner ``Meta`` - class. This attribute, if given, should be a list of field names - to include in the form. - - .. versionchanged:: 1.1 - - The form will render the fields in the same order they are specified in the - ``fields`` attribute. - -3. Use the ``exclude`` attribute of the ``ModelForm``'s inner ``Meta`` - class. This attribute, if given, should be a list of field names - to exclude from the form. - -For example, if you want a form for the ``Author`` model (defined -above) that includes only the ``name`` and ``title`` fields, you would -specify ``fields`` or ``exclude`` like this:: - - class PartialAuthorForm(ModelForm): - class Meta: - model = Author - fields = ('name', 'title') - - class PartialAuthorForm(ModelForm): - class Meta: - model = Author - exclude = ('birth_date',) - -Since the Author model has only 3 fields, 'name', 'title', and -'birth_date', the forms above will contain exactly the same fields. - -.. note:: - - If you specify ``fields`` or ``exclude`` when creating a form with - ``ModelForm``, then the fields that are not in the resulting form will not - be set by the form's ``save()`` method. Django will prevent any attempt to - save an incomplete model, so if the model does not allow the missing fields - to be empty, and does not provide a default value for the missing fields, - any attempt to ``save()`` a ``ModelForm`` with missing fields will fail. - To avoid this failure, you must instantiate your model with initial values - for the missing, but required fields:: - - author = Author(title='Mr') - form = PartialAuthorForm(request.POST, instance=author) - form.save() - - Alternatively, you can use ``save(commit=False)`` and manually set - any extra required fields:: - - form = PartialAuthorForm(request.POST) - author = form.save(commit=False) - author.title = 'Mr' - author.save() - - See the `section on saving forms`_ for more details on using - ``save(commit=False)``. - -.. _section on saving forms: `The save() method`_ - -Overriding the default field types or widgets ---------------------------------------------- - -.. versionadded:: 1.2 - The ``widgets`` attribute is new in Django 1.2. - -The default field types, as described in the `Field types`_ table above, are -sensible defaults. If you have a ``DateField`` in your model, chances are you'd -want that to be represented as a ``DateField`` in your form. But -``ModelForm`` gives you the flexibility of changing the form field type and -widget for a given model field. - -To specify a custom widget for a field, use the ``widgets`` attribute of the -inner ``Meta`` class. This should be a dictionary mapping field names to widget -classes or instances. - -For example, if you want the a ``CharField`` for the ``name`` -attribute of ``Author`` to be represented by a ``<textarea>`` instead -of its default ``<input type="text">``, you can override the field's -widget:: - - from django.forms import ModelForm, Textarea - - class AuthorForm(ModelForm): - class Meta: - model = Author - fields = ('name', 'title', 'birth_date') - widgets = { - 'name': Textarea(attrs={'cols': 80, 'rows': 20}), - } - -The ``widgets`` dictionary accepts either widget instances (e.g., -``Textarea(...)``) or classes (e.g., ``Textarea``). - -If you want to further customize a field -- including its type, label, etc. -- -you can do this by declaratively specifying fields like you would in a regular -``Form``. Declared fields will override the default ones generated by using the -``model`` attribute. - -For example, if you wanted to use ``MyDateFormField`` for the ``pub_date`` -field, you could do the following:: - - class ArticleForm(ModelForm): - pub_date = MyDateFormField() - - class Meta: - model = Article - -If you want to override a field's default label, then specify the ``label`` -parameter when declaring the form field:: - - >>> class ArticleForm(ModelForm): - ... pub_date = DateField(label='Publication date') - ... - ... class Meta: - ... model = Article - -.. note:: - - If you explicitly instantiate a form field like this, Django assumes that you - want to completely define its behavior; therefore, default attributes (such as - ``max_length`` or ``required``) are not drawn from the corresponding model. If - you want to maintain the behavior specified in the model, you must set the - relevant arguments explicitly when declaring the form field. - - For example, if the ``Article`` model looks like this:: - - class Article(models.Model): - headline = models.CharField(max_length=200, null=True, blank=True, - help_text="Use puns liberally") - content = models.TextField() - - and you want to do some custom validation for ``headline``, while keeping - the ``blank`` and ``help_text`` values as specified, you might define - ``ArticleForm`` like this:: - - class ArticleForm(ModelForm): - headline = MyFormField(max_length=200, required=False, - help_text="Use puns liberally") - - class Meta: - model = Article - - See the :doc:`form field documentation </ref/forms/fields>` for more information - on fields and their arguments. - -Changing the order of fields ----------------------------- - -.. versionadded:: 1.1 - -By default, a ``ModelForm`` will render fields in the same order that they are -defined on the model, with ``ManyToManyField`` instances appearing last. If -you want to change the order in which fields are rendered, you can use the -``fields`` attribute on the ``Meta`` class. - -The ``fields`` attribute defines the subset of model fields that will be -rendered, and the order in which they will be rendered. For example given this -model:: - - class Book(models.Model): - author = models.ForeignKey(Author) - title = models.CharField(max_length=100) - -the ``author`` field would be rendered first. If we wanted the title field -to be rendered first, we could specify the following ``ModelForm``:: - - >>> class BookForm(ModelForm): - ... class Meta: - ... model = Book - ... fields = ('title', 'author') - -.. _overriding-modelform-clean-method: - -Overriding the clean() method ------------------------------ - -You can override the ``clean()`` method on a model form to provide additional -validation in the same way you can on a normal form. - -In this regard, model forms have two specific characteristics when compared to -forms: - -By default the ``clean()`` method validates the uniqueness of fields that are -marked as ``unique``, ``unique_together`` or ``unique_for_date|month|year`` on -the model. Therefore, if you would like to override the ``clean()`` method and -maintain the default validation, you must call the parent class's ``clean()`` -method. - -Also, a model form instance bound to a model object will contain a -``self.instance`` attribute that gives model form methods access to that -specific model instance. - -Form inheritance ----------------- - -As with basic forms, you can extend and reuse ``ModelForms`` by inheriting -them. This is useful if you need to declare extra fields or extra methods on a -parent class for use in a number of forms derived from models. For example, -using the previous ``ArticleForm`` class:: - - >>> class EnhancedArticleForm(ArticleForm): - ... def clean_pub_date(self): - ... ... - -This creates a form that behaves identically to ``ArticleForm``, except there's -some extra validation and cleaning for the ``pub_date`` field. - -You can also subclass the parent's ``Meta`` inner class if you want to change -the ``Meta.fields`` or ``Meta.excludes`` lists:: - - >>> class RestrictedArticleForm(EnhancedArticleForm): - ... class Meta(ArticleForm.Meta): - ... exclude = ('body',) - -This adds the extra method from the ``EnhancedArticleForm`` and modifies -the original ``ArticleForm.Meta`` to remove one field. - -There are a couple of things to note, however. - - * Normal Python name resolution rules apply. If you have multiple base - classes that declare a ``Meta`` inner class, only the first one will be - used. This means the child's ``Meta``, if it exists, otherwise the - ``Meta`` of the first parent, etc. - - * For technical reasons, a subclass cannot inherit from both a ``ModelForm`` - and a ``Form`` simultaneously. - -Chances are these notes won't affect you unless you're trying to do something -tricky with subclassing. - -Interaction with model validation ---------------------------------- - -As part of its validation process, ``ModelForm`` will call the ``clean()`` -method of each field on your model that has a corresponding field on your form. -If you have excluded any model fields, validation will not be run on those -fields. See the :doc:`form validation </ref/forms/validation>` documentation -for more on how field cleaning and validation work. Also, your model's -``clean()`` method will be called before any uniqueness checks are made. See -:ref:`Validating objects <validating-objects>` for more information on the -model's ``clean()`` hook. - -.. _model-formsets: - -Model formsets -============== - -Like :doc:`regular formsets </topics/forms/formsets>`, Django provides a couple -of enhanced formset classes that make it easy to work with Django models. Let's -reuse the ``Author`` model from above:: - - >>> from django.forms.models import modelformset_factory - >>> AuthorFormSet = modelformset_factory(Author) - -This will create a formset that is capable of working with the data associated -with the ``Author`` model. It works just like a regular formset:: - - >>> formset = AuthorFormSet() - >>> print formset - <input type="hidden" name="form-TOTAL_FORMS" value="1" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS" /><input type="hidden" name="form-MAX_NUM_FORMS" id="id_form-MAX_NUM_FORMS" /> - <tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" maxlength="100" /></td></tr> - <tr><th><label for="id_form-0-title">Title:</label></th><td><select name="form-0-title" id="id_form-0-title"> - <option value="" selected="selected">---------</option> - <option value="MR">Mr.</option> - <option value="MRS">Mrs.</option> - <option value="MS">Ms.</option> - </select></td></tr> - <tr><th><label for="id_form-0-birth_date">Birth date:</label></th><td><input type="text" name="form-0-birth_date" id="id_form-0-birth_date" /><input type="hidden" name="form-0-id" id="id_form-0-id" /></td></tr> - -.. note:: - ``modelformset_factory`` uses ``formset_factory`` to generate formsets. - This means that a model formset is just an extension of a basic formset - that knows how to interact with a particular model. - -Changing the queryset ---------------------- - -By default, when you create a formset from a model, the formset will use a -queryset that includes all objects in the model (e.g., -``Author.objects.all()``). You can override this behavior by using the -``queryset`` argument:: - - >>> formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O')) - -Alternatively, you can create a subclass that sets ``self.queryset`` in -``__init__``:: - - from django.forms.models import BaseModelFormSet - - class BaseAuthorFormSet(BaseModelFormSet): - def __init__(self, *args, **kwargs): - super(BaseAuthorFormSet, self).__init__(*args, **kwargs) - self.queryset = Author.objects.filter(name__startswith='O') - -Then, pass your ``BaseAuthorFormSet`` class to the factory function:: - - >>> AuthorFormSet = modelformset_factory(Author, formset=BaseAuthorFormSet) - -If you want to return a formset that doesn't include *any* pre-existing -instances of the model, you can specify an empty QuerySet:: - - >>> AuthorFormSet(queryset=Author.objects.none()) - - -Controlling which fields are used with ``fields`` and ``exclude`` ------------------------------------------------------------------ - -By default, a model formset uses all fields in the model that are not marked -with ``editable=False``. However, this can be overridden at the formset level:: - - >>> AuthorFormSet = modelformset_factory(Author, fields=('name', 'title')) - -Using ``fields`` restricts the formset to use only the given fields. -Alternatively, you can take an "opt-out" approach, specifying which fields to -exclude:: - - >>> AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',)) - -.. _saving-objects-in-the-formset: - -Saving objects in the formset ------------------------------ - -As with a ``ModelForm``, you can save the data as a model object. This is done -with the formset's ``save()`` method:: - - # Create a formset instance with POST data. - >>> formset = AuthorFormSet(request.POST) - - # Assuming all is valid, save the data. - >>> instances = formset.save() - -The ``save()`` method returns the instances that have been saved to the -database. If a given instance's data didn't change in the bound data, the -instance won't be saved to the database and won't be included in the return -value (``instances``, in the above example). - -Pass ``commit=False`` to return the unsaved model instances:: - - # don't save to the database - >>> instances = formset.save(commit=False) - >>> for instance in instances: - ... # do something with instance - ... instance.save() - -This gives you the ability to attach data to the instances before saving them -to the database. If your formset contains a ``ManyToManyField``, you'll also -need to call ``formset.save_m2m()`` to ensure the many-to-many relationships -are saved properly. - -.. _model-formsets-max-num: - -Limiting the number of editable objects ---------------------------------------- - -.. versionchanged:: 1.2 - -As with regular formsets, you can use the ``max_num`` and ``extra`` parameters -to ``modelformset_factory`` to limit the number of extra forms displayed. - -``max_num`` does not prevent existing objects from being displayed:: - - >>> Author.objects.order_by('name') - [<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>] - - >>> AuthorFormSet = modelformset_factory(Author, max_num=1) - >>> formset = AuthorFormSet(queryset=Author.objects.order_by('name')) - >>> [x.name for x in formset.get_queryset()] - [u'Charles Baudelaire', u'Paul Verlaine', u'Walt Whitman'] - -If the value of ``max_num`` is greater than the number of existing related -objects, up to ``extra`` additional blank forms will be added to the formset, -so long as the total number of forms does not exceed ``max_num``:: - - >>> AuthorFormSet = modelformset_factory(Author, max_num=4, extra=2) - >>> formset = AuthorFormSet(queryset=Author.objects.order_by('name')) - >>> for form in formset.forms: - ... print form.as_table() - <tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" value="Charles Baudelaire" maxlength="100" /><input type="hidden" name="form-0-id" value="1" id="id_form-0-id" /></td></tr> - <tr><th><label for="id_form-1-name">Name:</label></th><td><input id="id_form-1-name" type="text" name="form-1-name" value="Paul Verlaine" maxlength="100" /><input type="hidden" name="form-1-id" value="3" id="id_form-1-id" /></td></tr> - <tr><th><label for="id_form-2-name">Name:</label></th><td><input id="id_form-2-name" type="text" name="form-2-name" value="Walt Whitman" maxlength="100" /><input type="hidden" name="form-2-id" value="2" id="id_form-2-id" /></td></tr> - <tr><th><label for="id_form-3-name">Name:</label></th><td><input id="id_form-3-name" type="text" name="form-3-name" maxlength="100" /><input type="hidden" name="form-3-id" id="id_form-3-id" /></td></tr> - -.. versionchanged:: 1.2 - -A ``max_num`` value of ``None`` (the default) puts no limit on the number of -forms displayed. - -Using a model formset in a view -------------------------------- - -Model formsets are very similar to formsets. Let's say we want to present a -formset to edit ``Author`` model instances:: - - def manage_authors(request): - AuthorFormSet = modelformset_factory(Author) - if request.method == 'POST': - formset = AuthorFormSet(request.POST, request.FILES) - if formset.is_valid(): - formset.save() - # do something. - else: - formset = AuthorFormSet() - return render_to_response("manage_authors.html", { - "formset": formset, - }) - -As you can see, the view logic of a model formset isn't drastically different -than that of a "normal" formset. The only difference is that we call -``formset.save()`` to save the data into the database. (This was described -above, in :ref:`saving-objects-in-the-formset`.) - -Overiding ``clean()`` on a ``model_formset`` --------------------------------------------- - -Just like with ``ModelForms``, by default the ``clean()`` method of a -``model_formset`` will validate that none of the items in the formset violate -the unique constraints on your model (either ``unique``, ``unique_together`` or -``unique_for_date|month|year``). If you want to overide the ``clean()`` method -on a ``model_formset`` and maintain this validation, you must call the parent -class's ``clean`` method:: - - class MyModelFormSet(BaseModelFormSet): - def clean(self): - super(MyModelFormSet, self).clean() - # example custom validation across forms in the formset: - for form in self.forms: - # your custom formset validation - -Using a custom queryset ------------------------ - -As stated earlier, you can override the default queryset used by the model -formset:: - - def manage_authors(request): - AuthorFormSet = modelformset_factory(Author) - if request.method == "POST": - formset = AuthorFormSet(request.POST, request.FILES, - queryset=Author.objects.filter(name__startswith='O')) - if formset.is_valid(): - formset.save() - # Do something. - else: - formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O')) - return render_to_response("manage_authors.html", { - "formset": formset, - }) - -Note that we pass the ``queryset`` argument in both the ``POST`` and ``GET`` -cases in this example. - -Using the formset in the template ---------------------------------- - -.. highlight:: html+django - -There are three ways to render a formset in a Django template. - -First, you can let the formset do most of the work:: - - <form method="post" action=""> - {{ formset }} - </form> - -Second, you can manually render the formset, but let the form deal with -itself:: - - <form method="post" action=""> - {{ formset.management_form }} - {% for form in formset.forms %} - {{ form }} - {% endfor %} - </form> - -When you manually render the forms yourself, be sure to render the management -form as shown above. See the :ref:`management form documentation -<understanding-the-managementform>`. - -Third, you can manually render each field:: - - <form method="post" action=""> - {{ formset.management_form }} - {% for form in formset.forms %} - {% for field in form %} - {{ field.label_tag }}: {{ field }} - {% endfor %} - {% endfor %} - </form> - -If you opt to use this third method and you don't iterate over the fields with -a ``{% for %}`` loop, you'll need to render the primary key field. For example, -if you were rendering the ``name`` and ``age`` fields of a model:: - - <form method="post" action=""> - {{ formset.management_form }} - {% for form in formset.forms %} - {{ form.id }} - <ul> - <li>{{ form.name }}</li> - <li>{{ form.age }}</li> - </ul> - {% endfor %} - </form> - -Notice how we need to explicitly render ``{{ form.id }}``. This ensures that -the model formset, in the ``POST`` case, will work correctly. (This example -assumes a primary key named ``id``. If you've explicitly defined your own -primary key that isn't called ``id``, make sure it gets rendered.) - -.. highlight:: python - -Inline formsets -=============== - -Inline formsets is a small abstraction layer on top of model formsets. These -simplify the case of working with related objects via a foreign key. Suppose -you have these two models:: - - class Author(models.Model): - name = models.CharField(max_length=100) - - class Book(models.Model): - author = models.ForeignKey(Author) - title = models.CharField(max_length=100) - -If you want to create a formset that allows you to edit books belonging to -a particular author, you could do this:: - - >>> from django.forms.models import inlineformset_factory - >>> BookFormSet = inlineformset_factory(Author, Book) - >>> author = Author.objects.get(name=u'Mike Royko') - >>> formset = BookFormSet(instance=author) - -.. note:: - ``inlineformset_factory`` uses ``modelformset_factory`` and marks - ``can_delete=True``. - -More than one foreign key to the same model -------------------------------------------- - -If your model contains more than one foreign key to the same model, you'll -need to resolve the ambiguity manually using ``fk_name``. For example, consider -the following model:: - - class Friendship(models.Model): - from_friend = models.ForeignKey(Friend) - to_friend = models.ForeignKey(Friend) - length_in_months = models.IntegerField() - -To resolve this, you can use ``fk_name`` to ``inlineformset_factory``:: - - >>> FriendshipFormSet = inlineformset_factory(Friend, Friendship, fk_name="from_friend") - -Using an inline formset in a view ---------------------------------- - -You may want to provide a view that allows a user to edit the related objects -of a model. Here's how you can do that:: - - def manage_books(request, author_id): - author = Author.objects.get(pk=author_id) - BookInlineFormSet = inlineformset_factory(Author, Book) - if request.method == "POST": - formset = BookInlineFormSet(request.POST, request.FILES, instance=author) - if formset.is_valid(): - formset.save() - # Do something. - else: - formset = BookInlineFormSet(instance=author) - return render_to_response("manage_books.html", { - "formset": formset, - }) - -Notice how we pass ``instance`` in both the ``POST`` and ``GET`` cases. diff --git a/parts/django/docs/topics/generic-views.txt b/parts/django/docs/topics/generic-views.txt deleted file mode 100644 index 41e32c8..0000000 --- a/parts/django/docs/topics/generic-views.txt +++ /dev/null @@ -1,501 +0,0 @@ -============= -Generic views -============= - -Writing Web applications can be monotonous, because we repeat certain patterns -again and again. Django tries to take away some of that monotony at the model -and template layers, but Web developers also experience this boredom at the view -level. - -Django's *generic views* were developed to ease that pain. They take certain -common idioms and patterns found in view development and abstract them so that -you can quickly write common views of data without having to write too much -code. - -We can recognize certain common tasks, like displaying a list of objects, and -write code that displays a list of *any* object. Then the model in question can -be passed as an extra argument to the URLconf. - -Django ships with generic views to do the following: - - * Perform common "simple" tasks: redirect to a different page and - render a given template. - - * Display list and detail pages for a single object. If we were creating an - application to manage conferences then a ``talk_list`` view and a - ``registered_user_list`` view would be examples of list views. A single - talk page is an example of what we call a "detail" view. - - * Present date-based objects in year/month/day archive pages, - associated detail, and "latest" pages. The Django Weblog's - (http://www.djangoproject.com/weblog/) year, month, and - day archives are built with these, as would be a typical - newspaper's archives. - - * Allow users to create, update, and delete objects -- with or - without authorization. - -Taken together, these views provide easy interfaces to perform the most common -tasks developers encounter. - -Using generic views -=================== - -All of these views are used by creating configuration dictionaries in -your URLconf files and passing those dictionaries as the third member of the -URLconf tuple for a given pattern. - -For example, here's a simple URLconf you could use to present a static "about" -page:: - - from django.conf.urls.defaults import * - from django.views.generic.simple import direct_to_template - - urlpatterns = patterns('', - ('^about/$', direct_to_template, { - 'template': 'about.html' - }) - ) - -Though this might seem a bit "magical" at first glance -- look, a view with no -code! --, actually the ``direct_to_template`` view simply grabs information from -the extra-parameters dictionary and uses that information when rendering the -view. - -Because this generic view -- and all the others -- is a regular view function -like any other, we can reuse it inside our own views. As an example, let's -extend our "about" example to map URLs of the form ``/about/<whatever>/`` to -statically rendered ``about/<whatever>.html``. We'll do this by first modifying -the URLconf to point to a view function: - -.. parsed-literal:: - - from django.conf.urls.defaults import * - from django.views.generic.simple import direct_to_template - **from books.views import about_pages** - - urlpatterns = patterns('', - ('^about/$', direct_to_template, { - 'template': 'about.html' - }), - **('^about/(\\w+)/$', about_pages),** - ) - -Next, we'll write the ``about_pages`` view:: - - from django.http import Http404 - from django.template import TemplateDoesNotExist - from django.views.generic.simple import direct_to_template - - def about_pages(request, page): - try: - return direct_to_template(request, template="about/%s.html" % page) - except TemplateDoesNotExist: - raise Http404() - -Here we're treating ``direct_to_template`` like any other function. Since it -returns an ``HttpResponse``, we can simply return it as-is. The only slightly -tricky business here is dealing with missing templates. We don't want a -nonexistent template to cause a server error, so we catch -``TemplateDoesNotExist`` exceptions and return 404 errors instead. - -.. admonition:: Is there a security vulnerability here? - - Sharp-eyed readers may have noticed a possible security hole: we're - constructing the template name using interpolated content from the browser - (``template="about/%s.html" % page``). At first glance, this looks like a - classic *directory traversal* vulnerability. But is it really? - - Not exactly. Yes, a maliciously crafted value of ``page`` could cause - directory traversal, but although ``page`` *is* taken from the request URL, - not every value will be accepted. The key is in the URLconf: we're using - the regular expression ``\w+`` to match the ``page`` part of the URL, and - ``\w`` only accepts letters and numbers. Thus, any malicious characters - (dots and slashes, here) will be rejected by the URL resolver before they - reach the view itself. - -Generic views of objects -======================== - -The ``direct_to_template`` certainly is useful, but Django's generic views -really shine when it comes to presenting views on your database content. Because -it's such a common task, Django comes with a handful of built-in generic views -that make generating list and detail views of objects incredibly easy. - -Let's take a look at one of these generic views: the "object list" view. We'll -be using these models:: - - # models.py - from django.db import models - - class Publisher(models.Model): - name = models.CharField(max_length=30) - address = models.CharField(max_length=50) - city = models.CharField(max_length=60) - state_province = models.CharField(max_length=30) - country = models.CharField(max_length=50) - website = models.URLField() - - def __unicode__(self): - return self.name - - class Meta: - ordering = ["-name"] - - class Book(models.Model): - title = models.CharField(max_length=100) - authors = models.ManyToManyField('Author') - publisher = models.ForeignKey(Publisher) - publication_date = models.DateField() - -To build a list page of all publishers, we'd use a URLconf along these lines:: - - from django.conf.urls.defaults import * - from django.views.generic import list_detail - from books.models import Publisher - - publisher_info = { - "queryset" : Publisher.objects.all(), - } - - urlpatterns = patterns('', - (r'^publishers/$', list_detail.object_list, publisher_info) - ) - -That's all the Python code we need to write. We still need to write a template, -however. We could explicitly tell the ``object_list`` view which template to use -by including a ``template_name`` key in the extra arguments dictionary, but in -the absence of an explicit template Django will infer one from the object's -name. In this case, the inferred template will be -``"books/publisher_list.html"`` -- the "books" part comes from the name of the -app that defines the model, while the "publisher" bit is just the lowercased -version of the model's name. - -.. highlightlang:: html+django - -This template will be rendered against a context containing a variable called -``object_list`` that contains all the publisher objects. A very simple template -might look like the following:: - - {% extends "base.html" %} - - {% block content %} - <h2>Publishers</h2> - <ul> - {% for publisher in object_list %} - <li>{{ publisher.name }}</li> - {% endfor %} - </ul> - {% endblock %} - -That's really all there is to it. All the cool features of generic views come -from changing the "info" dictionary passed to the generic view. The -:doc:`generic views reference</ref/generic-views>` documents all the generic -views and all their options in detail; the rest of this document will consider -some of the common ways you might customize and extend generic views. - -Extending generic views -======================= - -.. highlightlang:: python - -There's no question that using generic views can speed up development -substantially. In most projects, however, there comes a moment when the -generic views no longer suffice. Indeed, the most common question asked by new -Django developers is how to make generic views handle a wider array of -situations. - -Luckily, in nearly every one of these cases, there are ways to simply extend -generic views to handle a larger array of use cases. These situations usually -fall into a handful of patterns dealt with in the sections that follow. - -Making "friendly" template contexts ------------------------------------ - -You might have noticed that our sample publisher list template stores all the -books in a variable named ``object_list``. While this works just fine, it isn't -all that "friendly" to template authors: they have to "just know" that they're -dealing with publishers here. A better name for that variable would be -``publisher_list``; that variable's content is pretty obvious. - -We can change the name of that variable easily with the ``template_object_name`` -argument: - -.. parsed-literal:: - - publisher_info = { - "queryset" : Publisher.objects.all(), - **"template_object_name" : "publisher",** - } - - urlpatterns = patterns('', - (r'^publishers/$', list_detail.object_list, publisher_info) - ) - -Providing a useful ``template_object_name`` is always a good idea. Your -coworkers who design templates will thank you. - -Adding extra context --------------------- - -Often you simply need to present some extra information beyond that provided by -the generic view. For example, think of showing a list of all the books on each -publisher detail page. The ``object_detail`` generic view provides the -publisher to the context, but it seems there's no way to get additional -information in that template. - -But there is: all generic views take an extra optional parameter, -``extra_context``. This is a dictionary of extra objects that will be added to -the template's context. So, to provide the list of all books on the detail -detail view, we'd use an info dict like this: - -.. parsed-literal:: - - from books.models import Publisher, **Book** - - publisher_info = { - "queryset" : Publisher.objects.all(), - "template_object_name" : "publisher", - **"extra_context" : {"book_list" : Book.objects.all()}** - } - -This would populate a ``{{ book_list }}`` variable in the template context. -This pattern can be used to pass any information down into the template for the -generic view. It's very handy. - -However, there's actually a subtle bug here -- can you spot it? - -The problem has to do with when the queries in ``extra_context`` are evaluated. -Because this example puts ``Book.objects.all()`` in the URLconf, it will -be evaluated only once (when the URLconf is first loaded). Once you add or -remove books, you'll notice that the generic view doesn't reflect those -changes until you reload the Web server (see :ref:`caching-and-querysets` -for more information about when QuerySets are cached and evaluated). - -.. note:: - - This problem doesn't apply to the ``queryset`` generic view argument. Since - Django knows that particular QuerySet should *never* be cached, the generic - view takes care of clearing the cache when each view is rendered. - -The solution is to use a callback in ``extra_context`` instead of a value. Any -callable (i.e., a function) that's passed to ``extra_context`` will be evaluated -when the view is rendered (instead of only once). You could do this with an -explicitly defined function: - -.. parsed-literal:: - - def get_books(): - return Book.objects.all() - - publisher_info = { - "queryset" : Publisher.objects.all(), - "template_object_name" : "publisher", - "extra_context" : **{"book_list" : get_books}** - } - -or you could use a less obvious but shorter version that relies on the fact that -``Book.objects.all`` is itself a callable: - -.. parsed-literal:: - - publisher_info = { - "queryset" : Publisher.objects.all(), - "template_object_name" : "publisher", - "extra_context" : **{"book_list" : Book.objects.all}** - } - -Notice the lack of parentheses after ``Book.objects.all``; this references -the function without actually calling it (which the generic view will do later). - -Viewing subsets of objects --------------------------- - -Now let's take a closer look at this ``queryset`` key we've been using all -along. Most generic views take one of these ``queryset`` arguments -- it's how -the view knows which set of objects to display (see :doc:`/topics/db/queries` for -more information about ``QuerySet`` objects, and see the -:doc:`generic views reference</ref/generic-views>` for the complete details). - -To pick a simple example, we might want to order a list of books by -publication date, with the most recent first: - -.. parsed-literal:: - - book_info = { - "queryset" : Book.objects.all().order_by("-publication_date"), - } - - urlpatterns = patterns('', - (r'^publishers/$', list_detail.object_list, publisher_info), - **(r'^books/$', list_detail.object_list, book_info),** - ) - - -That's a pretty simple example, but it illustrates the idea nicely. Of course, -you'll usually want to do more than just reorder objects. If you want to -present a list of books by a particular publisher, you can use the same -technique: - -.. parsed-literal:: - - **acme_books = {** - **"queryset": Book.objects.filter(publisher__name="Acme Publishing"),** - **"template_name" : "books/acme_list.html"** - **}** - - urlpatterns = patterns('', - (r'^publishers/$', list_detail.object_list, publisher_info), - **(r'^books/acme/$', list_detail.object_list, acme_books),** - ) - -Notice that along with a filtered ``queryset``, we're also using a custom -template name. If we didn't, the generic view would use the same template as the -"vanilla" object list, which might not be what we want. - -Also notice that this isn't a very elegant way of doing publisher-specific -books. If we want to add another publisher page, we'd need another handful of -lines in the URLconf, and more than a few publishers would get unreasonable. -We'll deal with this problem in the next section. - -.. note:: - - If you get a 404 when requesting ``/books/acme/``, check to ensure you - actually have a Publisher with the name 'ACME Publishing'. Generic - views have an ``allow_empty`` parameter for this case. See the - :doc:`generic views reference</ref/generic-views>` for more details. - -Complex filtering with wrapper functions ----------------------------------------- - -Another common need is to filter down the objects given in a list page by some -key in the URL. Earlier we hard-coded the publisher's name in the URLconf, but -what if we wanted to write a view that displayed all the books by some arbitrary -publisher? We can "wrap" the ``object_list`` generic view to avoid writing a lot -of code by hand. As usual, we'll start by writing a URLconf: - -.. parsed-literal:: - - from books.views import books_by_publisher - - urlpatterns = patterns('', - (r'^publishers/$', list_detail.object_list, publisher_info), - **(r'^books/(\\w+)/$', books_by_publisher),** - ) - -Next, we'll write the ``books_by_publisher`` view itself:: - - from django.http import Http404 - from django.views.generic import list_detail - from books.models import Book, Publisher - - def books_by_publisher(request, name): - - # Look up the publisher (and raise a 404 if it can't be found). - try: - publisher = Publisher.objects.get(name__iexact=name) - except Publisher.DoesNotExist: - raise Http404 - - # Use the object_list view for the heavy lifting. - return list_detail.object_list( - request, - queryset = Book.objects.filter(publisher=publisher), - template_name = "books/books_by_publisher.html", - template_object_name = "books", - extra_context = {"publisher" : publisher} - ) - -This works because there's really nothing special about generic views -- they're -just Python functions. Like any view function, generic views expect a certain -set of arguments and return ``HttpResponse`` objects. Thus, it's incredibly easy -to wrap a small function around a generic view that does additional work before -(or after; see the next section) handing things off to the generic view. - -.. note:: - - Notice that in the preceding example we passed the current publisher being - displayed in the ``extra_context``. This is usually a good idea in wrappers - of this nature; it lets the template know which "parent" object is currently - being browsed. - -Performing extra work ---------------------- - -The last common pattern we'll look at involves doing some extra work before -or after calling the generic view. - -Imagine we had a ``last_accessed`` field on our ``Author`` object that we were -using to keep track of the last time anybody looked at that author:: - - # models.py - - class Author(models.Model): - salutation = models.CharField(max_length=10) - first_name = models.CharField(max_length=30) - last_name = models.CharField(max_length=40) - email = models.EmailField() - headshot = models.ImageField(upload_to='/tmp') - last_accessed = models.DateTimeField() - -The generic ``object_detail`` view, of course, wouldn't know anything about this -field, but once again we could easily write a custom view to keep that field -updated. - -First, we'd need to add an author detail bit in the URLconf to point to a -custom view: - -.. parsed-literal:: - - from books.views import author_detail - - urlpatterns = patterns('', - #... - **(r'^authors/(?P<author_id>\\d+)/$', author_detail),** - ) - -Then we'd write our wrapper function:: - - import datetime - from books.models import Author - from django.views.generic import list_detail - from django.shortcuts import get_object_or_404 - - def author_detail(request, author_id): - # Look up the Author (and raise a 404 if she's not found) - author = get_object_or_404(Author, pk=author_id) - - # Record the last accessed date - author.last_accessed = datetime.datetime.now() - author.save() - - # Show the detail page - return list_detail.object_detail( - request, - queryset = Author.objects.all(), - object_id = author_id, - ) - -.. note:: - - This code won't actually work unless you create a - ``books/author_detail.html`` template. - -We can use a similar idiom to alter the response returned by the generic view. -If we wanted to provide a downloadable plain-text version of the list of -authors, we could use a view like this:: - - def author_list_plaintext(request): - response = list_detail.object_list( - request, - queryset = Author.objects.all(), - mimetype = "text/plain", - template_name = "books/author_list.txt" - ) - response["Content-Disposition"] = "attachment; filename=authors.txt" - return response - -This works because the generic views return simple ``HttpResponse`` objects -that can be treated like dictionaries to set HTTP headers. This -``Content-Disposition`` business, by the way, instructs the browser to -download and save the page instead of displaying it in the browser. 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. diff --git a/parts/django/docs/topics/i18n/deployment.txt b/parts/django/docs/topics/i18n/deployment.txt deleted file mode 100644 index 4727841..0000000 --- a/parts/django/docs/topics/i18n/deployment.txt +++ /dev/null @@ -1,191 +0,0 @@ -========================== -Deployment of translations -========================== - -If you don't need internationalization -====================================== - -Django's internationalization hooks are on by default, and that means there's a -bit of i18n-related overhead in certain places of the framework. If you don't -use internationalization, you should take the two seconds to set -:setting:`USE_I18N = False <USE_I18N>` in your settings file. If -:setting:`USE_I18N` is set to ``False``, then Django will make some -optimizations so as not to load the internationalization machinery. - -You'll probably also want to remove ``'django.core.context_processors.i18n'`` -from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting. - -.. note:: - - There is also an independent but related :setting:`USE_L10N` setting that - controls if Django should implement format localization. - - If :setting:`USE_L10N` is set to ``True``, Django will handle numbers times, - and dates in the format of the current locale. That includes representation - of these field types on templates and allowed input formats for dates, - times on model forms. - - See :ref:`format-localization` for more details. - -If you do need internationalization -=================================== - -.. _how-django-discovers-language-preference: - -How Django discovers language preference ----------------------------------------- - -Once you've prepared your translations -- or, if you just want to use the -translations that come with Django -- you'll just need to activate translation -for your app. - -Behind the scenes, Django has a very flexible model of deciding which language -should be used -- installation-wide, for a particular user, or both. - -To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`. -Django uses this language as the default translation -- the final attempt if no -other translator finds a translation. - -If all you want to do is run Django with your native language, and a language -file is available for it, all you need to do is set ``LANGUAGE_CODE``. - -If you want to let each individual user specify which language he or she -prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language -selection based on data from the request. It customizes content for each user. - -To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'`` -to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you -should follow these guidelines: - - * Make sure it's one of the first middlewares installed. - * It should come after ``SessionMiddleware``, because ``LocaleMiddleware`` - makes use of session data. - * If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it. - -For example, your ``MIDDLEWARE_CLASSES`` might look like this:: - - MIDDLEWARE_CLASSES = ( - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.locale.LocaleMiddleware', - 'django.middleware.common.CommonMiddleware', - ) - -(For more on middleware, see the :doc:`middleware documentation -</topics/http/middleware>`.) - -``LocaleMiddleware`` tries to determine the user's language preference by -following this algorithm: - - * First, it looks for a ``django_language`` key in the current user's - session. - - * Failing that, it looks for a cookie. - - .. versionchanged:: 1.0 - - In Django version 0.96 and before, the cookie's name is hard-coded to - ``django_language``. In Django 1,0, The cookie name is set by the - ``LANGUAGE_COOKIE_NAME`` setting. (The default name is - ``django_language``.) - - * Failing that, it looks at the ``Accept-Language`` HTTP header. This - header is sent by your browser and tells the server which language(s) you - prefer, in order by priority. Django tries each language in the header - until it finds one with available translations. - - * Failing that, it uses the global ``LANGUAGE_CODE`` setting. - -.. _locale-middleware-notes: - -Notes: - - * In each of these places, the language preference is expected to be in the - standard :term:`language format<language code>`, as a string. For example, - Brazilian Portuguese is ``pt-br``. - - * If a base language is available but the sublanguage specified is not, - Django uses the base language. For example, if a user specifies ``de-at`` - (Austrian German) but Django only has ``de`` available, Django uses - ``de``. - - * Only languages listed in the :setting:`LANGUAGES` setting can be selected. - If you want to restrict the language selection to a subset of provided - languages (because your application doesn't provide all those languages), - set ``LANGUAGES`` to a list of languages. For example:: - - LANGUAGES = ( - ('de', _('German')), - ('en', _('English')), - ) - - This example restricts languages that are available for automatic - selection to German and English (and any sublanguage, like de-ch or - en-us). - - * If you define a custom ``LANGUAGES`` setting, as explained in the - previous bullet, it's OK to mark the languages as translation strings - -- but use a "dummy" ``ugettext()`` function, not the one in - ``django.utils.translation``. You should *never* import - ``django.utils.translation`` from within your settings file, because that - module in itself depends on the settings, and that would cause a circular - import. - - The solution is to use a "dummy" ``ugettext()`` function. Here's a sample - settings file:: - - ugettext = lambda s: s - - LANGUAGES = ( - ('de', ugettext('German')), - ('en', ugettext('English')), - ) - - With this arrangement, ``django-admin.py makemessages`` will still find - and mark these strings for translation, but the translation won't happen - at runtime -- so you'll have to remember to wrap the languages in the - *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime. - - * The ``LocaleMiddleware`` can only select languages for which there is a - Django-provided base translation. If you want to provide translations - for your application that aren't already in the set of translations - in Django's source tree, you'll want to provide at least a basic - one as described in the :ref:`Locale restrictions<locale-restrictions>` - note. - -Once ``LocaleMiddleware`` determines the user's preference, it makes this -preference available as ``request.LANGUAGE_CODE`` for each -:class:`~django.http.HttpRequest`. Feel free to read this value in your view -code. Here's a simple example:: - - def hello_world(request, count): - if request.LANGUAGE_CODE == 'de-at': - return HttpResponse("You prefer to read Austrian German.") - else: - return HttpResponse("You prefer to read another language.") - -Note that, with static (middleware-less) translation, the language is in -``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's -in ``request.LANGUAGE_CODE``. - -.. _settings file: ../settings/ -.. _middleware documentation: ../middleware/ -.. _session: ../sessions/ -.. _request object: ../request_response/#httprequest-objects - -How Django discovers translations ---------------------------------- - -As described in :ref:`using-translations-in-your-own-projects`, -at runtime, Django looks for translations by following this algorithm: - - * First, it looks for a ``locale`` directory in the directory containing - your settings file. - * Second, it looks for a ``locale`` directory in the project directory. - * Third, it looks for a ``locale`` directory in each of the installed apps. - It does this in the reverse order of INSTALLED_APPS - * Finally, it checks the Django-provided base translation in - ``django/conf/locale``. - -In all cases the name of the directory containing the translation is expected to -be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``, -etc. diff --git a/parts/django/docs/topics/i18n/index.txt b/parts/django/docs/topics/i18n/index.txt deleted file mode 100644 index 9c25192..0000000 --- a/parts/django/docs/topics/i18n/index.txt +++ /dev/null @@ -1,113 +0,0 @@ -===================================== -Internationalization and localization -===================================== - -Overview -======== - -Django has full support for internationalization of text in code and -templates, and format localization of dates and numbers. Here's how it works. - -Essentially, Django does two things: - - * It allows developers and template authors to specify which parts of - their apps should be translatable. - * It uses these hooks to translate Web apps for particular users according - to their language preferences. - -The complete process can be seen as divided in three stages. It is also possible -to identify an identical number of roles with very well defined responsibilities -associated with each of these tasks (although it's perfectly normal if you -find yourself performing more than one of these roles): - - * For application authors wishing to make sure their Django apps can be - used in different locales: :doc:`/topics/i18n/internationalization`. - * For translators wanting to translate Django apps: :doc:`/topics/i18n/localization`. - * For system administrators/final users setting up internationalized apps or - developers integrating third party apps: :doc:`/topics/i18n/deployment`. - -.. toctree:: - :hidden: - :maxdepth: 1 - - internationalization - localization - deployment - -.. _ seealso:: - -For more general information about the topic, see the `GNU gettext documentation`_ -and the `Wikipedia article`_. - -.. _GNU gettext documentation: http://www.gnu.org/software/gettext/manual/gettext.html#Concepts -.. _Wikipedia article: http://en.wikipedia.org/wiki/Internationalization_and_localization - -Glossary -======== - -First lets define some terms that will help us to handle a common language: - -.. glossary:: - - locale name - A locale name, either a language specification of the form ``ll`` or a - combined language and country specification of the form ``ll_CC``. - Examples: ``it``, ``de_AT``, ``es``, ``pt_BR``. Note the underscore in - some of them and the case of the part located to its right. - - language code - Represents the name of a language. Browsers send the names of the - languages they accept in the ``Accept-Language`` HTTP header using this - format. Examples: ``it``, ``de-at``, ``es``, ``pt-br``. Note the ``-`` - separator. - - message file - A message file is a plain-text file, representing a single language, - that contains all available :term:`translation strings - <translation string>` and how they should be represented in the given - language. Message files have a ``.po`` file extension. - - translation string - A literal that can be translated. - -.. _specialties-of-django-i18n: - -Specialties of Django translation -================================= - -Django's translation machinery uses the standard ``gettext`` module that comes -with Python. If you know ``gettext``, you might note these specialties in the -way Django does translation: - - * The string domain is ``django`` or ``djangojs``. This string domain is - used to differentiate between different programs that store their data - in a common message-file library (usually ``/usr/share/locale/``). The - ``django`` domain is used for python and template translation strings - and is loaded into the global translation catalogs. The ``djangojs`` - domain is only used for JavaScript translation catalogs to make sure - that those are as small as possible. - * Django doesn't use ``xgettext`` alone. It uses Python wrappers around - ``xgettext`` and ``msgfmt``. This is mostly for convenience. - -.. _technical-messages: - -Django technical message IDs ----------------------------- - -.. versionchanged:: 1.2 - Starting with Django 1.2, technical message IDs are being replaced by :ref:`format-localization` - -Django uses technical message IDs to translate date formats and time formats. -Technical message IDs are :term:`translation strings <translation string>` and -can be easily recognized; they're all upper case. You don't translate the -message ID as with other translation strings, you provide the correct local -variant on the provided English value. The format is identical to the format -strings used by the ``now`` template tag. - -For example, with ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``), -this would be the format string that you want to use in your language. A Django -contributor localizing it to Spanish probably would provide a ``"j N Y P"`` -"translation" for it in the relevant ``django.po`` file:: - - msgid "DATETIME_FORMAT" - msgstr "j N Y P" diff --git a/parts/django/docs/topics/i18n/internationalization.txt b/parts/django/docs/topics/i18n/internationalization.txt deleted file mode 100644 index b6847ea..0000000 --- a/parts/django/docs/topics/i18n/internationalization.txt +++ /dev/null @@ -1,624 +0,0 @@ -==================== -Internationalization -==================== - -Overview -======== - -The goal of internationalization is to allow a single Web application to offer -its content and functionality in multiple languages and locales. - -For text translations, you, the Django developer, can accomplish this goal by -adding a minimal amount of hooks to your Python and templates. These hooks -are called **translation strings**. They tell Django: "This text should be -translated into the end user's language, if a translation for this text is -available in that language." It's your responsibility to mark translatable -strings; the system can only translate strings it knows about. - -Django takes care of using these hooks to translate Web apps, on the fly, -according to users' language preferences. - -Specifying translation strings: In Python code -============================================== - -Standard translation --------------------- - -Specify a translation string by using the function ``ugettext()``. It's -convention to import this as a shorter alias, ``_``, to save typing. - -.. note:: - Python's standard library ``gettext`` module installs ``_()`` into the - global namespace, as an alias for ``gettext()``. In Django, we have chosen - not to follow this practice, for a couple of reasons: - - 1. For international character set (Unicode) support, ``ugettext()`` is - more useful than ``gettext()``. Sometimes, you should be using - ``ugettext_lazy()`` as the default translation method for a particular - file. Without ``_()`` in the global namespace, the developer has to - think about which is the most appropriate translation function. - - 2. The underscore character (``_``) is used to represent "the previous - result" in Python's interactive shell and doctest tests. Installing a - global ``_()`` function causes interference. Explicitly importing - ``ugettext()`` as ``_()`` avoids this problem. - -.. highlightlang:: python - -In this example, the text ``"Welcome to my site."`` is marked as a translation -string:: - - from django.utils.translation import ugettext as _ - - def my_view(request): - output = _("Welcome to my site.") - return HttpResponse(output) - -Obviously, you could code this without using the alias. This example is -identical to the previous one:: - - from django.utils.translation import ugettext - - def my_view(request): - output = ugettext("Welcome to my site.") - return HttpResponse(output) - -Translation works on computed values. This example is identical to the previous -two:: - - def my_view(request): - words = ['Welcome', 'to', 'my', 'site.'] - output = _(' '.join(words)) - return HttpResponse(output) - -Translation works on variables. Again, here's an identical example:: - - def my_view(request): - sentence = 'Welcome to my site.' - output = _(sentence) - return HttpResponse(output) - -(The caveat with using variables or computed values, as in the previous two -examples, is that Django's translation-string-detecting utility, -``django-admin.py makemessages``, won't be able to find these strings. More on -``makemessages`` later.) - -The strings you pass to ``_()`` or ``ugettext()`` can take placeholders, -specified with Python's standard named-string interpolation syntax. Example:: - - def my_view(request, m, d): - output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d} - return HttpResponse(output) - -This technique lets language-specific translations reorder the placeholder -text. For example, an English translation may be ``"Today is November 26."``, -while a Spanish translation may be ``"Hoy es 26 de Noviembre."`` -- with the -the month and the day placeholders swapped. - -For this reason, you should use named-string interpolation (e.g., ``%(day)s``) -instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you -have more than a single parameter. If you used positional interpolation, -translations wouldn't be able to reorder placeholder text. - -Marking strings as no-op ------------------------- - -Use the function ``django.utils.translation.ugettext_noop()`` to mark a string -as a translation string without translating it. The string is later translated -from a variable. - -Use this if you have constant strings that should be stored in the source -language because they are exchanged over systems or users -- such as strings in -a database -- but should be translated at the last possible point in time, such -as when the string is presented to the user. - -Pluralization -------------- - -Use the function ``django.utils.translation.ungettext()`` to specify pluralized -messages. - -``ungettext`` takes three arguments: the singular translation string, the plural -translation string and the number of objects. - -This function is useful when you need your Django application to be localizable -to languages where the number and complexity of `plural forms -<http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is -greater than the two forms used in English ('object' for the singular and -'objects' for all the cases where ``count`` is different from zero, irrespective -of its value.) - -For example:: - - from django.utils.translation import ungettext - def hello_world(request, count): - page = ungettext('there is %(count)d object', 'there are %(count)d objects', count) % { - 'count': count, - } - return HttpResponse(page) - -In this example the number of objects is passed to the translation languages as -the ``count`` variable. - -Lets see a slightly more complex usage example:: - - from django.utils.translation import ungettext - - count = Report.objects.count() - if count == 1: - name = Report._meta.verbose_name - else: - name = Report._meta.verbose_name_plural - - text = ungettext( - 'There is %(count)d %(name)s available.', - 'There are %(count)d %(name)s available.', - count - ) % { - 'count': count, - 'name': name - } - -Here we reuse localizable, hopefully already translated literals (contained in -the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for -other parts of the sentence so all of it is consistently based on the -cardinality of the elements at play. - -.. _pluralization-var-notes: - -.. note:: - - When using this technique, make sure you use a single name for every - extrapolated variable included in the literal. In the example above note how - we used the ``name`` Python variable in both translation strings. This - example would fail:: - - from django.utils.translation import ungettext - from myapp.models import Report - - count = Report.objects.count() - d = { - 'count': count, - 'name': Report._meta.verbose_name, - 'plural_name': Report._meta.verbose_name_plural - } - text = ungettext( - 'There is %(count)d %(name)s available.', - 'There are %(count)d %(plural_name)s available.', - count - ) % d - - You would get a ``a format specification for argument 'name', as in - 'msgstr[0]', doesn't exist in 'msgid'`` error when running - ``django-admin.py compilemessages``. - -.. _lazy-translations: - -Lazy translation ----------------- - -Use the function ``django.utils.translation.ugettext_lazy()`` to translate -strings lazily -- when the value is accessed rather than when the -``ugettext_lazy()`` function is called. - -For example, to translate a model's ``help_text``, do the following:: - - from django.utils.translation import ugettext_lazy - - class MyThing(models.Model): - name = models.CharField(help_text=ugettext_lazy('This is the help text')) - -In this example, ``ugettext_lazy()`` stores a lazy reference to the string -- -not the actual translation. The translation itself will be done when the string -is used in a string context, such as template rendering on the Django admin -site. - -The result of a ``ugettext_lazy()`` call can be used wherever you would use a -unicode string (an object with type ``unicode``) in Python. If you try to use -it where a bytestring (a ``str`` object) is expected, things will not work as -expected, since a ``ugettext_lazy()`` object doesn't know how to convert -itself to a bytestring. You can't use a unicode string inside a bytestring, -either, so this is consistent with normal Python behavior. For example:: - - # This is fine: putting a unicode proxy into a unicode string. - u"Hello %s" % ugettext_lazy("people") - - # This will not work, since you cannot insert a unicode object - # into a bytestring (nor can you insert our unicode proxy there) - "Hello %s" % ugettext_lazy("people") - -If you ever see output that looks like ``"hello -<django.utils.functional...>"``, you have tried to insert the result of -``ugettext_lazy()`` into a bytestring. That's a bug in your code. - -If you don't like the verbose name ``ugettext_lazy``, you can just alias it as -``_`` (underscore), like so:: - - from django.utils.translation import ugettext_lazy as _ - - class MyThing(models.Model): - name = models.CharField(help_text=_('This is the help text')) - -Always use lazy translations in :doc:`Django models </topics/db/models>`. -Field names and table names should be marked for translation (otherwise, they -won't be translated in the admin interface). This means writing explicit -``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class, -though, rather than relying on Django's default determination of -``verbose_name`` and ``verbose_name_plural`` by looking at the model's class -name:: - - from django.utils.translation import ugettext_lazy as _ - - class MyThing(models.Model): - name = models.CharField(_('name'), help_text=_('This is the help text')) - class Meta: - verbose_name = _('my thing') - verbose_name_plural = _('mythings') - -Working with lazy translation objects -------------------------------------- - -.. highlightlang:: python - -Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models -and utility functions is a common operation. When you're working with these -objects elsewhere in your code, you should ensure that you don't accidentally -convert them to strings, because they should be converted as late as possible -(so that the correct locale is in effect). This necessitates the use of a -couple of helper functions. - -Joining strings: string_concat() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Standard Python string joins (``''.join([...])``) will not work on lists -containing lazy translation objects. Instead, you can use -``django.utils.translation.string_concat()``, which creates a lazy object that -concatenates its contents *and* converts them to strings only when the result -is included in a string. For example:: - - from django.utils.translation import string_concat - ... - name = ugettext_lazy(u'John Lennon') - instrument = ugettext_lazy(u'guitar') - result = string_concat(name, ': ', instrument) - -In this case, the lazy translations in ``result`` will only be converted to -strings when ``result`` itself is used in a string (usually at template -rendering time). - -The allow_lazy() decorator -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Django offers many utility functions (particularly in ``django.utils``) that -take a string as their first argument and do something to that string. These -functions are used by template filters as well as directly in other code. - -If you write your own similar functions and deal with translations, you'll -face the problem of what to do when the first argument is a lazy translation -object. You don't want to convert it to a string immediately, because you might -be using this function outside of a view (and hence the current thread's locale -setting will not be correct). - -For cases like this, use the ``django.utils.functional.allow_lazy()`` -decorator. It modifies the function so that *if* it's called with a lazy -translation as the first argument, the function evaluation is delayed until it -needs to be converted to a string. - -For example:: - - from django.utils.functional import allow_lazy - - def fancy_utility_function(s, ...): - # Do some conversion on string 's' - ... - fancy_utility_function = allow_lazy(fancy_utility_function, unicode) - -The ``allow_lazy()`` decorator takes, in addition to the function to decorate, -a number of extra arguments (``*args``) specifying the type(s) that the -original function can return. Usually, it's enough to include ``unicode`` here -and ensure that your function returns only Unicode strings. - -Using this decorator means you can write your function and assume that the -input is a proper string, then add support for lazy translation objects at the -end. - -.. _specifying-translation-strings-in-template-code: - -Specifying translation strings: In template code -================================================ - -.. highlightlang:: html+django - -Translations in :doc:`Django templates </topics/templates>` uses two template -tags and a slightly different syntax than in Python code. To give your template -access to these tags, put ``{% load i18n %}`` toward the top of your template. - -``trans`` template tag ----------------------- - -The ``{% trans %}`` template tag translates either a constant string -(enclosed in single or double quotes) or variable content:: - - <title>{% trans "This is the title." %}</title> - <title>{% trans myvar %}</title> - -If the ``noop`` option is present, variable lookup still takes place but the -translation is skipped. This is useful when "stubbing out" content that will -require translation in the future:: - - <title>{% trans "myvar" noop %}</title> - -Internally, inline translations use an ``ugettext`` call. - -In case a template var (``myvar`` above) is passed to the tag, the tag will -first resolve such variable to a string at run-time and then look up that -string in the message catalogs. - -It's not possible to mix a template variable inside a string within ``{% trans -%}``. If your translations require strings with variables (placeholders), use -``{% blocktrans %}`` instead. - -``blocktrans`` template tag ---------------------------- - -Contrarily to the ``trans`` tag, the ``blocktrans`` tag allows you to mark -complex sentences consisting of literals and variable content for translation -by making use of placeholders:: - - {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %} - -To translate a template expression -- say, accessing object attributes or -using template filters -- you need to bind the expression to a local variable -for use within the translation block. Examples:: - - {% blocktrans with article.price as amount %} - That will cost $ {{ amount }}. - {% endblocktrans %} - - {% blocktrans with value|filter as myvar %} - This will have {{ myvar }} inside. - {% endblocktrans %} - -If you need to bind more than one expression inside a ``blocktrans`` tag, -separate the pieces with ``and``:: - - {% blocktrans with book|title as book_t and author|title as author_t %} - This is {{ book_t }} by {{ author_t }} - {% endblocktrans %} - -This tag also provides for pluralization. To use it: - - * Designate and bind a counter value with the name ``count``. This value will - be the one used to select the right plural form. - - * Specify both the singular and plural forms separating them with the - ``{% plural %}`` tag within the ``{% blocktrans %}`` and - ``{% endblocktrans %}`` tags. - -An example:: - - {% blocktrans count list|length as counter %} - There is only one {{ name }} object. - {% plural %} - There are {{ counter }} {{ name }} objects. - {% endblocktrans %} - -A more complex example:: - - {% blocktrans with article.price as amount count i.length as years %} - That will cost $ {{ amount }} per year. - {% plural %} - That will cost $ {{ amount }} per {{ years }} years. - {% endblocktrans %} - -When you use both the pluralization feature and bind values to local variables -in addition to the counter value, keep in mind that the ``blocktrans`` -construct is internally converted to an ``ungettext`` call. This means the -same :ref:`notes regarding ungettext variables <pluralization-var-notes>` -apply. - -.. _template-translation-vars: - -Other tags ----------- - -Each ``RequestContext`` has access to three translation-specific variables: - - * ``LANGUAGES`` is a list of tuples in which the first element is the - :term:`language code` and the second is the language name (translated into - the currently active locale). - - * ``LANGUAGE_CODE`` is the current user's preferred language, as a string. - Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`.) - - * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a - right-to-left language, e.g.: Hebrew, Arabic. If False it's a - left-to-right language, e.g.: English, French, German etc. - -If you don't use the ``RequestContext`` extension, you can get those values with -three tags:: - - {% get_current_language as LANGUAGE_CODE %} - {% get_available_languages as LANGUAGES %} - {% get_current_language_bidi as LANGUAGE_BIDI %} - -These tags also require a ``{% load i18n %}``. - -Translation hooks are also available within any template block tag that accepts -constant strings. In those cases, just use ``_()`` syntax to specify a -translation string:: - - {% some_special_tag _("Page not found") value|yesno:_("yes,no") %} - -In this case, both the tag and the filter will see the already-translated -string, so they don't need to be aware of translations. - -.. note:: - In this example, the translation infrastructure will be passed the string - ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The - translated string will need to contain the comma so that the filter - parsing code knows how to split up the arguments. For example, a German - translator might translate the string ``"yes,no"`` as ``"ja,nein"`` - (keeping the comma intact). - -.. _Django templates: ../templates_python/ - -Specifying translation strings: In JavaScript code -================================================== - -Adding translations to JavaScript poses some problems: - - * JavaScript code doesn't have access to a ``gettext`` implementation. - - * JavaScript code doesn't have access to .po or .mo files; they need to be - delivered by the server. - - * The translation catalogs for JavaScript should be kept as small as - possible. - -Django provides an integrated solution for these problems: It passes the -translations into JavaScript, so you can call ``gettext``, etc., from within -JavaScript. - -The ``javascript_catalog`` view -------------------------------- - -.. module:: django.views.i18n - -.. function:: javascript_catalog(request, domain='djangojs', packages=None) - -The main solution to these problems is the :meth:`django.views.i18n.javascript_catalog` -view, which sends out a JavaScript code library with functions that mimic the -``gettext`` interface, plus an array of translation strings. Those translation -strings are taken from the application, project or Django core, according to what -you specify in either the info_dict or the URL. - -You hook it up like this:: - - js_info_dict = { - 'packages': ('your.app.package',), - } - - urlpatterns = patterns('', - (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), - ) - -Each string in ``packages`` should be in Python dotted-package syntax (the -same format as the strings in ``INSTALLED_APPS``) and should refer to a package -that contains a ``locale`` directory. If you specify multiple packages, all -those catalogs are merged into one catalog. This is useful if you have -JavaScript that uses strings from different applications. - -By default, the view uses the ``djangojs`` gettext domain. This can be -changed by altering the ``domain`` argument. - -You can make the view dynamic by putting the packages into the URL pattern:: - - urlpatterns = patterns('', - (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'), - ) - -With this, you specify the packages as a list of package names delimited by '+' -signs in the URL. This is especially useful if your pages use code from -different apps and this changes often and you don't want to pull in one big -catalog file. As a security measure, these values can only be either -``django.conf`` or any package from the ``INSTALLED_APPS`` setting. - -Using the JavaScript translation catalog ----------------------------------------- - -To use the catalog, just pull in the dynamically generated script like this:: - - <script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script> - -This uses reverse URL lookup to find the URL of the JavaScript catalog view. -When the catalog is loaded, your JavaScript code can use the standard -``gettext`` interface to access it:: - - document.write(gettext('this is to be translated')); - -There is also an ``ngettext`` interface:: - - var object_cnt = 1 // or 0, or 2, or 3, ... - s = ngettext('literal for the singular case', - 'literal for the plural case', object_cnt); - -and even a string interpolation function:: - - function interpolate(fmt, obj, named); - -The interpolation syntax is borrowed from Python, so the ``interpolate`` -function supports both positional and named interpolation: - - * Positional interpolation: ``obj`` contains a JavaScript Array object - whose elements values are then sequentially interpolated in their - corresponding ``fmt`` placeholders in the same order they appear. - For example:: - - fmts = ngettext('There is %s object. Remaining: %s', - 'There are %s objects. Remaining: %s', 11); - s = interpolate(fmts, [11, 20]); - // s is 'There are 11 objects. Remaining: 20' - - * Named interpolation: This mode is selected by passing the optional - boolean ``named`` parameter as true. ``obj`` contains a JavaScript - object or associative array. For example:: - - d = { - count: 10, - total: 50 - }; - - fmts = ngettext('Total: %(total)s, there is %(count)s object', - 'there are %(count)s of a total of %(total)s objects', d.count); - s = interpolate(fmts, d, true); - -You shouldn't go over the top with string interpolation, though: this is still -JavaScript, so the code has to make repeated regular-expression substitutions. -This isn't as fast as string interpolation in Python, so keep it to those -cases where you really need it (for example, in conjunction with ``ngettext`` -to produce proper pluralizations). - -The ``set_language`` redirect view -================================== - -.. function:: set_language(request) - -As a convenience, Django comes with a view, :meth:`django.views.i18n.set_language`, -that sets a user's language preference and redirects back to the previous page. - -Activate this view by adding the following line to your URLconf:: - - (r'^i18n/', include('django.conf.urls.i18n')), - -(Note that this example makes the view available at ``/i18n/setlang/``.) - -The view expects to be called via the ``POST`` method, with a ``language`` -parameter set in request. If session support is enabled, the view -saves the language choice in the user's session. Otherwise, it saves the -language choice in a cookie that is by default named ``django_language``. -(The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.) - -After setting the language choice, Django redirects the user, following this -algorithm: - - * Django looks for a ``next`` parameter in the ``POST`` data. - * If that doesn't exist, or is empty, Django tries the URL in the - ``Referrer`` header. - * If that's empty -- say, if a user's browser suppresses that header -- - then the user will be redirected to ``/`` (the site root) as a fallback. - -Here's example HTML template code: - -.. code-block:: html+django - - <form action="/i18n/setlang/" method="post"> - {% csrf_token %} - <input name="next" type="hidden" value="/next/page/" /> - <select name="language"> - {% for lang in LANGUAGES %} - <option value="{{ lang.0 }}">{{ lang.1 }}</option> - {% endfor %} - </select> - <input type="submit" value="Go" /> - </form> diff --git a/parts/django/docs/topics/i18n/localization.txt b/parts/django/docs/topics/i18n/localization.txt deleted file mode 100644 index 38d74e6..0000000 --- a/parts/django/docs/topics/i18n/localization.txt +++ /dev/null @@ -1,317 +0,0 @@ -============ -Localization -============ - -This document covers two localization-related topics: `Creating language -files`_ and `locale aware date, time and numbers input/output in forms`_ - -.. _`Creating language files`: how-to-create-language-files_ -.. _`locale aware date, time and numbers input/output in forms`: format-localization_ - -.. seealso:: - - The :doc:`/howto/i18n` document included with the Django HOW-TO documents collection. - -.. _how-to-create-language-files: - -How to create language files -============================ - -Once the string literals of an application have been tagged for later -translation, the translation themselves need to be written (or obtained). Here's -how that works. - -.. _locale-restrictions: - -.. admonition:: Locale restrictions - - Django does not support localizing your application into a locale for which - Django itself has not been translated. In this case, it will ignore your - translation files. If you were to try this and Django supported it, you - would inevitably see a mixture of translated strings (from your application) - and English strings (from Django itself). If you want to support a locale - for your application that is not already part of Django, you'll need to make - at least a minimal translation of the Django core. - - A good starting point is to copy the Django English ``.po`` file and to - translate at least some :term:`translation strings <translation string>`. - -Message files -------------- - -The first step is to create a :term:`message file` for a new language. A message -file is a plain-text file, representing a single language, that contains all -available translation strings and how they should be represented in the given -language. Message files have a ``.po`` file extension. - -Django comes with a tool, ``django-admin.py makemessages``, that automates the -creation and upkeep of these files. - -.. admonition:: A note to Django veterans - - The old tool ``bin/make-messages.py`` has been moved to the command - ``django-admin.py makemessages`` to provide consistency throughout Django. - -.. admonition:: Gettext utilities - - The ``makemessages`` command (and ``compilemessages`` discussed later) use - commands from the GNU gettext toolset: ``xgettext``, ``msgfmt``, - ``msgmerge`` and ``msguniq``. - - .. versionchanged:: 1.2 - - The minimum version of the ``gettext`` utilities supported is 0.15. - -To create or update a message file, run this command:: - - django-admin.py makemessages -l de - -...where ``de`` is the language code for the message file you want to create. -The language code, in this case, is in :term:`locale format<locale name>`. For -example, it's ``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian -German. - -The script should be run from one of two places: - - * The root directory of your Django project. - * The root directory of your Django app. - -The script runs over your project source tree or your application source tree -and pulls out all strings marked for translation. It creates (or updates) a -message file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de`` -example, the file will be ``locale/de/LC_MESSAGES/django.po``. - -By default ``django-admin.py makemessages`` examines every file that has the -``.html`` file extension. In case you want to override that default, use the -``--extension`` or ``-e`` option to specify the file extensions to examine:: - - django-admin.py makemessages -l de -e txt - -Separate multiple extensions with commas and/or use ``-e`` or ``--extension`` -multiple times:: - - django-admin.py makemessages -l de -e html,txt -e xml - -When :ref:`creating message files from JavaScript source code -<creating-message-files-from-js-code>` you need to use the special 'djangojs' -domain, **not** ``-e js``. - -.. admonition:: No gettext? - - If you don't have the ``gettext`` utilities installed, ``django-admin.py - makemessages`` will create empty files. If that's the case, either install - the ``gettext`` utilities or just copy the English message file - (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting - point; it's just an empty translation file. - -.. admonition:: Working on Windows? - - If you're using Windows and need to install the GNU gettext utilities so - ``django-admin makemessages`` works see :ref:`gettext_on_windows` for more - information. - -The format of ``.po`` files is straightforward. Each ``.po`` file contains a -small bit of metadata, such as the translation maintainer's contact -information, but the bulk of the file is a list of **messages** -- simple -mappings between translation strings and the actual translated text for the -particular language. - -For example, if your Django app contained a translation string for the text -``"Welcome to my site."``, like so:: - - _("Welcome to my site.") - -...then ``django-admin.py makemessages`` will have created a ``.po`` file -containing the following snippet -- a message:: - - #: path/to/python/module.py:23 - msgid "Welcome to my site." - msgstr "" - -A quick explanation: - - * ``msgid`` is the translation string, which appears in the source. Don't - change it. - * ``msgstr`` is where you put the language-specific translation. It starts - out empty, so it's your responsibility to change it. Make sure you keep - the quotes around your translation. - * As a convenience, each message includes, in the form of a comment line - prefixed with ``#`` and located above the ``msgid`` line, the filename and - line number from which the translation string was gleaned. - -Long messages are a special case. There, the first string directly after the -``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be -written over the next few lines as one string per line. Those strings are -directly concatenated. Don't forget trailing spaces within the strings; -otherwise, they'll be tacked together without whitespace! - -.. admonition:: Mind your charset - - When creating a PO file with your favorite text editor, first edit - the charset line (search for ``"CHARSET"``) and set it to the charset - you'll be using to edit the content. Due to the way the ``gettext`` tools - work internally and because we want to allow non-ASCII source strings in - Django's core and your applications, you **must** use UTF-8 as the encoding - for your PO file. This means that everybody will be using the same - encoding, which is important when Django processes the PO files. - -To reexamine all source code and templates for new translation strings and -update all message files for **all** languages, run this:: - - django-admin.py makemessages -a - -Compiling message files ------------------------ - -After you create your message file -- and each time you make changes to it -- -you'll need to compile it into a more efficient form, for use by ``gettext``. -Do this with the ``django-admin.py compilemessages`` utility. - -This tool runs over all available ``.po`` files and creates ``.mo`` files, which -are binary files optimized for use by ``gettext``. In the same directory from -which you ran ``django-admin.py makemessages``, run ``django-admin.py -compilemessages`` like this:: - - django-admin.py compilemessages - -That's it. Your translations are ready for use. - -.. admonition:: A note to Django veterans - - The old tool ``bin/compile-messages.py`` has been moved to the command - ``django-admin.py compilemessages`` to provide consistency throughout - Django. - -.. admonition:: Working on Windows? - - If you're using Windows and need to install the GNU gettext utilities so - ``django-admin compilemessages`` works see :ref:`gettext_on_windows` for more - information. - -.. admonition:: .po files: Encoding and BOM usage. - - Django only supports ``.po`` files encoded in UTF-8 and without any BOM - (Byte Order Mark) so if your text editor adds such marks to the beginning of - files by default then you will need to reconfigure it. - -.. _creating-message-files-from-js-code: - -Creating message files from JavaScript source code -================================================== - -You create and update the message files the same way as the other Django message -files -- with the ``django-admin.py makemessages`` tool. The only difference is -you need to provide a ``-d djangojs`` parameter, like this:: - - django-admin.py makemessages -d djangojs -l de - -This would create or update the message file for JavaScript for German. -After updating message files, just run ``django-admin.py compilemessages`` -the same way as you do with normal Django message files. - -.. _gettext_on_windows: - -``gettext`` on Windows -====================== - -This is only needed for people who either want to extract message IDs or compile -message files (``.po``). Translation work itself just involves editing existing -files of this type, but if you want to create your own message files, or want to -test or compile a changed message file, you will need the ``gettext`` utilities: - - * Download the following zip files from the GNOME servers - http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one - of its mirrors_ - - * ``gettext-runtime-X.zip`` - * ``gettext-tools-X.zip`` - - ``X`` is the version number, we are requiring ``0.15`` or higher. - - * Extract the contents of the ``bin\`` directories in both files to the - same folder on your system (i.e. ``C:\Program Files\gettext-utils``) - - * Update the system PATH: - - * ``Control Panel > System > Advanced > Environment Variables``. - * In the ``System variables`` list, click ``Path``, click ``Edit``. - * Add ``;C:\Program Files\gettext-utils\bin`` at the end of the - ``Variable value`` field. - -.. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS - -You may also use ``gettext`` binaries you have obtained elsewhere, so long as -the ``xgettext --version`` command works properly. Do not attempt to use Django -translation utilities with a ``gettext`` package if the command ``xgettext ---version`` entered at a Windows command prompt causes a popup window saying -"xgettext.exe has generated errors and will be closed by Windows". - -.. _format-localization: - -Format localization -=================== - -.. versionadded:: 1.2 - -Django's formatting system is disabled by default. To enable it, it's -necessary to set :setting:`USE_L10N = True <USE_L10N>` in your settings file. - -.. note:: - The default :file:`settings.py` file created by - :djadmin:`django-admin.py startproject <startproject>` includes - :setting:`USE_L10N = True <USE_L10N>` for convenience. - -When using Django's formatting system, dates and numbers on templates will be -displayed using the format specified for the current locale. Two users -accessing the same content, but in different language, will see date and -number fields formatted in different ways, depending on the format for their -current locale. - -Django will also use localized formats when parsing data in forms. That means -Django uses different formats for different locales when guessing the format -used by the user when inputting data on forms. - -.. note:: - Django uses different formats for displaying data to those it uses for - parsing data. Most notably, the formats for parsing dates can't use the - ``%a`` (abbreviated weekday name), ``%A`` (full weekday name), - ``%b`` (abbreviated month name), ``%B`` (full month name), - or ``%p`` (AM/PM). - -To enable a form field to localize input and output data simply use its -``localize`` argument:: - - class CashRegisterForm(forms.Form): - product = forms.CharField() - revenue = forms.DecimalField(max_digits=4, decimal_places=2, localize=True) - -Creating custom format files ----------------------------- - -Django provides format definitions for many locales, but sometimes you might -want to create your own, because a format files doesn't exist for your locale, -or because you want to overwrite some of the values. - -To use custom formats, first thing to do, is to specify the path where you'll -place format files. To do that, just set your :setting:`FORMAT_MODULE_PATH` -setting to the path (in the format ``'foo.bar.baz``) where format files -will exists. - -Files are not placed directly in this directory, but in a directory named as -the locale, and must be named ``formats.py``. - -To customize the English formats, a structure like this would be needed:: - - mysite/ - formats/ - __init__.py - en/ - __init__.py - formats.py - -where :file:`formats.py` contains custom format definitions. For example:: - - THOUSAND_SEPARATOR = ' ' - -to use a space as a thousand separator, instead of the default for English, -a comma. diff --git a/parts/django/docs/topics/index.txt b/parts/django/docs/topics/index.txt deleted file mode 100644 index 4c6b7fc..0000000 --- a/parts/django/docs/topics/index.txt +++ /dev/null @@ -1,27 +0,0 @@ -Using Django -============ - -Introductions to all the key parts of Django you'll need to know: - -.. toctree:: - :maxdepth: 1 - - install - db/index - http/index - forms/index - forms/modelforms - templates - generic-views - files - testing - auth - cache - conditional-view-processing - email - i18n/index - pagination - serialization - settings - signals - diff --git a/parts/django/docs/topics/install.txt b/parts/django/docs/topics/install.txt deleted file mode 100644 index 20c8074..0000000 --- a/parts/django/docs/topics/install.txt +++ /dev/null @@ -1,298 +0,0 @@ -===================== -How to install Django -===================== - -This document will get you up and running with Django. - -Install Python -============== - -Being a Python Web framework, Django requires Python. - -It works with any Python version from 2.4 to 2.7 (due to backwards -incompatibilities in Python 3.0, Django does not currently work with -Python 3.0; see :doc:`the Django FAQ </faq/install>` for more -information on supported Python versions and the 3.0 transition). - -Get Python at http://www.python.org. If you're running Linux or Mac OS X, you -probably already have it installed. - -.. admonition:: Django on Jython - - If you use Jython_ (a Python implementation for the Java platform), you'll - need to follow a few additional steps. See :doc:`/howto/jython` for details. - -.. _jython: http://jython.org/ - -Install Apache and mod_wsgi -============================= - -If you just want to experiment with Django, skip ahead to the next section; -Django includes a lightweight Web server you can use for testing, so you won't -need to set up Apache until you're ready to deploy Django in production. - -If you want to use Django on a production site, use Apache with `mod_wsgi`_. -mod_wsgi is similar to mod_perl -- it embeds Python within Apache and loads -Python code into memory when the server starts. Code stays in memory throughout -the life of an Apache process, which leads to significant performance gains over -other server arrangements. Make sure you have Apache installed, with the -mod_wsgi module activated. Django will work with any version of Apache that -supports mod_wsgi. - -See :doc:`How to use Django with mod_wsgi </howto/deployment/modwsgi>` for -information on how to configure mod_wsgi once you have it installed. - -If you can't use mod_wsgi for some reason, fear not: Django supports many other -deployment options. A great second choice is :doc:`mod_python -</howto/deployment/modpython>`, the predecessor to mod_wsgi. Additionally, Django -follows the WSGI_ spec, which allows it to run on a variety of server platforms. -See the `server-arrangements wiki page`_ for specific installation instructions -for each platform. - -.. _Apache: http://httpd.apache.org/ -.. _mod_wsgi: http://code.google.com/p/modwsgi/ -.. _WSGI: http://www.python.org/dev/peps/pep-0333/ -.. _server-arrangements wiki page: http://code.djangoproject.com/wiki/ServerArrangements - -.. _database-installation: - -Get your database running -========================= - -If you plan to use Django's database API functionality, you'll need to make -sure a database server is running. Django supports many different database -servers and is officially supported with PostgreSQL_, MySQL_, Oracle_ and -SQLite_ (although SQLite doesn't require a separate server to be running). - -In addition to the officially supported databases, there are backends provided -by 3rd parties that allow you to use other databases with Django: - -* `Sybase SQL Anywhere`_ -* `IBM DB2`_ -* `Microsoft SQL Server 2005`_ -* Firebird_ -* ODBC_ - -The Django versions and ORM features supported by these unofficial backends -vary considerably. Queries regarding the specific capabilities of these -unofficial backends, along with any support queries, should be directed to the -support channels provided by each 3rd party project. - -In addition to a database backend, you'll need to make sure your Python -database bindings are installed. - -* If you're using PostgreSQL, you'll need the psycopg_ package. Django supports - both version 1 and 2. (When you configure Django's database layer, specify - either ``postgresql`` [for version 1] or ``postgresql_psycopg2`` [for version 2].) - You might want to refer to our :ref:`PostgreSQL notes <postgresql-notes>` for - further technical details specific to this database. - - If you're on Windows, check out the unofficial `compiled Windows version`_. - -* If you're using MySQL, you'll need MySQLdb_, version 1.2.1p2 or higher. You - will also want to read the database-specific :ref:`notes for the MySQL - backend <mysql-notes>`. - -* If you're using SQLite and Python 2.4, you'll need pysqlite_. Use version - 2.0.3 or higher. Python 2.5 ships with an SQLite wrapper in the standard - library, so you don't need to install anything extra in that case. Please - read the :ref:`SQLite backend notes <sqlite-notes>`. - -* If you're using Oracle, you'll need a copy of cx_Oracle_, but please - read the database-specific :ref:`notes for the Oracle backend <oracle-notes>` - for important information regarding supported versions of both Oracle and - ``cx_Oracle``. - -* If you're using an unofficial 3rd party backend, please consult the - documentation provided for any additional requirements. - -If you plan to use Django's ``manage.py syncdb`` command to -automatically create database tables for your models, you'll need to -ensure that Django has permission to create and alter tables in the -database you're using; if you plan to manually create the tables, you -can simply grant Django ``SELECT``, ``INSERT``, ``UPDATE`` and -``DELETE`` permissions. On some databases, Django will need -``ALTER TABLE`` privileges during ``syncdb`` but won't issue -``ALTER TABLE`` statements on a table once ``syncdb`` has created it. - -If you're using Django's :doc:`testing framework</topics/testing>` to test database queries, -Django will need permission to create a test database. - -.. _PostgreSQL: http://www.postgresql.org/ -.. _MySQL: http://www.mysql.com/ -.. _psycopg: http://initd.org/pub/software/psycopg/ -.. _compiled Windows version: http://stickpeople.com/projects/python/win-psycopg/ -.. _MySQLdb: http://sourceforge.net/projects/mysql-python -.. _SQLite: http://www.sqlite.org/ -.. _pysqlite: http://trac.edgewall.org/wiki/PySqlite -.. _cx_Oracle: http://cx-oracle.sourceforge.net/ -.. _Oracle: http://www.oracle.com/ -.. _Sybase SQL Anywhere: http://code.google.com/p/sqlany-django/ -.. _IBM DB2: http://code.google.com/p/ibm-db/ -.. _Microsoft SQL Server 2005: http://code.google.com/p/django-mssql/ -.. _Firebird: http://code.google.com/p/django-firebird/ -.. _ODBC: http://code.google.com/p/django-pyodbc/ -.. _removing-old-versions-of-django: - -Remove any old versions of Django -================================= - -If you are upgrading your installation of Django from a previous version, -you will need to uninstall the old Django version before installing the -new version. - -If you installed Django using ``setup.py install``, uninstalling -is as simple as deleting the ``django`` directory from your Python -``site-packages``. - -If you installed Django from a Python egg, remove the Django ``.egg`` file, -and remove the reference to the egg in the file named ``easy-install.pth``. -This file should also be located in your ``site-packages`` directory. - -.. admonition:: Where are my ``site-packages`` stored? - - The location of the ``site-packages`` directory depends on the operating - system, and the location in which Python was installed. To find out your - system's ``site-packages`` location, execute the following: - - .. code-block:: bash - - python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" - - (Note that this should be run from a shell prompt, not a Python interactive - prompt.) - -.. _install-django-code: - -Install the Django code -======================= - -Installation instructions are slightly different depending on whether you're -installing a distribution-specific package, downloading the latest official -release, or fetching the latest development version. - -It's easy, no matter which way you choose. - -Installing a distribution-specific package -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Check the :doc:`distribution specific notes </misc/distributions>` to see if your -platform/distribution provides official Django packages/installers. -Distribution-provided packages will typically allow for automatic installation -of dependencies and easy upgrade paths. - -.. _installing-official-release: - -Installing an official release -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - 1. Download the latest release from our `download page`_. - - 2. Untar the downloaded file (e.g. ``tar xzvf Django-NNN.tar.gz``, - where ``NNN`` is the version number of the latest release). - If you're using Windows, you can download the command-line tool - bsdtar_ to do this, or you can use a GUI-based tool such as 7-zip_. - - 3. Change into the directory created in step 2 (e.g. ``cd Django-NNN``). - - 4. If you're using Linux, Mac OS X or some other flavor of Unix, enter - the command ``sudo python setup.py install`` at the shell prompt. - If you're using Windows, start up a command shell with administrator - privileges and run the command ``setup.py install``. - -These commands will install Django in your Python installation's -``site-packages`` directory. - -.. _bsdtar: http://gnuwin32.sourceforge.net/packages/bsdtar.htm -.. _7-zip: http://www.7-zip.org/ - -.. _installing-development-version: - -Installing the development version -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. admonition:: Tracking Django development - - If you decide to use the latest development version of Django, - you'll want to pay close attention to `the development timeline`_, - and you'll want to keep an eye on `the list of - backwards-incompatible changes`_. This will help you stay on top - of any new features you might want to use, as well as any changes - you'll need to make to your code when updating your copy of Django. - (For stable releases, any necessary changes are documented in the - release notes.) - -.. _the development timeline: http://code.djangoproject.com/timeline -.. _the list of backwards-incompatible changes: http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges - -If you'd like to be able to update your Django code occasionally with the -latest bug fixes and improvements, follow these instructions: - -1. Make sure that you have Subversion_ installed, and that you can run its - commands from a shell. (Enter ``svn help`` at a shell prompt to test - this.) - -2. Check out Django's main development branch (the 'trunk') like so: - - .. code-block:: bash - - svn co http://code.djangoproject.com/svn/django/trunk/ django-trunk - -3. Next, make sure that the Python interpreter can load Django's code. There - are various ways of accomplishing this. One of the most convenient, on - Linux, Mac OSX or other Unix-like systems, is to use a symbolic link: - - .. code-block:: bash - - ln -s WORKING-DIR/django-trunk/django SITE-PACKAGES-DIR/django - - (In the above line, change ``SITE-PACKAGES-DIR`` to match the location of - your system's ``site-packages`` directory, as explained in the - "Where are my ``site-packages`` stored?" section above. Change WORKING-DIR - to match the full path to your new ``django-trunk`` directory.) - - Alternatively, you can define your ``PYTHONPATH`` environment variable - so that it includes the ``django-trunk`` directory. This is perhaps the - most convenient solution on Windows systems, which don't support symbolic - links. (Environment variables can be defined on Windows systems `from the - Control Panel`_.) - - .. admonition:: What about Apache and mod_python? - - If you take the approach of setting ``PYTHONPATH``, you'll need to - remember to do the same thing in your Apache configuration once you - deploy your production site. Do this by setting ``PythonPath`` in your - Apache configuration file. - - More information about deployment is available, of course, in our - :doc:`How to use Django with mod_python </howto/deployment/modpython>` - documentation. - -4. On Unix-like systems, create a symbolic link to the file - ``django-trunk/django/bin/django-admin.py`` in a directory on your system - path, such as ``/usr/local/bin``. For example: - - .. code-block:: bash - - ln -s WORKING-DIR/django-trunk/django/bin/django-admin.py /usr/local/bin - - (In the above line, change WORKING-DIR to match the full path to your new - ``django-trunk`` directory.) - - This simply lets you type ``django-admin.py`` from within any directory, - rather than having to qualify the command with the full path to the file. - - On Windows systems, the same result can be achieved by copying the file - ``django-trunk/django/bin/django-admin.py`` to somewhere on your system - path, for example ``C:\Python24\Scripts``. - -You *don't* have to run ``python setup.py install``, because you've already -carried out the equivalent actions in steps 3 and 4. - -When you want to update your copy of the Django source code, just run the -command ``svn update`` from within the ``django-trunk`` directory. When you do -this, Subversion will automatically download any changes. - -.. _`download page`: http://www.djangoproject.com/download/ -.. _Subversion: http://subversion.tigris.org/ -.. _from the Control Panel: http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/sysdm_advancd_environmnt_addchange_variable.mspx diff --git a/parts/django/docs/topics/pagination.txt b/parts/django/docs/topics/pagination.txt deleted file mode 100644 index ee8a433..0000000 --- a/parts/django/docs/topics/pagination.txt +++ /dev/null @@ -1,281 +0,0 @@ -========== -Pagination -========== - -.. module:: django.core.paginator - :synopsis: Classes to help you easily manage paginated data. - -.. versionchanged:: 1.0 - Pagination facilities have been almost fully reworked. - -Django provides a few classes that help you manage paginated data -- that is, -data that's split across several pages, with "Previous/Next" links. These -classes live in :file:`django/core/paginator.py`. - -Example -======= - -Give :class:`Paginator` a list of objects, plus the number of items you'd like to -have on each page, and it gives you methods for accessing the items for each -page:: - - >>> from django.core.paginator import Paginator - >>> objects = ['john', 'paul', 'george', 'ringo'] - >>> p = Paginator(objects, 2) - - >>> p.count - 4 - >>> p.num_pages - 2 - >>> p.page_range - [1, 2] - - >>> page1 = p.page(1) - >>> page1 - <Page 1 of 2> - >>> page1.object_list - ['john', 'paul'] - - >>> page2 = p.page(2) - >>> page2.object_list - ['george', 'ringo'] - >>> page2.has_next() - False - >>> page2.has_previous() - True - >>> page2.has_other_pages() - True - >>> page2.next_page_number() - 3 - >>> page2.previous_page_number() - 1 - >>> page2.start_index() # The 1-based index of the first item on this page - 3 - >>> page2.end_index() # The 1-based index of the last item on this page - 4 - - >>> p.page(0) - Traceback (most recent call last): - ... - EmptyPage: That page number is less than 1 - >>> p.page(3) - Traceback (most recent call last): - ... - EmptyPage: That page contains no results - -.. note:: - - Note that you can give ``Paginator`` a list/tuple, a Django ``QuerySet``, or - any other object with a ``count()`` or ``__len__()`` method. When - determining the number of objects contained in the passed object, - ``Paginator`` will first try calling ``count()``, then fallback to using - ``len()`` if the passed object has no ``count()`` method. This allows - objects such as Django's ``QuerySet`` to use a more efficient ``count()`` - method when available. - - -Using ``Paginator`` in a view -============================== - -Here's a slightly more complex example using :class:`Paginator` in a view to -paginate a queryset. We give both the view and the accompanying template to -show how you can display the results. This example assumes you have a -``Contacts`` model that has already been imported. - -The view function looks like this:: - - from django.core.paginator import Paginator, InvalidPage, EmptyPage - - def listing(request): - contact_list = Contacts.objects.all() - paginator = Paginator(contact_list, 25) # Show 25 contacts per page - - # Make sure page request is an int. If not, deliver first page. - try: - page = int(request.GET.get('page', '1')) - except ValueError: - page = 1 - - # If page request (9999) is out of range, deliver last page of results. - try: - contacts = paginator.page(page) - except (EmptyPage, InvalidPage): - contacts = paginator.page(paginator.num_pages) - - return render_to_response('list.html', {"contacts": contacts}) - -In the template :file:`list.html`, you'll want to include navigation between -pages along with any interesting information from the objects themselves:: - - {% for contact in contacts.object_list %} - {# Each "contact" is a Contact model object. #} - {{ contact.full_name|upper }}<br /> - ... - {% endfor %} - - <div class="pagination"> - <span class="step-links"> - {% if contacts.has_previous %} - <a href="?page={{ contacts.previous_page_number }}">previous</a> - {% endif %} - - <span class="current"> - Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}. - </span> - - {% if contacts.has_next %} - <a href="?page={{ contacts.next_page_number }}">next</a> - {% endif %} - </span> - </div> - - -``Paginator`` objects -===================== - -The :class:`Paginator` class has this constructor: - -.. class:: Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True) - -Required arguments ------------------- - -``object_list`` - A list, tuple, Django ``QuerySet``, or other sliceable object with a - ``count()`` or ``__len__()`` method. - -``per_page`` - The maximum number of items to include on a page, not including orphans - (see the ``orphans`` optional argument below). - -Optional arguments ------------------- - -``orphans`` - The minimum number of items allowed on the last page, defaults to zero. - Use this when you don't want to have a last page with very few items. - If the last page would normally have a number of items less than or equal - to ``orphans``, then those items will be added to the previous page (which - becomes the last page) instead of leaving the items on a page by - themselves. For example, with 23 items, ``per_page=10``, and - ``orphans=3``, there will be two pages; the first page with 10 items and - the second (and last) page with 13 items. - -``allow_empty_first_page`` - Whether or not the first page is allowed to be empty. If ``False`` and - ``object_list`` is empty, then an ``EmptyPage`` error will be raised. - -Methods -------- - -.. method:: Paginator.page(number) - - Returns a :class:`Page` object with the given 1-based index. Raises - :exc:`InvalidPage` if the given page number doesn't exist. - -Attributes ----------- - -.. attribute:: Paginator.count - - The total number of objects, across all pages. - - .. note:: - - When determining the number of objects contained in ``object_list``, - ``Paginator`` will first try calling ``object_list.count()``. If - ``object_list`` has no ``count()`` method, then ``Paginator`` will - fallback to using ``object_list.__len__()``. This allows objects, such - as Django's ``QuerySet``, to use a more efficient ``count()`` method - when available. - -.. attribute:: Paginator.num_pages - - The total number of pages. - -.. attribute:: Paginator.page_range - - A 1-based range of page numbers, e.g., ``[1, 2, 3, 4]``. - -``InvalidPage`` exceptions -========================== - -The ``page()`` method raises ``InvalidPage`` if the requested page is invalid -(i.e., not an integer) or contains no objects. Generally, it's enough to trap -the ``InvalidPage`` exception, but if you'd like more granularity, you can trap -either of the following exceptions: - -``PageNotAnInteger`` - Raised when ``page()`` is given a value that isn't an integer. - -``EmptyPage`` - Raised when ``page()`` is given a valid value but no objects exist on that - page. - -Both of the exceptions are subclasses of ``InvalidPage``, so you can handle -them both with a simple ``except InvalidPage``. - - -``Page`` objects -================ - -.. class:: Page(object_list, number, paginator) - -You usually won't construct :class:`Pages <Page>` by hand -- you'll get them -using :meth:`Paginator.page`. - - -Methods -------- - -.. method:: Page.has_next() - - Returns ``True`` if there's a next page. - -.. method:: Page.has_previous() - - Returns ``True`` if there's a previous page. - -.. method:: Page.has_other_pages() - - Returns ``True`` if there's a next *or* previous page. - -.. method:: Page.next_page_number() - - Returns the next page number. Note that this is "dumb" and will return the - next page number regardless of whether a subsequent page exists. - -.. method:: Page.previous_page_number() - - Returns the previous page number. Note that this is "dumb" and will return - the previous page number regardless of whether a previous page exists. - -.. method:: Page.start_index() - - Returns the 1-based index of the first object on the page, relative to all - of the objects in the paginator's list. For example, when paginating a list - of 5 objects with 2 objects per page, the second page's :meth:`~Page.start_index` - would return ``3``. - -.. method:: Page.end_index() - - Returns the 1-based index of the last object on the page, relative to all of - the objects in the paginator's list. For example, when paginating a list of - 5 objects with 2 objects per page, the second page's :meth:`~Page.end_index` - would return ``4``. - -Attributes ----------- - -.. attribute:: Page.object_list - - The list of objects on this page. - -.. attribute:: Page.number - - The 1-based page number for this page. - -.. attribute:: Page.paginator - - The associated :class:`Paginator` object. - diff --git a/parts/django/docs/topics/serialization.txt b/parts/django/docs/topics/serialization.txt deleted file mode 100644 index c8acc85..0000000 --- a/parts/django/docs/topics/serialization.txt +++ /dev/null @@ -1,402 +0,0 @@ -========================== -Serializing Django objects -========================== - -Django's serialization framework provides a mechanism for "translating" Django -objects into other formats. Usually these other formats will be text-based and -used for sending Django objects over a wire, but it's possible for a -serializer to handle any format (text-based or not). - -.. seealso:: - - If you just want to get some data from your tables into a serialized - form, you could use the :djadmin:`dumpdata` management command. - -Serializing data ----------------- - -At the highest level, serializing data is a very simple operation:: - - from django.core import serializers - data = serializers.serialize("xml", SomeModel.objects.all()) - -The arguments to the ``serialize`` function are the format to serialize the data -to (see `Serialization formats`_) and a :class:`~django.db.models.QuerySet` to -serialize. (Actually, the second argument can be any iterator that yields Django -objects, but it'll almost always be a QuerySet). - -You can also use a serializer object directly:: - - XMLSerializer = serializers.get_serializer("xml") - xml_serializer = XMLSerializer() - xml_serializer.serialize(queryset) - data = xml_serializer.getvalue() - -This is useful if you want to serialize data directly to a file-like object -(which includes an :class:`~django.http.HttpResponse`):: - - out = open("file.xml", "w") - xml_serializer.serialize(SomeModel.objects.all(), stream=out) - -Subset of fields -~~~~~~~~~~~~~~~~ - -If you only want a subset of fields to be serialized, you can -specify a ``fields`` argument to the serializer:: - - from django.core import serializers - data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size')) - -In this example, only the ``name`` and ``size`` attributes of each model will -be serialized. - -.. note:: - - Depending on your model, you may find that it is not possible to - deserialize a model that only serializes a subset of its fields. If a - serialized object doesn't specify all the fields that are required by a - model, the deserializer will not be able to save deserialized instances. - -Inherited Models -~~~~~~~~~~~~~~~~ - -If you have a model that is defined using an :ref:`abstract base class -<abstract-base-classes>`, you don't have to do anything special to serialize -that model. Just call the serializer on the object (or objects) that you want to -serialize, and the output will be a complete representation of the serialized -object. - -However, if you have a model that uses :ref:`multi-table inheritance -<multi-table-inheritance>`, you also need to serialize all of the base classes -for the model. This is because only the fields that are locally defined on the -model will be serialized. For example, consider the following models:: - - class Place(models.Model): - name = models.CharField(max_length=50) - - class Restaurant(Place): - serves_hot_dogs = models.BooleanField() - -If you only serialize the Restaurant model:: - - data = serializers.serialize('xml', Restaurant.objects.all()) - -the fields on the serialized output will only contain the `serves_hot_dogs` -attribute. The `name` attribute of the base class will be ignored. - -In order to fully serialize your Restaurant instances, you will need to -serialize the Place models as well:: - - all_objects = list(Restaurant.objects.all()) + list(Place.objects.all()) - data = serializers.serialize('xml', all_objects) - -Deserializing data ------------------- - -Deserializing data is also a fairly simple operation:: - - for obj in serializers.deserialize("xml", data): - do_something_with(obj) - -As you can see, the ``deserialize`` function takes the same format argument as -``serialize``, a string or stream of data, and returns an iterator. - -However, here it gets slightly complicated. The objects returned by the -``deserialize`` iterator *aren't* simple Django objects. Instead, they are -special ``DeserializedObject`` instances that wrap a created -- but unsaved -- -object and any associated relationship data. - -Calling ``DeserializedObject.save()`` saves the object to the database. - -This ensures that deserializing is a non-destructive operation even if the -data in your serialized representation doesn't match what's currently in the -database. Usually, working with these ``DeserializedObject`` instances looks -something like:: - - for deserialized_object in serializers.deserialize("xml", data): - if object_should_be_saved(deserialized_object): - deserialized_object.save() - -In other words, the usual use is to examine the deserialized objects to make -sure that they are "appropriate" for saving before doing so. Of course, if you -trust your data source you could just save the object and move on. - -The Django object itself can be inspected as ``deserialized_object.object``. - -.. _serialization-formats: - -Serialization formats ---------------------- - -Django supports a number of serialization formats, some of which require you -to install third-party Python modules: - - ========== ============================================================== - Identifier Information - ========== ============================================================== - ``xml`` Serializes to and from a simple XML dialect. - - ``json`` Serializes to and from JSON_ (using a version of simplejson_ - bundled with Django). - - ``yaml`` Serializes to YAML (YAML Ain't a Markup Language). This - serializer is only available if PyYAML_ is installed. - ========== ============================================================== - -.. _json: http://json.org/ -.. _simplejson: http://undefined.org/python/#simplejson -.. _PyYAML: http://www.pyyaml.org/ - -Notes for specific serialization formats -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -json -^^^^ - -If you're using UTF-8 (or any other non-ASCII encoding) data with the JSON -serializer, you must pass ``ensure_ascii=False`` as a parameter to the -``serialize()`` call. Otherwise, the output won't be encoded correctly. - -For example:: - - json_serializer = serializers.get_serializer("json")() - json_serializer.serialize(queryset, ensure_ascii=False, stream=response) - -The Django source code includes the simplejson_ module. However, if you're -using Python 2.6 or later (which includes a builtin version of the module), Django will -use the builtin ``json`` module automatically. If you have a system installed -version that includes the C-based speedup extension, or your system version is -more recent than the version shipped with Django (currently, 2.0.7), the -system version will be used instead of the version included with Django. - -Be aware that if you're serializing using that module directly, not all Django -output can be passed unmodified to simplejson. In particular, :ref:`lazy -translation objects <lazy-translations>` need a `special encoder`_ written for -them. Something like this will work:: - - from django.utils.functional import Promise - from django.utils.encoding import force_unicode - - class LazyEncoder(simplejson.JSONEncoder): - def default(self, obj): - if isinstance(obj, Promise): - return force_unicode(obj) - return super(LazyEncoder, self).default(obj) - -.. _special encoder: http://svn.red-bean.com/bob/simplejson/tags/simplejson-1.7/docs/index.html - -.. _topics-serialization-natural-keys: - -Natural keys ------------- - -.. versionadded:: 1.2 - - The ability to use natural keys when serializing/deserializing data was - added in the 1.2 release. - -The default serialization strategy for foreign keys and many-to-many -relations is to serialize the value of the primary key(s) of the -objects in the relation. This strategy works well for most types of -object, but it can cause difficulty in some circumstances. - -Consider the case of a list of objects that have foreign key on -:class:`ContentType`. If you're going to serialize an object that -refers to a content type, you need to have a way to refer to that -content type. Content Types are automatically created by Django as -part of the database synchronization process, so you don't need to -include content types in a fixture or other serialized data. As a -result, the primary key of any given content type isn't easy to -predict - it will depend on how and when :djadmin:`syncdb` was -executed to create the content types. - -There is also the matter of convenience. An integer id isn't always -the most convenient way to refer to an object; sometimes, a -more natural reference would be helpful. - -It is for these reasons that Django provides *natural keys*. A natural -key is a tuple of values that can be used to uniquely identify an -object instance without using the primary key value. - -Deserialization of natural keys -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Consider the following two models:: - - from django.db import models - - class Person(models.Model): - first_name = models.CharField(max_length=100) - last_name = models.CharField(max_length=100) - - birthdate = models.DateField() - - class Meta: - unique_together = (('first_name', 'last_name'),) - - class Book(models.Model): - name = models.CharField(max_length=100) - author = models.ForeignKey(Person) - -Ordinarily, serialized data for ``Book`` would use an integer to refer to -the author. For example, in JSON, a Book might be serialized as:: - - ... - { - "pk": 1, - "model": "store.book", - "fields": { - "name": "Mostly Harmless", - "author": 42 - } - } - ... - -This isn't a particularly natural way to refer to an author. It -requires that you know the primary key value for the author; it also -requires that this primary key value is stable and predictable. - -However, if we add natural key handling to Person, the fixture becomes -much more humane. To add natural key handling, you define a default -Manager for Person with a ``get_by_natural_key()`` method. In the case -of a Person, a good natural key might be the pair of first and last -name:: - - from django.db import models - - class PersonManager(models.Manager): - def get_by_natural_key(self, first_name, last_name): - return self.get(first_name=first_name, last_name=last_name) - - class Person(models.Model): - objects = PersonManager() - - first_name = models.CharField(max_length=100) - last_name = models.CharField(max_length=100) - - birthdate = models.DateField() - - class Meta: - unique_together = (('first_name', 'last_name'),) - -Now books can use that natural key to refer to ``Person`` objects:: - - ... - { - "pk": 1, - "model": "store.book", - "fields": { - "name": "Mostly Harmless", - "author": ["Douglas", "Adams"] - } - } - ... - -When you try to load this serialized data, Django will use the -``get_by_natural_key()`` method to resolve ``["Douglas", "Adams"]`` -into the primary key of an actual ``Person`` object. - -.. note:: - - Whatever fields you use for a natural key must be able to uniquely - identify an object. This will usually mean that your model will - have a uniqueness clause (either unique=True on a single field, or - ``unique_together`` over multiple fields) for the field or fields - in your natural key. However, uniqueness doesn't need to be - enforced at the database level. If you are certain that a set of - fields will be effectively unique, you can still use those fields - as a natural key. - -Serialization of natural keys -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -So how do you get Django to emit a natural key when serializing an object? -Firstly, you need to add another method -- this time to the model itself:: - - class Person(models.Model): - objects = PersonManager() - - first_name = models.CharField(max_length=100) - last_name = models.CharField(max_length=100) - - birthdate = models.DateField() - - def natural_key(self): - return (self.first_name, self.last_name) - - class Meta: - unique_together = (('first_name', 'last_name'),) - -That method should always return a natural key tuple -- in this -example, ``(first name, last name)``. Then, when you call -``serializers.serialize()``, you provide a ``use_natural_keys=True`` -argument:: - - >>> serializers.serialize('json', [book1, book2], indent=2, use_natural_keys=True) - -When ``use_natural_keys=True`` is specified, Django will use the -``natural_key()`` method to serialize any reference to objects of the -type that defines the method. - -If you are using :djadmin:`dumpdata` to generate serialized data, you -use the `--natural` command line flag to generate natural keys. - -.. note:: - - You don't need to define both ``natural_key()`` and - ``get_by_natural_key()``. If you don't want Django to output - natural keys during serialization, but you want to retain the - ability to load natural keys, then you can opt to not implement - the ``natural_key()`` method. - - Conversely, if (for some strange reason) you want Django to output - natural keys during serialization, but *not* be able to load those - key values, just don't define the ``get_by_natural_key()`` method. - -Dependencies during serialization -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Since natural keys rely on database lookups to resolve references, it -is important that data exists before it is referenced. You can't make -a `forward reference` with natural keys - the data you are referencing -must exist before you include a natural key reference to that data. - -To accommodate this limitation, calls to :djadmin:`dumpdata` that use -the :djadminopt:`--natural` option will serialize any model with a -``natural_key()`` method before it serializes normal key objects. - -However, this may not always be enough. If your natural key refers to -another object (by using a foreign key or natural key to another object -as part of a natural key), then you need to be able to ensure that -the objects on which a natural key depends occur in the serialized data -before the natural key requires them. - -To control this ordering, you can define dependencies on your -``natural_key()`` methods. You do this by setting a ``dependencies`` -attribute on the ``natural_key()`` method itself. - -For example, consider the ``Permission`` model in ``contrib.auth``. -The following is a simplified version of the ``Permission`` model:: - - class Permission(models.Model): - name = models.CharField(max_length=50) - content_type = models.ForeignKey(ContentType) - codename = models.CharField(max_length=100) - # ... - def natural_key(self): - return (self.codename,) + self.content_type.natural_key() - -The natural key for a ``Permission`` is a combination of the codename for the -``Permission``, and the ``ContentType`` to which the ``Permission`` applies. This means -that ``ContentType`` must be serialized before ``Permission``. To define this -dependency, we add one extra line:: - - class Permission(models.Model): - # ... - def natural_key(self): - return (self.codename,) + self.content_type.natural_key() - natural_key.dependencies = ['contenttypes.contenttype'] - -This definition ensures that ``ContentType`` models are serialized before -``Permission`` models. In turn, any object referencing ``Permission`` will -be serialized after both ``ContentType`` and ``Permission``. diff --git a/parts/django/docs/topics/settings.txt b/parts/django/docs/topics/settings.txt deleted file mode 100644 index 59c02c3..0000000 --- a/parts/django/docs/topics/settings.txt +++ /dev/null @@ -1,255 +0,0 @@ -=============== -Django settings -=============== - -A Django settings file contains all the configuration of your Django -installation. This document explains how settings work and which settings are -available. - -The basics -========== - -A settings file is just a Python module with module-level variables. - -Here are a couple of example settings:: - - DEBUG = False - DEFAULT_FROM_EMAIL = 'webmaster@example.com' - TEMPLATE_DIRS = ('/home/templates/mike', '/home/templates/john') - -Because a settings file is a Python module, the following apply: - - * It doesn't allow for Python syntax errors. - * It can assign settings dynamically using normal Python syntax. - For example:: - - MY_SETTING = [str(i) for i in range(30)] - - * It can import values from other settings files. - -.. _django-settings-module: - -Designating the settings -======================== - -When you use Django, you have to tell it which settings you're using. Do this -by using an environment variable, ``DJANGO_SETTINGS_MODULE``. - -The value of ``DJANGO_SETTINGS_MODULE`` should be in Python path syntax, e.g. -``mysite.settings``. Note that the settings module should be on the -Python `import search path`_. - -.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html - -The django-admin.py utility ---------------------------- - -When using :doc:`django-admin.py </ref/django-admin>`, you can either set the -environment variable once, or explicitly pass in the settings module each time -you run the utility. - -Example (Unix Bash shell):: - - export DJANGO_SETTINGS_MODULE=mysite.settings - django-admin.py runserver - -Example (Windows shell):: - - set DJANGO_SETTINGS_MODULE=mysite.settings - django-admin.py runserver - -Use the ``--settings`` command-line argument to specify the settings manually:: - - django-admin.py runserver --settings=mysite.settings - -.. _django-admin.py: ../django-admin/ - -On the server (mod_python) --------------------------- - -In your live server environment, you'll need to tell Apache/mod_python which -settings file to use. Do that with ``SetEnv``:: - - <Location "/mysite/"> - SetHandler python-program - PythonHandler django.core.handlers.modpython - SetEnv DJANGO_SETTINGS_MODULE mysite.settings - </Location> - -Read the :doc:`Django mod_python documentation </howto/deployment/modpython>` for -more information. - -Default settings -================ - -A Django settings file doesn't have to define any settings if it doesn't need -to. Each setting has a sensible default value. These defaults live in the -module :file:`django/conf/global_settings.py`. - -Here's the algorithm Django uses in compiling settings: - - * Load settings from ``global_settings.py``. - * Load settings from the specified settings file, overriding the global - settings as necessary. - -Note that a settings file should *not* import from ``global_settings``, because -that's redundant. - -Seeing which settings you've changed ------------------------------------- - -There's an easy way to view which of your settings deviate from the default -settings. The command ``python manage.py diffsettings`` displays differences -between the current settings file and Django's default settings. - -For more, see the :djadmin:`diffsettings` documentation. - -Using settings in Python code -============================= - -In your Django apps, use settings by importing the object -``django.conf.settings``. Example:: - - from django.conf import settings - - if settings.DEBUG: - # Do something - -Note that ``django.conf.settings`` isn't a module -- it's an object. So -importing individual settings is not possible:: - - from django.conf.settings import DEBUG # This won't work. - -Also note that your code should *not* import from either ``global_settings`` or -your own settings file. ``django.conf.settings`` abstracts the concepts of -default settings and site-specific settings; it presents a single interface. -It also decouples the code that uses settings from the location of your -settings. - -Altering settings at runtime -============================ - -You shouldn't alter settings in your applications at runtime. For example, -don't do this in a view:: - - from django.conf import settings - - settings.DEBUG = True # Don't do this! - -The only place you should assign to settings is in a settings file. - -Security -======== - -Because a settings file contains sensitive information, such as the database -password, you should make every attempt to limit access to it. For example, -change its file permissions so that only you and your Web server's user can -read it. This is especially important in a shared-hosting environment. - -Available settings -================== - -For a full list of available settings, see the :doc:`settings reference </ref/settings>`. - -Creating your own settings -========================== - -There's nothing stopping you from creating your own settings, for your own -Django apps. Just follow these conventions: - - * Setting names are in all uppercase. - * Don't reinvent an already-existing setting. - -For settings that are sequences, Django itself uses tuples, rather than lists, -but this is only a convention. - -.. _settings-without-django-settings-module: - -Using settings without setting DJANGO_SETTINGS_MODULE -===================================================== - -In some cases, you might want to bypass the ``DJANGO_SETTINGS_MODULE`` -environment variable. For example, if you're using the template system by -itself, you likely don't want to have to set up an environment variable -pointing to a settings module. - -In these cases, you can configure Django's settings manually. Do this by -calling: - -.. function:: django.conf.settings.configure(default_settings, **settings) - -Example:: - - from django.conf import settings - - settings.configure(DEBUG=True, TEMPLATE_DEBUG=True, - TEMPLATE_DIRS=('/home/web-apps/myapp', '/home/web-apps/base')) - -Pass ``configure()`` as many keyword arguments as you'd like, with each keyword -argument representing a setting and its value. Each argument name should be all -uppercase, with the same name as the settings described above. If a particular -setting is not passed to ``configure()`` and is needed at some later point, -Django will use the default setting value. - -Configuring Django in this fashion is mostly necessary -- and, indeed, -recommended -- when you're using a piece of the framework inside a larger -application. - -Consequently, when configured via ``settings.configure()``, Django will not -make any modifications to the process environment variables (see the -documentation of :setting:`TIME_ZONE` for why this would normally occur). It's -assumed that you're already in full control of your environment in these -cases. - -Custom default settings ------------------------ - -If you'd like default values to come from somewhere other than -``django.conf.global_settings``, you can pass in a module or class that -provides the default settings as the ``default_settings`` argument (or as the -first positional argument) in the call to ``configure()``. - -In this example, default settings are taken from ``myapp_defaults``, and the -``DEBUG`` setting is set to ``True``, regardless of its value in -``myapp_defaults``:: - - from django.conf import settings - from myapp import myapp_defaults - - settings.configure(default_settings=myapp_defaults, DEBUG=True) - -The following example, which uses ``myapp_defaults`` as a positional argument, -is equivalent:: - - settings.configure(myapp_defaults, DEBUG = True) - -Normally, you will not need to override the defaults in this fashion. The -Django defaults are sufficiently tame that you can safely use them. Be aware -that if you do pass in a new default module, it entirely *replaces* the Django -defaults, so you must specify a value for every possible setting that might be -used in that code you are importing. Check in -``django.conf.settings.global_settings`` for the full list. - -Either configure() or DJANGO_SETTINGS_MODULE is required --------------------------------------------------------- - -If you're not setting the ``DJANGO_SETTINGS_MODULE`` environment variable, you -*must* call ``configure()`` at some point before using any code that reads -settings. - -If you don't set ``DJANGO_SETTINGS_MODULE`` and don't call ``configure()``, -Django will raise an ``ImportError`` exception the first time a setting -is accessed. - -If you set ``DJANGO_SETTINGS_MODULE``, access settings values somehow, *then* -call ``configure()``, Django will raise a ``RuntimeError`` indicating -that settings have already been configured. - -Also, it's an error to call ``configure()`` more than once, or to call -``configure()`` after any setting has been accessed. - -It boils down to this: Use exactly one of either ``configure()`` or -``DJANGO_SETTINGS_MODULE``. Not both, and not neither. - -.. _@login_required: ../authentication/#the-login-required-decorator - diff --git a/parts/django/docs/topics/signals.txt b/parts/django/docs/topics/signals.txt deleted file mode 100644 index 35e111d..0000000 --- a/parts/django/docs/topics/signals.txt +++ /dev/null @@ -1,255 +0,0 @@ -======= -Signals -======= - -.. module:: django.dispatch - :synopsis: Signal dispatch - -Django includes a "signal dispatcher" which helps allow decoupled applications -get notified when actions occur elsewhere in the framework. In a nutshell, -signals allow certain *senders* to notify a set of *receivers* that some action -has taken place. They're especially useful when many pieces of code may be -interested in the same events. - -Django provides a :doc:`set of built-in signals </ref/signals>` that let user -code get notified by Django itself of certain actions. These include some useful -notifications: - - * :data:`django.db.models.signals.pre_save` & - :data:`django.db.models.signals.post_save` - - Sent before or after a model's :meth:`~django.db.models.Model.save` method - is called. - - * :data:`django.db.models.signals.pre_delete` & - :data:`django.db.models.signals.post_delete` - - Sent before or after a model's :meth:`~django.db.models.Model.delete` - method is called. - - * :data:`django.db.models.signals.m2m_changed` - - Sent when a :class:`ManyToManyField` on a model is changed. - - * :data:`django.core.signals.request_started` & - :data:`django.core.signals.request_finished` - - Sent when Django starts or finishes an HTTP request. - -See the :doc:`built-in signal documentation </ref/signals>` for a complete list, -and a complete explanation of each signal. - -You can also `define and send your own custom signals`_; see below. - -.. _define and send your own custom signals: `defining and sending signals`_ - -Listening to signals -==================== - -To receive a signal, you need to register a *receiver* function that gets -called when the signal is sent by using the -:meth:`.Signal.connect` method: - -.. method:: Signal.connect(receiver, [sender=None, weak=True, dispatch_uid=None]) - - :param receiver: The callback function which will be connected to this - signal. See :ref:`receiver-functions` for more information. - - :param sender: Specifies a particular sender to receive signals from. See - :ref:`connecting-to-specific-signals` for more information. - - :param weak: Django stores signal handlers as weak references by - default. Thus, if your receiver is a local function, it may be - garbage collected. To prevent this, pass ``weak=False`` when you call - the signal's ``connect()`` method. - - :param dispatch_uid: A unique identifier for a signal receiver in cases - where duplicate signals may be sent. See - :ref:`preventing-duplicate-signals` for more information. - -Let's see how this works by registering a signal that -gets called after each HTTP request is finished. We'll be connecting to the -:data:`~django.core.signals.request_finished` signal. - -.. _receiver-functions: - -Receiver functions ------------------- - -First, we need to define a receiver function. A receiver can be any Python -function or method: - -.. code-block:: python - - def my_callback(sender, **kwargs): - print "Request finished!" - -Notice that the function takes a ``sender`` argument, along with wildcard -keyword arguments (``**kwargs``); all signal handlers must take these arguments. - -We'll look at senders `a bit later`_, but right now look at the ``**kwargs`` -argument. All signals send keyword arguments, and may change those keyword -arguments at any time. In the case of -:data:`~django.core.signals.request_finished`, it's documented as sending no -arguments, which means we might be tempted to write our signal handling as -``my_callback(sender)``. - -.. _a bit later: `connecting to signals sent by specific senders`_ - -This would be wrong -- in fact, Django will throw an error if you do so. That's -because at any point arguments could get added to the signal and your receiver -must be able to handle those new arguments. - -.. _connecting-receiver-functions: - -Connecting receiver functions ------------------------------ - -Next, we'll need to connect our receiver to the signal: - -.. code-block:: python - - from django.core.signals import request_finished - - request_finished.connect(my_callback) - -Now, our ``my_callback`` function will be called each time a request finishes. - -.. admonition:: Where should this code live? - - You can put signal handling and registration code anywhere you like. - However, you'll need to make sure that the module it's in gets imported - early on so that the signal handling gets registered before any signals need - to be sent. This makes your app's ``models.py`` a good place to put - registration of signal handlers. - -.. _connecting-to-specific-signals: - -Connecting to signals sent by specific senders ----------------------------------------------- - -Some signals get sent many times, but you'll only be interested in receiving a -certain subset of those signals. For example, consider the -:data:`django.db.models.signals.pre_save` signal sent before a model gets saved. -Most of the time, you don't need to know when *any* model gets saved -- just -when one *specific* model is saved. - -In these cases, you can register to receive signals sent only by particular -senders. In the case of :data:`django.db.models.signals.pre_save`, the sender -will be the model class being saved, so you can indicate that you only want -signals sent by some model: - -.. code-block:: python - - from django.db.models.signals import pre_save - from myapp.models import MyModel - - def my_handler(sender, **kwargs): - ... - - pre_save.connect(my_handler, sender=MyModel) - -The ``my_handler`` function will only be called when an instance of ``MyModel`` -is saved. - -Different signals use different objects as their senders; you'll need to consult -the :doc:`built-in signal documentation </ref/signals>` for details of each -particular signal. - -.. _preventing-duplicate-signals: - -Preventing duplicate signals ----------------------------- - -In some circumstances, the module in which you are connecting signals may be -imported multiple times. This can cause your receiver function to be -registered more than once, and thus called multiples times for a single signal -event. - -If this behavior is problematic (such as when using signals to -send an e-mail whenever a model is saved), pass a unique identifier as -the ``dispatch_uid`` argument to identify your receiver function. This -identifier will usually be a string, although any hashable object will -suffice. The end result is that your receiver function will only be -bound to the signal once for each unique ``dispatch_uid`` value. - -.. code-block:: python - - from django.core.signals import request_finished - - request_finished.connect(my_callback, dispatch_uid="my_unique_identifier") - -Defining and sending signals -============================ - -Your applications can take advantage of the signal infrastructure and provide -its own signals. - -Defining signals ----------------- - -.. class:: Signal([providing_args=list]) - -All signals are :class:`django.dispatch.Signal` instances. The -``providing_args`` is a list of the names of arguments the signal will provide -to listeners. - -For example: - -.. code-block:: python - - import django.dispatch - - pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"]) - -This declares a ``pizza_done`` signal that will provide receivers with -``toppings`` and ``size`` arguments. - -Remember that you're allowed to change this list of arguments at any time, so getting the API right on the first try isn't necessary. - -Sending signals ---------------- - -There are two ways to send send signals in Django. - -.. method:: Signal.send(sender, **kwargs) -.. method:: Signal.send_robust(sender, **kwargs) - -To send a signal, call either :meth:`Signal.send` or :meth:`Signal.send_robust`. -You must provide the ``sender`` argument, and may provide as many other keyword -arguments as you like. - -For example, here's how sending our ``pizza_done`` signal might look: - -.. code-block:: python - - class PizzaStore(object): - ... - - def send_pizza(self, toppings, size): - pizza_done.send(sender=self, toppings=toppings, size=size) - ... - -Both ``send()`` and ``send_robust()`` return a list of tuple pairs -``[(receiver, response), ... ]``, representing the list of called receiver -functions and their response values. - -``send()`` differs from ``send_robust()`` in how exceptions raised by receiver -functions are handled. ``send()`` does *not* catch any exceptions raised by -receivers; it simply allows errors to propagate. Thus not all receivers may -be notified of a signal in the face of an error. - -``send_robust()`` catches all errors derived from Python's ``Exception`` class, -and ensures all receivers are notified of the signal. If an error occurs, the -error instance is returned in the tuple pair for the receiver that raised the error. - -Disconnecting signals -===================== - -.. method:: Signal.disconnect([receiver=None, sender=None, weak=True, dispatch_uid=None]) - -To disconnect a receiver from a signal, call :meth:`Signal.disconnect`. The -arguments are as described in :meth:`.Signal.connect`. - -The *receiver* argument indicates the registered receiver to disconnect. It may -be ``None`` if ``dispatch_uid`` is used to identify the receiver. diff --git a/parts/django/docs/topics/templates.txt b/parts/django/docs/topics/templates.txt deleted file mode 100644 index d249bd3..0000000 --- a/parts/django/docs/topics/templates.txt +++ /dev/null @@ -1,617 +0,0 @@ -============================ -The Django template language -============================ - -.. admonition:: About this document - - This document explains the language syntax of the Django template system. If - you're looking for a more technical perspective on how it works and how to - extend it, see :doc:`/ref/templates/api`. - -Django's template language is designed to strike a balance between power and -ease. It's designed to feel comfortable to those used to working with HTML. If -you have any exposure to other text-based template languages, such as Smarty_ -or CheetahTemplate_, you should feel right at home with Django's templates. - -.. admonition:: Philosophy - - If you have a background in programming, or if you're used to languages - like PHP which mix programming code directly into HTML, you'll want to - bear in mind that the Django template system is not simply Python embedded - into HTML. This is by design: the template system is meant to express - presentation, not program logic. - - The Django template system provides tags which function similarly to some - programming constructs -- an :ttag:`if` tag for boolean tests, a :ttag:`for` - tag for looping, etc. -- but these are not simply executed as the - corresponding Python code, and the template system will not execute - arbitrary Python expressions. Only the tags, filters and syntax listed below - are supported by default (although you can add :doc:`your own extensions - </howto/custom-template-tags>` to the template language as needed). - -.. _`The Django template language: For Python programmers`: ../templates_python/ -.. _Smarty: http://smarty.php.net/ -.. _CheetahTemplate: http://www.cheetahtemplate.org/ - -Templates -========= - -.. highlightlang:: html+django - -A template is simply a text file. It can generate any text-based format (HTML, -XML, CSV, etc.). - -A template contains **variables**, which get replaced with values when the -template is evaluated, and **tags**, which control the logic of the template. - -Below is a minimal template that illustrates a few basics. Each element will be -explained later in this document.:: - - {% extends "base_generic.html" %} - - {% block title %}{{ section.title }}{% endblock %} - - {% block content %} - <h1>{{ section.title }}</h1> - - {% for story in story_list %} - <h2> - <a href="{{ story.get_absolute_url }}"> - {{ story.headline|upper }} - </a> - </h2> - <p>{{ story.tease|truncatewords:"100" }}</p> - {% endfor %} - {% endblock %} - -.. admonition:: Philosophy - - Why use a text-based template instead of an XML-based one (like Zope's - TAL)? We wanted Django's template language to be usable for more than - just XML/HTML templates. At World Online, we use it for e-mails, - JavaScript and CSV. You can use the template language for any text-based - format. - - Oh, and one more thing: Making humans edit XML is sadistic! - -Variables -========= - -Variables look like this: ``{{ variable }}``. When the template engine -encounters a variable, it evaluates that variable and replaces it with the -result. - -Use a dot (``.``) to access attributes of a variable. - -.. admonition:: Behind the scenes - - Technically, when the template system encounters a dot, it tries the - following lookups, in this order: - - * Dictionary lookup - * Attribute lookup - * Method call - * List-index lookup - -In the above example, ``{{ section.title }}`` will be replaced with the -``title`` attribute of the ``section`` object. - -If you use a variable that doesn't exist, the template system will insert -the value of the ``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''`` -(the empty string) by default. - -Filters -======= - -You can modify variables for display by using **filters**. - -Filters look like this: ``{{ name|lower }}``. This displays the value of the -``{{ name }}`` variable after being filtered through the ``lower`` filter, -which converts text to lowercase. Use a pipe (``|``) to apply a filter. - -Filters can be "chained." The output of one filter is applied to the next. -``{{ text|escape|linebreaks }}`` is a common idiom for escaping text contents, -then converting line breaks to ``<p>`` tags. - -Some filters take arguments. A filter argument looks like this: ``{{ -bio|truncatewords:30 }}``. This will display the first 30 words of the ``bio`` -variable. - -Filter arguments that contain spaces must be quoted; for example, to join a list -with commas and spaced you'd use ``{{ list|join:", " }}``. - -Django provides about thirty built-in template filters. You can read all about -them in the :ref:`built-in filter reference <ref-templates-builtins-filters>`. -To give you a taste of what's available, here are some of the more commonly used -template filters: - - :tfilter:`default` - If a variable is false or empty, use given default. Otherwise, use the - value of the variable - - For example:: - - {{ value|default:"nothing" }} - - If ``value`` isn't provided or is empty, the above will display - "``nothing``". - - :tfilter:`length` - Returns the length of the value. This works for both strings and lists; - for example:: - - {{ value|length }} - - If ``value`` is ``['a', 'b', 'c', 'd']``, the output will be ``4``. - - :tfilter:`striptags` - Strips all [X]HTML tags. For example:: - - {{ value|striptags }} - - If ``value`` is ``"<b>Joel</b> <button>is</button> a - <span>slug</span>"``, the output will be ``"Joel is a slug"``. - -Again, these are just a few examples; see the :ref:`built-in filter reference -<ref-templates-builtins-filters>` for the complete list. - -You can also create your own custom template filters; see -:doc:`/howto/custom-template-tags`. - -.. seealso:: - - Django's admin interface can include a complete reference of all template - tags and filters available for a given site. See - :doc:`/ref/contrib/admin/admindocs`. - -Tags -==== - -Tags look like this: ``{% tag %}``. Tags are more complex than variables: Some -create text in the output, some control flow by performing loops or logic, and -some load external information into the template to be used by later variables. - -Some tags require beginning and ending tags (i.e. ``{% tag %} ... tag contents -... {% endtag %}``). - -Django ships with about two dozen built-in template tags. You can read all about -them in the :ref:`built-in tag reference <ref-templates-builtins-tags>`. To give -you a taste of what's available, here are some of the more commonly used -tags: - - :ttag:`for` - Loop over each item in an array. For example, to display a list of athletes - provided in ``athlete_list``:: - - <ul> - {% for athlete in athlete_list %} - <li>{{ athlete.name }}</li> - {% endfor %} - </ul> - - :ttag:`if` and ``else`` - Evaluates a variable, and if that variable is "true" the contents of the - block are displayed:: - - {% if athlete_list %} - Number of athletes: {{ athlete_list|length }} - {% else %} - No athletes. - {% endif %} - - In the above, if ``athlete_list`` is not empty, the number of athletes - will be displayed by the ``{{ athlete_list|length }}`` variable. - - You can also use filters and various operators in the ``if`` tag:: - - {% if athlete_list|length > 1 %} - Team: {% for athlete in athlete_list %} ... {% endfor %} - {% else %} - Athlete: {{ athlete_list.0.name }} - {% endif %} - - :ttag:`block` and :ttag:`extends` - Set up `template inheritance`_ (see below), a powerful way - of cutting down on "boilerplate" in templates. - -Again, the above is only a selection of the whole list; see the :ref:`built-in -tag reference <ref-templates-builtins-tags>` for the complete list. - -You can also create your own custom template tags; see -:doc:`/howto/custom-template-tags`. - -.. seealso:: - - Django's admin interface can include a complete reference of all template - tags and filters available for a given site. See - :doc:`/ref/contrib/admin/admindocs`. - -Comments -======== - -To comment-out part of a line in a template, use the comment syntax: ``{# #}``. - -For example, this template would render as ``'hello'``:: - - {# greeting #}hello - -A comment can contain any template code, invalid or not. For example:: - - {# {% if foo %}bar{% else %} #} - -This syntax can only be used for single-line comments (no newlines are permitted -between the ``{#`` and ``#}`` delimiters). If you need to comment out a -multiline portion of the template, see the :ttag:`comment` tag. - -.. _template-inheritance: - -Template inheritance -==================== - -The most powerful -- and thus the most complex -- part of Django's template -engine is template inheritance. Template inheritance allows you to build a base -"skeleton" template that contains all the common elements of your site and -defines **blocks** that child templates can override. - -It's easiest to understand template inheritance by starting with an example:: - - <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> - <head> - <link rel="stylesheet" href="style.css" /> - <title>{% block title %}My amazing site{% endblock %}</title> - </head> - - <body> - <div id="sidebar"> - {% block sidebar %} - <ul> - <li><a href="/">Home</a></li> - <li><a href="/blog/">Blog</a></li> - </ul> - {% endblock %} - </div> - - <div id="content"> - {% block content %}{% endblock %} - </div> - </body> - </html> - -This template, which we'll call ``base.html``, defines a simple HTML skeleton -document that you might use for a simple two-column page. It's the job of -"child" templates to fill the empty blocks with content. - -In this example, the ``{% block %}`` tag defines three blocks that child -templates can fill in. All the ``block`` tag does is to tell the template -engine that a child template may override those portions of the template. - -A child template might look like this:: - - {% extends "base.html" %} - - {% block title %}My amazing blog{% endblock %} - - {% block content %} - {% for entry in blog_entries %} - <h2>{{ entry.title }}</h2> - <p>{{ entry.body }}</p> - {% endfor %} - {% endblock %} - -The ``{% extends %}`` tag is the key here. It tells the template engine that -this template "extends" another template. When the template system evaluates -this template, first it locates the parent -- in this case, "base.html". - -At that point, the template engine will notice the three ``{% block %}`` tags -in ``base.html`` and replace those blocks with the contents of the child -template. Depending on the value of ``blog_entries``, the output might look -like:: - - <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> - <head> - <link rel="stylesheet" href="style.css" /> - <title>My amazing blog</title> - </head> - - <body> - <div id="sidebar"> - <ul> - <li><a href="/">Home</a></li> - <li><a href="/blog/">Blog</a></li> - </ul> - </div> - - <div id="content"> - <h2>Entry one</h2> - <p>This is my first entry.</p> - - <h2>Entry two</h2> - <p>This is my second entry.</p> - </div> - </body> - </html> - -Note that since the child template didn't define the ``sidebar`` block, the -value from the parent template is used instead. Content within a ``{% block %}`` -tag in a parent template is always used as a fallback. - -You can use as many levels of inheritance as needed. One common way of using -inheritance is the following three-level approach: - - * Create a ``base.html`` template that holds the main look-and-feel of your - site. - * Create a ``base_SECTIONNAME.html`` template for each "section" of your - site. For example, ``base_news.html``, ``base_sports.html``. These - templates all extend ``base.html`` and include section-specific - styles/design. - * Create individual templates for each type of page, such as a news - article or blog entry. These templates extend the appropriate section - template. - -This approach maximizes code reuse and makes it easy to add items to shared -content areas, such as section-wide navigation. - -Here are some tips for working with inheritance: - - * If you use ``{% extends %}`` in a template, it must be the first template - tag in that template. Template inheritance won't work, otherwise. - - * More ``{% block %}`` tags in your base templates are better. Remember, - child templates don't have to define all parent blocks, so you can fill - in reasonable defaults in a number of blocks, then only define the ones - you need later. It's better to have more hooks than fewer hooks. - - * If you find yourself duplicating content in a number of templates, it - probably means you should move that content to a ``{% block %}`` in a - parent template. - - * If you need to get the content of the block from the parent template, - the ``{{ block.super }}`` variable will do the trick. This is useful - if you want to add to the contents of a parent block instead of - completely overriding it. Data inserted using ``{{ block.super }}`` will - not be automatically escaped (see the `next section`_), since it was - already escaped, if necessary, in the parent template. - - * For extra readability, you can optionally give a *name* to your - ``{% endblock %}`` tag. For example:: - - {% block content %} - ... - {% endblock content %} - - In larger templates, this technique helps you see which ``{% block %}`` - tags are being closed. - -Finally, note that you can't define multiple ``{% block %}`` tags with the same -name in the same template. This limitation exists because a block tag works in -"both" directions. That is, a block tag doesn't just provide a hole to fill -- -it also defines the content that fills the hole in the *parent*. If there were -two similarly-named ``{% block %}`` tags in a template, that template's parent -wouldn't know which one of the blocks' content to use. - -.. _next section: #automatic-html-escaping -.. _automatic-html-escaping: - -Automatic HTML escaping -======================= - -.. versionadded:: 1.0 - -When generating HTML from templates, there's always a risk that a variable will -include characters that affect the resulting HTML. For example, consider this -template fragment:: - - Hello, {{ name }}. - -At first, this seems like a harmless way to display a user's name, but consider -what would happen if the user entered his name as this:: - - <script>alert('hello')</script> - -With this name value, the template would be rendered as:: - - Hello, <script>alert('hello')</script> - -...which means the browser would pop-up a JavaScript alert box! - -Similarly, what if the name contained a ``'<'`` symbol, like this? - - <b>username - -That would result in a rendered template like this:: - - Hello, <b>username - -...which, in turn, would result in the remainder of the Web page being bolded! - -Clearly, user-submitted data shouldn't be trusted blindly and inserted directly -into your Web pages, because a malicious user could use this kind of hole to -do potentially bad things. This type of security exploit is called a -`Cross Site Scripting`_ (XSS) attack. - -To avoid this problem, you have two options: - - * One, you can make sure to run each untrusted variable through the - ``escape`` filter (documented below), which converts potentially harmful - HTML characters to unharmful ones. This was the default solution - in Django for its first few years, but the problem is that it puts the - onus on *you*, the developer / template author, to ensure you're escaping - everything. It's easy to forget to escape data. - - * Two, you can take advantage of Django's automatic HTML escaping. The - remainder of this section describes how auto-escaping works. - -By default in Django, every template automatically escapes the output -of every variable tag. Specifically, these five characters are -escaped: - - * ``<`` is converted to ``<`` - * ``>`` is converted to ``>`` - * ``'`` (single quote) is converted to ``'`` - * ``"`` (double quote) is converted to ``"`` - * ``&`` is converted to ``&`` - -Again, we stress that this behavior is on by default. If you're using Django's -template system, you're protected. - -.. _Cross Site Scripting: http://en.wikipedia.org/wiki/Cross-site_scripting - -How to turn it off ------------------- - -If you don't want data to be auto-escaped, on a per-site, per-template level or -per-variable level, you can turn it off in several ways. - -Why would you want to turn it off? Because sometimes, template variables -contain data that you *intend* to be rendered as raw HTML, in which case you -don't want their contents to be escaped. For example, you might store a blob of -HTML in your database and want to embed that directly into your template. Or, -you might be using Django's template system to produce text that is *not* HTML --- like an e-mail message, for instance. - -For individual variables -~~~~~~~~~~~~~~~~~~~~~~~~ - -To disable auto-escaping for an individual variable, use the ``safe`` filter:: - - This will be escaped: {{ data }} - This will not be escaped: {{ data|safe }} - -Think of *safe* as shorthand for *safe from further escaping* or *can be -safely interpreted as HTML*. In this example, if ``data`` contains ``'<b>'``, -the output will be:: - - This will be escaped: <b> - This will not be escaped: <b> - -For template blocks -~~~~~~~~~~~~~~~~~~~ - -To control auto-escaping for a template, wrap the template (or just a -particular section of the template) in the ``autoescape`` tag, like so:: - - {% autoescape off %} - Hello {{ name }} - {% endautoescape %} - -The ``autoescape`` tag takes either ``on`` or ``off`` as its argument. At -times, you might want to force auto-escaping when it would otherwise be -disabled. Here is an example template:: - - Auto-escaping is on by default. Hello {{ name }} - - {% autoescape off %} - This will not be auto-escaped: {{ data }}. - - Nor this: {{ other_data }} - {% autoescape on %} - Auto-escaping applies again: {{ name }} - {% endautoescape %} - {% endautoescape %} - -The auto-escaping tag passes its effect onto templates that extend the -current one as well as templates included via the ``include`` tag, just like -all block tags. For example:: - - # base.html - - {% autoescape off %} - <h1>{% block title %}{% endblock %}</h1> - {% block content %} - {% endblock %} - {% endautoescape %} - - - # child.html - - {% extends "base.html" %} - {% block title %}This & that{% endblock %} - {% block content %}{{ greeting }}{% endblock %} - -Because auto-escaping is turned off in the base template, it will also be -turned off in the child template, resulting in the following rendered -HTML when the ``greeting`` variable contains the string ``<b>Hello!</b>``:: - - <h1>This & that</h1> - <b>Hello!</b> - -Notes ------ - -Generally, template authors don't need to worry about auto-escaping very much. -Developers on the Python side (people writing views and custom filters) need to -think about the cases in which data shouldn't be escaped, and mark data -appropriately, so things Just Work in the template. - -If you're creating a template that might be used in situations where you're -not sure whether auto-escaping is enabled, then add an ``escape`` filter to any -variable that needs escaping. When auto-escaping is on, there's no danger of -the ``escape`` filter *double-escaping* data -- the ``escape`` filter does not -affect auto-escaped variables. - -String literals and automatic escaping --------------------------------------- - -As we mentioned earlier, filter arguments can be strings:: - - {{ data|default:"This is a string literal." }} - -All string literals are inserted **without** any automatic escaping into the -template -- they act as if they were all passed through the ``safe`` filter. -The reasoning behind this is that the template author is in control of what -goes into the string literal, so they can make sure the text is correctly -escaped when the template is written. - -This means you would write :: - - {{ data|default:"3 < 2" }} - -...rather than :: - - {{ data|default:"3 < 2" }} <-- Bad! Don't do this. - -This doesn't affect what happens to data coming from the variable itself. -The variable's contents are still automatically escaped, if necessary, because -they're beyond the control of the template author. - -.. _loading-custom-template-libraries: - -Custom tag and filter libraries -=============================== - -Certain applications provide custom tag and filter libraries. To access them in -a template, use the ``{% load %}`` tag:: - - {% load comments %} - - {% comment_form for blogs.entries entry.id with is_public yes %} - -In the above, the ``load`` tag loads the ``comments`` tag library, which then -makes the ``comment_form`` tag available for use. Consult the documentation -area in your admin to find the list of custom libraries in your installation. - -The ``{% load %}`` tag can take multiple library names, separated by spaces. -Example:: - - {% load comments i18n %} - -See :doc:`/howto/custom-template-tags` for information on writing your own custom -template libraries. - -Custom libraries and template inheritance ------------------------------------------ - -When you load a custom tag or filter library, the tags/filters are only made -available to the current template -- not any parent or child templates along -the template-inheritance path. - -For example, if a template ``foo.html`` has ``{% load comments %}``, a child -template (e.g., one that has ``{% extends "foo.html" %}``) will *not* have -access to the comments template tags and filters. The child template is -responsible for its own ``{% load comments %}``. - -This is a feature for the sake of maintainability and sanity. diff --git a/parts/django/docs/topics/testing.txt b/parts/django/docs/topics/testing.txt deleted file mode 100644 index 155f758..0000000 --- a/parts/django/docs/topics/testing.txt +++ /dev/null @@ -1,1613 +0,0 @@ -=========================== -Testing Django applications -=========================== - -.. module:: django.test - :synopsis: Testing tools for Django applications. - -Automated testing is an extremely useful bug-killing tool for the modern -Web developer. You can use a collection of tests -- a **test suite** -- to -solve, or avoid, a number of problems: - - * When you're writing new code, you can use tests to validate your code - works as expected. - - * When you're refactoring or modifying old code, you can use tests to - ensure your changes haven't affected your application's behavior - unexpectedly. - -Testing a Web application is a complex task, because a Web application is made -of several layers of logic -- from HTTP-level request handling, to form -validation and processing, to template rendering. With Django's test-execution -framework and assorted utilities, you can simulate requests, insert test data, -inspect your application's output and generally verify your code is doing what -it should be doing. - -The best part is, it's really easy. - -This document is split into two primary sections. First, we explain how to -write tests with Django. Then, we explain how to run them. - -Writing tests -============= - -There are two primary ways to write tests with Django, corresponding to the -two test frameworks that ship in the Python standard library. The two -frameworks are: - - * **Doctests** -- tests that are embedded in your functions' docstrings and - are written in a way that emulates a session of the Python interactive - interpreter. For example:: - - def my_func(a_list, idx): - """ - >>> a = ['larry', 'curly', 'moe'] - >>> my_func(a, 0) - 'larry' - >>> my_func(a, 1) - 'curly' - """ - return a_list[idx] - - * **Unit tests** -- tests that are expressed as methods on a Python class - that subclasses ``unittest.TestCase``. For example:: - - import unittest - - class MyFuncTestCase(unittest.TestCase): - def testBasic(self): - a = ['larry', 'curly', 'moe'] - self.assertEquals(my_func(a, 0), 'larry') - self.assertEquals(my_func(a, 1), 'curly') - -You can choose the test framework you like, depending on which syntax you -prefer, or you can mix and match, using one framework for some of your code and -the other framework for other code. You can also use any *other* Python test -frameworks, as we'll explain in a bit. - -Writing doctests ----------------- - -Doctests use Python's standard doctest_ module, which searches your docstrings -for statements that resemble a session of the Python interactive interpreter. -A full explanation of how doctest works is out of the scope of this document; -read Python's official documentation for the details. - -.. admonition:: What's a **docstring**? - - A good explanation of docstrings (and some guidelines for using them - effectively) can be found in :pep:`257`: - - A docstring is a string literal that occurs as the first statement in - a module, function, class, or method definition. Such a docstring - becomes the ``__doc__`` special attribute of that object. - - For example, this function has a docstring that describes what it does:: - - def add_two(num): - "Return the result of adding two to the provided number." - return num + 2 - - Because tests often make great documentation, putting tests directly in - your docstrings is an effective way to document *and* test your code. - -For a given Django application, the test runner looks for doctests in two -places: - - * The ``models.py`` file. You can define module-level doctests and/or a - doctest for individual models. It's common practice to put - application-level doctests in the module docstring and model-level - doctests in the model docstrings. - - * A file called ``tests.py`` in the application directory -- i.e., the - directory that holds ``models.py``. This file is a hook for any and all - doctests you want to write that aren't necessarily related to models. - -Here is an example model doctest:: - - # models.py - - from django.db import models - - class Animal(models.Model): - """ - An animal that knows how to make noise - - # Create some animals - >>> lion = Animal.objects.create(name="lion", sound="roar") - >>> cat = Animal.objects.create(name="cat", sound="meow") - - # Make 'em speak - >>> lion.speak() - 'The lion says "roar"' - >>> cat.speak() - 'The cat says "meow"' - """ - name = models.CharField(max_length=20) - sound = models.CharField(max_length=20) - - def speak(self): - return 'The %s says "%s"' % (self.name, self.sound) - -When you :ref:`run your tests <running-tests>`, the test runner will find this -docstring, notice that portions of it look like an interactive Python session, -and execute those lines while checking that the results match. - -In the case of model tests, note that the test runner takes care of creating -its own test database. That is, any test that accesses a database -- by -creating and saving model instances, for example -- will not affect your -production database. However, the database is not refreshed between doctests, -so if your doctest requires a certain state you should consider flushing the -database or loading a fixture. (See the section on fixtures, below, for more -on this.) Note that to use this feature, the database user Django is connecting -as must have ``CREATE DATABASE`` rights. - -For more details about how doctest works, see the `standard library -documentation for doctest`_. - -.. _doctest: http://docs.python.org/library/doctest.html -.. _standard library documentation for doctest: doctest_ - -Writing unit tests ------------------- - -Like doctests, Django's unit tests use a standard library module: unittest_. -This module uses a different way of defining tests, taking a class-based -approach. - -As with doctests, for a given Django application, the test runner looks for -unit tests in two places: - - * The ``models.py`` file. The test runner looks for any subclass of - ``unittest.TestCase`` in this module. - - * A file called ``tests.py`` in the application directory -- i.e., the - directory that holds ``models.py``. Again, the test runner looks for any - subclass of ``unittest.TestCase`` in this module. - -This example ``unittest.TestCase`` subclass is equivalent to the example given -in the doctest section above:: - - import unittest - from myapp.models import Animal - - class AnimalTestCase(unittest.TestCase): - def setUp(self): - self.lion = Animal.objects.create(name="lion", sound="roar") - self.cat = Animal.objects.create(name="cat", sound="meow") - - def testSpeaking(self): - self.assertEquals(self.lion.speak(), 'The lion says "roar"') - self.assertEquals(self.cat.speak(), 'The cat says "meow"') - -When you :ref:`run your tests <running-tests>`, the default behavior of the -test utility is to find all the test cases (that is, subclasses of -``unittest.TestCase``) in ``models.py`` and ``tests.py``, automatically build a -test suite out of those test cases, and run that suite. - -There is a second way to define the test suite for a module: if you define a -function called ``suite()`` in either ``models.py`` or ``tests.py``, the -Django test runner will use that function to construct the test suite for that -module. This follows the `suggested organization`_ for unit tests. See the -Python documentation for more details on how to construct a complex test -suite. - -For more details about ``unittest``, see the `standard library unittest -documentation`_. - -.. _unittest: http://docs.python.org/library/unittest.html -.. _standard library unittest documentation: unittest_ -.. _suggested organization: http://docs.python.org/library/unittest.html#organizing-tests - -Which should I use? -------------------- - -Because Django supports both of the standard Python test frameworks, it's up to -you and your tastes to decide which one to use. You can even decide to use -*both*. - -For developers new to testing, however, this choice can seem confusing. Here, -then, are a few key differences to help you decide which approach is right for -you: - - * If you've been using Python for a while, ``doctest`` will probably feel - more "pythonic". It's designed to make writing tests as easy as possible, - so it requires no overhead of writing classes or methods. You simply put - tests in docstrings. This has the added advantage of serving as - documentation (and correct documentation, at that!). - - If you're just getting started with testing, using doctests will probably - get you started faster. - - * The ``unittest`` framework will probably feel very familiar to developers - coming from Java. ``unittest`` is inspired by Java's JUnit, so you'll - feel at home with this method if you've used JUnit or any test framework - inspired by JUnit. - - * If you need to write a bunch of tests that share similar code, then - you'll appreciate the ``unittest`` framework's organization around - classes and methods. This makes it easy to abstract common tasks into - common methods. The framework also supports explicit setup and/or cleanup - routines, which give you a high level of control over the environment - in which your test cases are run. - -Again, remember that you can use both systems side-by-side (even in the same -app). In the end, most projects will eventually end up using both. Each shines -in different circumstances. - -.. _running-tests: - -Running tests -============= - -Once you've written tests, run them using the :djadmin:`test` command of -your project's ``manage.py`` utility:: - - $ ./manage.py test - -By default, this will run every test in every application in -:setting:`INSTALLED_APPS`. If you only want to run tests for a particular -application, add the application name to the command line. For example, if your -:setting:`INSTALLED_APPS` contains ``'myproject.polls'`` and -``'myproject.animals'``, you can run the ``myproject.animals`` unit tests alone -with this command:: - - $ ./manage.py test animals - -Note that we used ``animals``, not ``myproject.animals``. - -.. versionadded:: 1.0 - You can now choose which test to run. - -You can be even *more* specific by naming an individual test case. To -run a single test case in an application (for example, the -``AnimalTestCase`` described in the "Writing unit tests" section), add -the name of the test case to the label on the command line:: - - $ ./manage.py test animals.AnimalTestCase - -And it gets even more granular than that! To run a *single* test -method inside a test case, add the name of the test method to the -label:: - - $ ./manage.py test animals.AnimalTestCase.testFluffyAnimals - -.. versionadded:: 1.2 - The ability to select individual doctests was added. - -You can use the same rules if you're using doctests. Django will use the -test label as a path to the test method or class that you want to run. -If your ``models.py`` or ``tests.py`` has a function with a doctest, or -class with a class-level doctest, you can invoke that test by appending the -name of the test method or class to the label:: - - $ ./manage.py test animals.classify - -If you want to run the doctest for a specific method in a class, add the -name of the method to the label:: - - $ ./manage.py test animals.Classifier.run - -If you're using a ``__test__`` dictionary to specify doctests for a -module, Django will use the label as a key in the ``__test__`` dictionary -for defined in ``models.py`` and ``tests.py``. - -.. versionadded:: 1.2 - You can now trigger a graceful exit from a test run by pressing ``Ctrl-C``. - -If you press ``Ctrl-C`` while the tests are running, the test runner will -wait for the currently running test to complete and then exit gracefully. -During a graceful exit the test runner will output details of any test -failures, report on how many tests were run and how many errors and failures -were encountered, and destroy any test databases as usual. Thus pressing -``Ctrl-C`` can be very useful if you forget to pass the :djadminopt:`--failfast` -option, notice that some tests are unexpectedly failing, and want to get details -on the failures without waiting for the full test run to complete. - -If you do not want to wait for the currently running test to finish, you -can press ``Ctrl-C`` a second time and the test run will halt immediately, -but not gracefully. No details of the tests run before the interruption will -be reported, and any test databases created by the run will not be destroyed. - -.. admonition:: Test with warnings enabled - - It is a good idea to run your tests with ``python -Wall manage.py - test``. This will allow you to catch any deprecation warnings that - might be in your code. Django (as well as many other libraries) use - warnings to flag when features are deprecated. It can also flag - areas in your code that are not strictly wrong, but may benefit - from a better implementation. - -Running tests outside the test runner -------------------------------------- - -If you want to run tests outside of ``./manage.py test`` -- for example, -from a shell prompt -- you will need to set up the test -environment first. Django provides a convenience method to do this:: - - >>> from django.test.utils import setup_test_environment - >>> setup_test_environment() - -This convenience method sets up the test database, and puts other -Django features into modes that allow for repeatable testing. - -The call to :meth:`~django.test.utils.setup_test_environment` is made -automatically as part of the setup of `./manage.py test`. You only -need to manually invoke this method if you're not using running your -tests via Django's test runner. - -The test database ------------------ - -Tests that require a database (namely, model tests) will not use your "real" -(production) database. Separate, blank databases are created for the tests. - -Regardless of whether the tests pass or fail, the test databases are destroyed -when all the tests have been executed. - -By default the test databases get their names by prepending ``test_`` -to the value of the :setting:`NAME` settings for the databases -defined in :setting:`DATABASES`. When using the SQLite database engine -the tests will by default use an in-memory database (i.e., the -database will be created in memory, bypassing the filesystem -entirely!). If you want to use a different database name, specify -:setting:`TEST_NAME` in the dictionary for any given database in -:setting:`DATABASES`. - -Aside from using a separate database, the test runner will otherwise -use all of the same database settings you have in your settings file: -:setting:`ENGINE`, :setting:`USER`, :setting:`HOST`, etc. The test -database is created by the user specified by ``USER``, so you'll need -to make sure that the given user account has sufficient privileges to -create a new database on the system. - -.. versionadded:: 1.0 - -For fine-grained control over the character encoding of your test -database, use the :setting:`TEST_CHARSET` option. If you're using -MySQL, you can also use the :setting:`TEST_COLLATION` option to -control the particular collation used by the test database. See the -:doc:`settings documentation </ref/settings>` for details of these -advanced settings. - -.. _topics-testing-masterslave: - -Testing master/slave configurations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.2 - -If you're testing a multiple database configuration with master/slave -replication, this strategy of creating test databases poses a problem. -When the test databases are created, there won't be any replication, -and as a result, data created on the master won't be seen on the -slave. - -To compensate for this, Django allows you to define that a database is -a *test mirror*. Consider the following (simplified) example database -configuration:: - - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.mysql', - 'NAME': 'myproject', - 'HOST': 'dbmaster', - # ... plus some other settings - }, - 'slave': { - 'ENGINE': 'django.db.backends.mysql', - 'NAME': 'myproject', - 'HOST': 'dbslave', - 'TEST_MIRROR': 'default' - # ... plus some other settings - } - } - -In this setup, we have two database servers: ``dbmaster``, described -by the database alias ``default``, and ``dbslave`` described by the -alias ``slave``. As you might expect, ``dbslave`` has been configured -by the database administrator as a read slave of ``dbmaster``, so in -normal activity, any write to ``default`` will appear on ``slave``. - -If Django created two independent test databases, this would break any -tests that expected replication to occur. However, the ``slave`` -database has been configured as a test mirror (using the -:setting:`TEST_MIRROR` setting), indicating that under testing, -``slave`` should be treated as a mirror of ``default``. - -When the test environment is configured, a test version of ``slave`` -will *not* be created. Instead the connection to ``slave`` -will be redirected to point at ``default``. As a result, writes to -``default`` will appear on ``slave`` -- but because they are actually -the same database, not because there is data replication between the -two databases. - -.. _topics-testing-creation-dependencies: - -Controlling creation order for test databases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.2.4 - -By default, Django will always create the ``default`` database first. -However, no guarantees are made on the creation order of any other -databases in your test setup. - -If your database configuration requires a specific creation order, you -can specify the dependencies that exist using the -:setting:`TEST_DEPENDENCIES` setting. Consider the following -(simplified) example database configuration:: - - DATABASES = { - 'default': { - # ... db settings - 'TEST_DEPENDENCIES': ['diamonds'] - }, - 'diamonds': { - # ... db settings - }, - 'clubs': { - # ... db settings - 'TEST_DEPENDENCIES': ['diamonds'] - }, - 'spades': { - # ... db settings - 'TEST_DEPENDENCIES': ['diamonds','hearts'] - }, - 'hearts': { - # ... db settings - 'TEST_DEPENDENCIES': ['diamonds','clubs'] - } - } - -Under this configuration, the ``diamonds`` database will be created first, -as it is the only database alias without dependencies. The ``default``` and -``clubs`` alias will be created next (although the order of creation of this -pair is not guaranteed); then ``hearts``; and finally ``spades``. - -If there are any circular dependencies in the -:setting:`TEST_DEPENDENCIES` definition, an ``ImproperlyConfigured`` -exception will be raised. - -Other test conditions ---------------------- - -Regardless of the value of the :setting:`DEBUG` setting in your configuration -file, all Django tests run with :setting:`DEBUG`\=False. This is to ensure that -the observed output of your code matches what will be seen in a production -setting. - -Understanding the test output ------------------------------ - -When you run your tests, you'll see a number of messages as the test runner -prepares itself. You can control the level of detail of these messages with the -``verbosity`` option on the command line:: - - Creating test database... - Creating table myapp_animal - Creating table myapp_mineral - Loading 'initial_data' fixtures... - No fixtures found. - -This tells you that the test runner is creating a test database, as described -in the previous section. - -Once the test database has been created, Django will run your tests. -If everything goes well, you'll see something like this:: - - ---------------------------------------------------------------------- - Ran 22 tests in 0.221s - - OK - -If there are test failures, however, you'll see full details about which tests -failed:: - - ====================================================================== - FAIL: Doctest: ellington.core.throttle.models - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "/dev/django/test/doctest.py", line 2153, in runTest - raise self.failureException(self.format_failure(new.getvalue())) - AssertionError: Failed doctest test for myapp.models - File "/dev/myapp/models.py", line 0, in models - - ---------------------------------------------------------------------- - File "/dev/myapp/models.py", line 14, in myapp.models - Failed example: - throttle.check("actor A", "action one", limit=2, hours=1) - Expected: - True - Got: - False - - ---------------------------------------------------------------------- - Ran 2 tests in 0.048s - - FAILED (failures=1) - -A full explanation of this error output is beyond the scope of this document, -but it's pretty intuitive. You can consult the documentation of Python's -``unittest`` library for details. - -Note that the return code for the test-runner script is the total number of -failed and erroneous tests. If all the tests pass, the return code is 0. This -feature is useful if you're using the test-runner script in a shell script and -need to test for success or failure at that level. - -Testing tools -============= - -Django provides a small set of tools that come in handy when writing tests. - -The test client ---------------- - -.. module:: django.test.client - :synopsis: Django's test client. - -The test client is a Python class that acts as a dummy Web browser, allowing -you to test your views and interact with your Django-powered application -programmatically. - -Some of the things you can do with the test client are: - - * Simulate GET and POST requests on a URL and observe the response -- - everything from low-level HTTP (result headers and status codes) to - page content. - - * Test that the correct view is executed for a given URL. - - * Test that a given request is rendered by a given Django template, with - a template context that contains certain values. - -Note that the test client is not intended to be a replacement for Twill_, -Selenium_, or other "in-browser" frameworks. Django's test client has -a different focus. In short: - - * Use Django's test client to establish that the correct view is being - called and that the view is collecting the correct context data. - - * Use in-browser frameworks such as Twill and Selenium to test *rendered* - HTML and the *behavior* of Web pages, namely JavaScript functionality. - -A comprehensive test suite should use a combination of both test types. - -.. _Twill: http://twill.idyll.org/ -.. _Selenium: http://seleniumhq.org/ - -Overview and a quick example -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To use the test client, instantiate ``django.test.client.Client`` and retrieve -Web pages:: - - >>> from django.test.client import Client - >>> c = Client() - >>> response = c.post('/login/', {'username': 'john', 'password': 'smith'}) - >>> response.status_code - 200 - >>> response = c.get('/customer/details/') - >>> response.content - '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...' - -As this example suggests, you can instantiate ``Client`` from within a session -of the Python interactive interpreter. - -Note a few important things about how the test client works: - - * The test client does *not* require the Web server to be running. In fact, - it will run just fine with no Web server running at all! That's because - it avoids the overhead of HTTP and deals directly with the Django - framework. This helps make the unit tests run quickly. - - * When retrieving pages, remember to specify the *path* of the URL, not the - whole domain. For example, this is correct:: - - >>> c.get('/login/') - - This is incorrect:: - - >>> c.get('http://www.example.com/login/') - - The test client is not capable of retrieving Web pages that are not - powered by your Django project. If you need to retrieve other Web pages, - use a Python standard library module such as urllib_ or urllib2_. - - * To resolve URLs, the test client uses whatever URLconf is pointed-to by - your :setting:`ROOT_URLCONF` setting. - - * Although the above example would work in the Python interactive - interpreter, some of the test client's functionality, notably the - template-related functionality, is only available *while tests are - running*. - - The reason for this is that Django's test runner performs a bit of black - magic in order to determine which template was loaded by a given view. - This black magic (essentially a patching of Django's template system in - memory) only happens during test running. - - * By default, the test client will disable any CSRF checks - performed by your site. - - .. versionadded:: 1.2.2 - - If, for some reason, you *want* the test client to perform CSRF - checks, you can create an instance of the test client that - enforces CSRF checks. To do this, pass in the - ``enforce_csrf_checks`` argument when you construct your - client:: - - >>> from django.test import Client - >>> csrf_client = Client(enforce_csrf_checks=True) - - -.. _urllib: http://docs.python.org/library/urllib.html -.. _urllib2: http://docs.python.org/library/urllib2.html - -Making requests -~~~~~~~~~~~~~~~ - -Use the ``django.test.client.Client`` class to make requests. It requires no -arguments at time of construction: - -.. class:: Client() - - Once you have a ``Client`` instance, you can call any of the following - methods: - - .. method:: Client.get(path, data={}, follow=False, **extra) - - - Makes a GET request on the provided ``path`` and returns a ``Response`` - object, which is documented below. - - The key-value pairs in the ``data`` dictionary are used to create a GET - data payload. For example:: - - >>> c = Client() - >>> c.get('/customers/details/', {'name': 'fred', 'age': 7}) - - ...will result in the evaluation of a GET request equivalent to:: - - /customers/details/?name=fred&age=7 - - The ``extra`` keyword arguments parameter can be used to specify - headers to be sent in the request. For example:: - - >>> c = Client() - >>> c.get('/customers/details/', {'name': 'fred', 'age': 7}, - ... HTTP_X_REQUESTED_WITH='XMLHttpRequest') - - ...will send the HTTP header ``HTTP_X_REQUESTED_WITH`` to the - details view, which is a good way to test code paths that use the - :meth:`django.http.HttpRequest.is_ajax()` method. - - .. versionadded:: 1.1 - - If you already have the GET arguments in URL-encoded form, you can - use that encoding instead of using the data argument. For example, - the previous GET request could also be posed as:: - - >>> c = Client() - >>> c.get('/customers/details/?name=fred&age=7') - - If you provide a URL with both an encoded GET data and a data argument, - the data argument will take precedence. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - If you had an url ``/redirect_me/`` that redirected to ``/next/``, that - redirected to ``/final/``, this is what you'd see:: - - >>> response = c.get('/redirect_me/', follow=True) - >>> response.redirect_chain - [(u'http://testserver/next/', 302), (u'http://testserver/final/', 302)] - - .. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra) - - Makes a POST request on the provided ``path`` and returns a - ``Response`` object, which is documented below. - - The key-value pairs in the ``data`` dictionary are used to submit POST - data. For example:: - - >>> c = Client() - >>> c.post('/login/', {'name': 'fred', 'passwd': 'secret'}) - - ...will result in the evaluation of a POST request to this URL:: - - /login/ - - ...with this POST data:: - - name=fred&passwd=secret - - If you provide ``content_type`` (e.g., ``text/xml`` for an XML - payload), the contents of ``data`` will be sent as-is in the POST - request, using ``content_type`` in the HTTP ``Content-Type`` header. - - If you don't provide a value for ``content_type``, the values in - ``data`` will be transmitted with a content type of - ``multipart/form-data``. In this case, the key-value pairs in ``data`` - will be encoded as a multipart message and used to create the POST data - payload. - - To submit multiple values for a given key -- for example, to specify - the selections for a ``<select multiple>`` -- provide the values as a - list or tuple for the required key. For example, this value of ``data`` - would submit three selected values for the field named ``choices``:: - - {'choices': ('a', 'b', 'd')} - - Submitting files is a special case. To POST a file, you need only - provide the file field name as a key, and a file handle to the file you - wish to upload as a value. For example:: - - >>> c = Client() - >>> f = open('wishlist.doc') - >>> c.post('/customers/wishes/', {'name': 'fred', 'attachment': f}) - >>> f.close() - - (The name ``attachment`` here is not relevant; use whatever name your - file-processing code expects.) - - Note that if you wish to use the same file handle for multiple - ``post()`` calls then you will need to manually reset the file - pointer between posts. The easiest way to do this is to - manually close the file after it has been provided to - ``post()``, as demonstrated above. - - You should also ensure that the file is opened in a way that - allows the data to be read. If your file contains binary data - such as an image, this means you will need to open the file in - ``rb`` (read binary) mode. - - The ``extra`` argument acts the same as for :meth:`Client.get`. - - .. versionchanged:: 1.1 - - If the URL you request with a POST contains encoded parameters, these - parameters will be made available in the request.GET data. For example, - if you were to make the request:: - - >>> c.post('/login/?visitor=true', {'name': 'fred', 'passwd': 'secret'}) - - ... the view handling this request could interrogate request.POST - to retrieve the username and password, and could interrogate request.GET - to determine if the user was a visitor. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - .. method:: Client.head(path, data={}, follow=False, **extra) - - .. versionadded:: 1.1 - - Makes a HEAD request on the provided ``path`` and returns a ``Response`` - object. Useful for testing RESTful interfaces. Acts just like - :meth:`Client.get` except it does not return a message body. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - .. method:: Client.options(path, data={}, follow=False, **extra) - - .. versionadded:: 1.1 - - Makes an OPTIONS request on the provided ``path`` and returns a - ``Response`` object. Useful for testing RESTful interfaces. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - The ``extra`` argument acts the same as for :meth:`Client.get`. - - .. method:: Client.put(path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra) - - .. versionadded:: 1.1 - - Makes a PUT request on the provided ``path`` and returns a - ``Response`` object. Useful for testing RESTful interfaces. Acts just - like :meth:`Client.post` except with the PUT request method. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - .. method:: Client.delete(path, follow=False, **extra) - - .. versionadded:: 1.1 - - Makes an DELETE request on the provided ``path`` and returns a - ``Response`` object. Useful for testing RESTful interfaces. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - The ``extra`` argument acts the same as for :meth:`Client.get`. - - .. method:: Client.login(**credentials) - - .. versionadded:: 1.0 - - If your site uses Django's :doc:`authentication system</topics/auth>` - and you deal with logging in users, you can use the test client's - ``login()`` method to simulate the effect of a user logging into the - site. - - After you call this method, the test client will have all the cookies - and session data required to pass any login-based tests that may form - part of a view. - - The format of the ``credentials`` argument depends on which - :ref:`authentication backend <authentication-backends>` you're using - (which is configured by your :setting:`AUTHENTICATION_BACKENDS` - setting). If you're using the standard authentication backend provided - by Django (``ModelBackend``), ``credentials`` should be the user's - username and password, provided as keyword arguments:: - - >>> c = Client() - >>> c.login(username='fred', password='secret') - - # Now you can access a view that's only available to logged-in users. - - If you're using a different authentication backend, this method may - require different credentials. It requires whichever credentials are - required by your backend's ``authenticate()`` method. - - ``login()`` returns ``True`` if it the credentials were accepted and - login was successful. - - Finally, you'll need to remember to create user accounts before you can - use this method. As we explained above, the test runner is executed - using a test database, which contains no users by default. As a result, - user accounts that are valid on your production site will not work - under test conditions. You'll need to create users as part of the test - suite -- either manually (using the Django model API) or with a test - fixture. Remember that if you want your test user to have a password, - you can't set the user's password by setting the password attribute - directly -- you must use the - :meth:`~django.contrib.auth.models.User.set_password()` function to - store a correctly hashed password. Alternatively, you can use the - :meth:`~django.contrib.auth.models.UserManager.create_user` helper - method to create a new user with a correctly hashed password. - - .. method:: Client.logout() - - .. versionadded:: 1.0 - - If your site uses Django's :doc:`authentication system</topics/auth>`, - the ``logout()`` method can be used to simulate the effect of a user - logging out of your site. - - After you call this method, the test client will have all the cookies - and session data cleared to defaults. Subsequent requests will appear - to come from an AnonymousUser. - -Testing responses -~~~~~~~~~~~~~~~~~ - -The ``get()`` and ``post()`` methods both return a ``Response`` object. This -``Response`` object is *not* the same as the ``HttpResponse`` object returned -Django views; the test response object has some additional data useful for -test code to verify. - -Specifically, a ``Response`` object has the following attributes: - -.. class:: Response() - - .. attribute:: client - - The test client that was used to make the request that resulted in the - response. - - .. attribute:: content - - The body of the response, as a string. This is the final page content as - rendered by the view, or any error message. - - .. attribute:: context - - The template ``Context`` instance that was used to render the template that - produced the response content. - - If the rendered page used multiple templates, then ``context`` will be a - list of ``Context`` objects, in the order in which they were rendered. - - .. versionadded:: 1.1 - - Regardless of the number of templates used during rendering, you can - retrieve context values using the ``[]`` operator. For example, the - context variable ``name`` could be retrieved using:: - - >>> response = client.get('/foo/') - >>> response.context['name'] - 'Arthur' - - .. attribute:: request - - The request data that stimulated the response. - - .. attribute:: status_code - - The HTTP status of the response, as an integer. See RFC2616_ for a full - list of HTTP status codes. - - .. attribute:: template - - The ``Template`` instance that was used to render the final content. Use - ``template.name`` to get the template's file name, if the template was - loaded from a file. (The name is a string such as ``'admin/index.html'``.) - - If the rendered page used multiple templates -- e.g., using :ref:`template - inheritance<template-inheritance>` -- then ``template`` will be a list of - ``Template`` instances, in the order in which they were rendered. - -You can also use dictionary syntax on the response object to query the value -of any settings in the HTTP headers. For example, you could determine the -content type of a response using ``response['Content-Type']``. - -.. _RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - -Exceptions -~~~~~~~~~~ - -If you point the test client at a view that raises an exception, that exception -will be visible in the test case. You can then use a standard ``try...except`` -block or ``unittest.TestCase.assertRaises()`` to test for exceptions. - -The only exceptions that are not visible to the test client are ``Http404``, -``PermissionDenied`` and ``SystemExit``. Django catches these exceptions -internally and converts them into the appropriate HTTP response codes. In these -cases, you can check ``response.status_code`` in your test. - -Persistent state -~~~~~~~~~~~~~~~~ - -The test client is stateful. If a response returns a cookie, then that cookie -will be stored in the test client and sent with all subsequent ``get()`` and -``post()`` requests. - -Expiration policies for these cookies are not followed. If you want a cookie -to expire, either delete it manually or create a new ``Client`` instance (which -will effectively delete all cookies). - -A test client has two attributes that store persistent state information. You -can access these properties as part of a test condition. - -.. attribute:: Client.cookies - - A Python ``SimpleCookie`` object, containing the current values of all the - client cookies. See the `Cookie module documentation`_ for more. - -.. attribute:: Client.session - - A dictionary-like object containing session information. See the - :doc:`session documentation</topics/http/sessions>` for full details. - - To modify the session and then save it, it must be stored in a variable - first (because a new ``SessionStore`` is created every time this property - is accessed):: - - def test_something(self): - session = self.client.session - session['somekey'] = 'test' - session.save() - -.. _Cookie module documentation: http://docs.python.org/library/cookie.html - -Example -~~~~~~~ - -The following is a simple unit test using the test client:: - - import unittest - from django.test.client import Client - - class SimpleTest(unittest.TestCase): - def setUp(self): - # Every test needs a client. - self.client = Client() - - def test_details(self): - # Issue a GET request. - response = self.client.get('/customer/details/') - - # Check that the response is 200 OK. - self.failUnlessEqual(response.status_code, 200) - - # Check that the rendered context contains 5 customers. - self.failUnlessEqual(len(response.context['customers']), 5) - -TestCase --------- - -.. currentmodule:: django.test - -Normal Python unit test classes extend a base class of ``unittest.TestCase``. -Django provides an extension of this base class: - -.. class:: TestCase() - -This class provides some additional capabilities that can be useful for testing -Web sites. - -Converting a normal ``unittest.TestCase`` to a Django ``TestCase`` is easy: -just change the base class of your test from ``unittest.TestCase`` to -``django.test.TestCase``. All of the standard Python unit test functionality -will continue to be available, but it will be augmented with some useful -additions. - -.. versionadded:: 1.1 - -.. class:: TransactionTestCase() - -Django ``TestCase`` classes make use of database transaction facilities, if -available, to speed up the process of resetting the database to a known state -at the beginning of each test. A consequence of this, however, is that the -effects of transaction commit and rollback cannot be tested by a Django -``TestCase`` class. If your test requires testing of such transactional -behavior, you should use a Django ``TransactionTestCase``. - -``TransactionTestCase`` and ``TestCase`` are identical except for the manner -in which the database is reset to a known state and the ability for test code -to test the effects of commit and rollback. A ``TransactionTestCase`` resets -the database before the test runs by truncating all tables and reloading -initial data. A ``TransactionTestCase`` may call commit and rollback and -observe the effects of these calls on the database. - -A ``TestCase``, on the other hand, does not truncate tables and reload initial -data at the beginning of a test. Instead, it encloses the test code in a -database transaction that is rolled back at the end of the test. It also -prevents the code under test from issuing any commit or rollback operations -on the database, to ensure that the rollback at the end of the test restores -the database to its initial state. In order to guarantee that all ``TestCase`` -code starts with a clean database, the Django test runner runs all ``TestCase`` -tests first, before any other tests (e.g. doctests) that may alter the -database without restoring it to its original state. - -When running on a database that does not support rollback (e.g. MySQL with the -MyISAM storage engine), ``TestCase`` falls back to initializing the database -by truncating tables and reloading initial data. - - -.. note:: - The ``TestCase`` use of rollback to un-do the effects of the test code - may reveal previously-undetected errors in test code. For example, - test code that assumes primary keys values will be assigned starting at - one may find that assumption no longer holds true when rollbacks instead - of table truncation are being used to reset the database. Similarly, - the reordering of tests so that all ``TestCase`` classes run first may - reveal unexpected dependencies on test case ordering. In such cases a - quick fix is to switch the ``TestCase`` to a ``TransactionTestCase``. - A better long-term fix, that allows the test to take advantage of the - speed benefit of ``TestCase``, is to fix the underlying test problem. - - -Default test client -~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. attribute:: TestCase.client - -Every test case in a ``django.test.TestCase`` instance has access to an -instance of a Django test client. This client can be accessed as -``self.client``. This client is recreated for each test, so you don't have to -worry about state (such as cookies) carrying over from one test to another. - -This means, instead of instantiating a ``Client`` in each test:: - - import unittest - from django.test.client import Client - - class SimpleTest(unittest.TestCase): - def test_details(self): - client = Client() - response = client.get('/customer/details/') - self.failUnlessEqual(response.status_code, 200) - - def test_index(self): - client = Client() - response = client.get('/customer/index/') - self.failUnlessEqual(response.status_code, 200) - -...you can just refer to ``self.client``, like so:: - - from django.test import TestCase - - class SimpleTest(TestCase): - def test_details(self): - response = self.client.get('/customer/details/') - self.failUnlessEqual(response.status_code, 200) - - def test_index(self): - response = self.client.get('/customer/index/') - self.failUnlessEqual(response.status_code, 200) - -.. _topics-testing-fixtures: - -Fixture loading -~~~~~~~~~~~~~~~ - -.. attribute:: TestCase.fixtures - -A test case for a database-backed Web site isn't much use if there isn't any -data in the database. To make it easy to put test data into the database, -Django's custom ``TestCase`` class provides a way of loading **fixtures**. - -A fixture is a collection of data that Django knows how to import into a -database. For example, if your site has user accounts, you might set up a -fixture of fake user accounts in order to populate your database during tests. - -The most straightforward way of creating a fixture is to use the -:djadmin:`manage.py dumpdata <dumpdata>` command. This assumes you -already have some data in your database. See the :djadmin:`dumpdata -documentation<dumpdata>` for more details. - -.. note:: - If you've ever run :djadmin:`manage.py syncdb<syncdb>`, you've - already used a fixture without even knowing it! When you call - :djadmin:`syncdb` in the database for the first time, Django - installs a fixture called ``initial_data``. This gives you a way - of populating a new database with any initial data, such as a - default set of categories. - - Fixtures with other names can always be installed manually using - the :djadmin:`manage.py loaddata<loaddata>` command. - -Once you've created a fixture and placed it in a ``fixtures`` directory in one -of your :setting:`INSTALLED_APPS`, you can use it in your unit tests by -specifying a ``fixtures`` class attribute on your :class:`django.test.TestCase` -subclass:: - - from django.test import TestCase - from myapp.models import Animal - - class AnimalTestCase(TestCase): - fixtures = ['mammals.json', 'birds'] - - def setUp(self): - # Test definitions as before. - call_setup_methods() - - def testFluffyAnimals(self): - # A test that uses the fixtures. - call_some_test_code() - -Here's specifically what will happen: - - * At the start of each test case, before ``setUp()`` is run, Django will - flush the database, returning the database to the state it was in - directly after :djadmin:`syncdb` was called. - - * Then, all the named fixtures are installed. In this example, Django will - install any JSON fixture named ``mammals``, followed by any fixture named - ``birds``. See the :djadmin:`loaddata` documentation for more - details on defining and installing fixtures. - -This flush/load procedure is repeated for each test in the test case, so you -can be certain that the outcome of a test will not be affected by another test, -or by the order of test execution. - -URLconf configuration -~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. attribute:: TestCase.urls - -If your application provides views, you may want to include tests that use the -test client to exercise those views. However, an end user is free to deploy the -views in your application at any URL of their choosing. This means that your -tests can't rely upon the fact that your views will be available at a -particular URL. - -In order to provide a reliable URL space for your test, -``django.test.TestCase`` provides the ability to customize the URLconf -configuration for the duration of the execution of a test suite. If your -``TestCase`` instance defines an ``urls`` attribute, the ``TestCase`` will use -the value of that attribute as the ``ROOT_URLCONF`` for the duration of that -test. - -For example:: - - from django.test import TestCase - - class TestMyViews(TestCase): - urls = 'myapp.test_urls' - - def testIndexPageView(self): - # Here you'd test your view using ``Client``. - call_some_test_code() - -This test case will use the contents of ``myapp.test_urls`` as the -URLconf for the duration of the test case. - -.. _emptying-test-outbox: - -Multi-database support -~~~~~~~~~~~~~~~~~~~~~~ - -.. attribute:: TestCase.multi_db - -.. versionadded:: 1.2 - -Django sets up a test database corresponding to every database that is -defined in the :setting:`DATABASES` definition in your settings -file. However, a big part of the time taken to run a Django TestCase -is consumed by the call to ``flush`` that ensures that you have a -clean database at the start of each test run. If you have multiple -databases, multiple flushes are required (one for each database), -which can be a time consuming activity -- especially if your tests -don't need to test multi-database activity. - -As an optimization, Django only flushes the ``default`` database at -the start of each test run. If your setup contains multiple databases, -and you have a test that requires every database to be clean, you can -use the ``multi_db`` attribute on the test suite to request a full -flush. - -For example:: - - class TestMyViews(TestCase): - multi_db = True - - def testIndexPageView(self): - call_some_test_code() - -This test case will flush *all* the test databases before running -``testIndexPageView``. - -Emptying the test outbox -~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -If you use Django's custom ``TestCase`` class, the test runner will clear the -contents of the test e-mail outbox at the start of each test case. - -For more detail on e-mail services during tests, see `E-mail services`_. - -Assertions -~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. versionchanged:: 1.2 - Addded ``msg_prefix`` argument. - -As Python's normal ``unittest.TestCase`` class implements assertion methods -such as ``assertTrue`` and ``assertEquals``, Django's custom ``TestCase`` class -provides a number of custom assertion methods that are useful for testing Web -applications: - -The failure messages given by the assertion methods can be customized -with the ``msg_prefix`` argument. This string will be prefixed to any -failure message generated by the assertion. This allows you to provide -additional details that may help you to identify the location and -cause of an failure in your test suite. - -.. method:: TestCase.assertContains(response, text, count=None, status_code=200, msg_prefix='') - - Asserts that a ``Response`` instance produced the given ``status_code`` and - that ``text`` appears in the content of the response. If ``count`` is - provided, ``text`` must occur exactly ``count`` times in the response. - -.. method:: TestCase.assertNotContains(response, text, status_code=200, msg_prefix='') - - Asserts that a ``Response`` instance produced the given ``status_code`` and - that ``text`` does not appears in the content of the response. - -.. method:: TestCase.assertFormError(response, form, field, errors, msg_prefix='') - - Asserts that a field on a form raises the provided list of errors when - rendered on the form. - - ``form`` is the name the ``Form`` instance was given in the template - context. - - ``field`` is the name of the field on the form to check. If ``field`` - has a value of ``None``, non-field errors (errors you can access via - ``form.non_field_errors()``) will be checked. - - ``errors`` is an error string, or a list of error strings, that are - expected as a result of form validation. - -.. method:: TestCase.assertTemplateUsed(response, template_name, msg_prefix='') - - Asserts that the template with the given name was used in rendering the - response. - - The name is a string such as ``'admin/index.html'``. - -.. method:: TestCase.assertTemplateNotUsed(response, template_name, msg_prefix='') - - Asserts that the template with the given name was *not* used in rendering - the response. - -.. method:: TestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='') - - Asserts that the response return a ``status_code`` redirect status, it - redirected to ``expected_url`` (including any GET data), and the final - page was received with ``target_status_code``. - - .. versionadded:: 1.1 - - If your request used the ``follow`` argument, the ``expected_url`` and - ``target_status_code`` will be the url and status code for the final - point of the redirect chain. - -.. _topics-testing-email: - -E-mail services ---------------- - -.. versionadded:: 1.0 - -If any of your Django views send e-mail using :doc:`Django's e-mail -functionality </topics/email>`, you probably don't want to send e-mail each time -you run a test using that view. For this reason, Django's test runner -automatically redirects all Django-sent e-mail to a dummy outbox. This lets you -test every aspect of sending e-mail -- from the number of messages sent to the -contents of each message -- without actually sending the messages. - -The test runner accomplishes this by transparently replacing the normal -email backend with a testing backend. -(Don't worry -- this has no effect on any other e-mail senders outside of -Django, such as your machine's mail server, if you're running one.) - -.. currentmodule:: django.core.mail - -.. data:: django.core.mail.outbox - -During test running, each outgoing e-mail is saved in -``django.core.mail.outbox``. This is a simple list of all -:class:`~django.core.mail.EmailMessage` instances that have been sent. -The ``outbox`` attribute is a special attribute that is created *only* when -the ``locmem`` e-mail backend is used. It doesn't normally exist as part of the -:mod:`django.core.mail` module and you can't import it directly. The code -below shows how to access this attribute correctly. - -Here's an example test that examines ``django.core.mail.outbox`` for length -and contents:: - - from django.core import mail - from django.test import TestCase - - class EmailTest(TestCase): - def test_send_email(self): - # Send message. - mail.send_mail('Subject here', 'Here is the message.', - 'from@example.com', ['to@example.com'], - fail_silently=False) - - # Test that one message has been sent. - self.assertEquals(len(mail.outbox), 1) - - # Verify that the subject of the first message is correct. - self.assertEquals(mail.outbox[0].subject, 'Subject here') - -As noted :ref:`previously <emptying-test-outbox>`, the test outbox is emptied -at the start of every test in a Django ``TestCase``. To empty the outbox -manually, assign the empty list to ``mail.outbox``:: - - from django.core import mail - - # Empty the test outbox - mail.outbox = [] - -Using different testing frameworks -================================== - -Clearly, ``doctest`` and ``unittest`` are not the only Python testing -frameworks. While Django doesn't provide explicit support for alternative -frameworks, it does provide a way to invoke tests constructed for an -alternative framework as if they were normal Django tests. - -When you run ``./manage.py test``, Django looks at the :setting:`TEST_RUNNER` -setting to determine what to do. By default, :setting:`TEST_RUNNER` points to -``'django.test.simple.DjangoTestSuiteRunner'``. This class defines the default Django -testing behavior. This behavior involves: - - #. Performing global pre-test setup. - - #. Looking for unit tests and doctests in the ``models.py`` and - ``tests.py`` files in each installed application. - - #. Creating the test databases. - - #. Running ``syncdb`` to install models and initial data into the test - databases. - - #. Running the unit tests and doctests that are found. - - #. Destroying the test databases. - - #. Performing global post-test teardown. - -If you define your own test runner class and point :setting:`TEST_RUNNER` at -that class, Django will execute your test runner whenever you run -``./manage.py test``. In this way, it is possible to use any test framework -that can be executed from Python code, or to modify the Django test execution -process to satisfy whatever testing requirements you may have. - -.. _topics-testing-test_runner: - -Defining a test runner ----------------------- - -.. versionchanged:: 1.2 - Prior to 1.2, test runners were a single function, not a class. - -.. currentmodule:: django.test.simple - -A test runner is a class defining a ``run_tests()`` method. Django ships -with a ``DjangoTestSuiteRunner`` class that defines the default Django -testing behavior. This class defines the ``run_tests()`` entry point, -plus a selection of other methods that are used to by ``run_tests()`` to -set up, execute and tear down the test suite. - -.. class:: DjangoTestSuiteRunner(verbosity=1, interactive=True, failfast=True, **kwargs) - - ``verbosity`` determines the amount of notification and debug information - that will be printed to the console; ``0`` is no output, ``1`` is normal - output, and ``2`` is verbose output. - - If ``interactive`` is ``True``, the test suite has permission to ask the - user for instructions when the test suite is executed. An example of this - behavior would be asking for permission to delete an existing test - database. If ``interactive`` is ``False``, the test suite must be able to - run without any manual intervention. - - If ``failfast`` is ``True``, the test suite will stop running after the - first test failure is detected. - - Django will, from time to time, extend the capabilities of - the test runner by adding new arguments. The ``**kwargs`` declaration - allows for this expansion. If you subclass ``DjangoTestSuiteRunner`` or - write your own test runner, ensure accept and handle the ``**kwargs`` - parameter. - -.. method:: DjangoTestSuiteRunner.run_tests(test_labels, extra_tests=None, **kwargs) - - Run the test suite. - - ``test_labels`` is a list of strings describing the tests to be run. A test - label can take one of three forms: - - * ``app.TestCase.test_method`` -- Run a single test method in a test - case. - * ``app.TestCase`` -- Run all the test methods in a test case. - * ``app`` -- Search for and run all tests in the named application. - - If ``test_labels`` has a value of ``None``, the test runner should run - search for tests in all the applications in :setting:`INSTALLED_APPS`. - - ``extra_tests`` is a list of extra ``TestCase`` instances to add to the - suite that is executed by the test runner. These extra tests are run - in addition to those discovered in the modules listed in ``test_labels``. - - This method should return the number of tests that failed. - -.. method:: DjangoTestSuiteRunner.setup_test_environment(**kwargs) - - Sets up the test environment ready for testing. - -.. method:: DjangoTestSuiteRunner.build_suite(test_labels, extra_tests=None, **kwargs) - - Constructs a test suite that matches the test labels provided. - - ``test_labels`` is a list of strings describing the tests to be run. A test - label can take one of three forms: - - * ``app.TestCase.test_method`` -- Run a single test method in a test - case. - * ``app.TestCase`` -- Run all the test methods in a test case. - * ``app`` -- Search for and run all tests in the named application. - - If ``test_labels`` has a value of ``None``, the test runner should run - search for tests in all the applications in :setting:`INSTALLED_APPS`. - - ``extra_tests`` is a list of extra ``TestCase`` instances to add to the - suite that is executed by the test runner. These extra tests are run - in addition to those discovered in the modules listed in ``test_labels``. - - Returns a ``TestSuite`` instance ready to be run. - -.. method:: DjangoTestSuiteRunner.setup_databases(**kwargs) - - Creates the test databases. - - Returns a data structure that provides enough detail to undo the changes - that have been made. This data will be provided to the ``teardown_databases()`` - function at the conclusion of testing. - -.. method:: DjangoTestSuiteRunner.run_suite(suite, **kwargs) - - Runs the test suite. - - Returns the result produced by the running the test suite. - -.. method:: DjangoTestSuiteRunner.teardown_databases(old_config, **kwargs) - - Destroys the test databases, restoring pre-test conditions. - - ``old_config`` is a data structure defining the changes in the - database configuration that need to be reversed. It is the return - value of the ``setup_databases()`` method. - -.. method:: DjangoTestSuiteRunner.teardown_test_environment(**kwargs) - - Restores the pre-test environment. - -.. method:: DjangoTestSuiteRunner.suite_result(suite, result, **kwargs) - - Computes and returns a return code based on a test suite, and the result - from that test suite. - - -Testing utilities ------------------ - -.. module:: django.test.utils - :synopsis: Helpers to write custom test runners. - -To assist in the creation of your own test runner, Django provides a number of -utility methods in the ``django.test.utils`` module. - -.. function:: setup_test_environment() - - Performs any global pre-test setup, such as the installing the - instrumentation of the template rendering system and setting up - the dummy ``SMTPConnection``. - -.. function:: teardown_test_environment() - - Performs any global post-test teardown, such as removing the black - magic hooks into the template system and restoring normal e-mail - services. - -The creation module of the database backend (``connection.creation``) -also provides some utilities that can be useful during testing. - -.. function:: create_test_db(verbosity=1, autoclobber=False) - - Creates a new test database and runs ``syncdb`` against it. - - ``verbosity`` has the same behavior as in ``run_tests()``. - - ``autoclobber`` describes the behavior that will occur if a - database with the same name as the test database is discovered: - - * If ``autoclobber`` is ``False``, the user will be asked to - approve destroying the existing database. ``sys.exit`` is - called if the user does not approve. - - * If autoclobber is ``True``, the database will be destroyed - without consulting the user. - - Returns the name of the test database that it created. - - ``create_test_db()`` has the side effect of modifying the value of - :setting:`NAME` in :setting:`DATABASES` to match the name of the test - database. - - .. versionchanged:: 1.0 - ``create_test_db()`` now returns the name of the test database. - -.. function:: destroy_test_db(old_database_name, verbosity=1) - - Destroys the database whose name is in stored in :setting:`NAME` in the - :setting:`DATABASES`, and sets :setting:`NAME` to use the - provided name. - - ``verbosity`` has the same behavior as in ``run_tests()``. |