From b03203c8cb991c16ac8a3d74c8c4078182d0bb48 Mon Sep 17 00:00:00 2001 From: Nishanth Amuluru Date: Tue, 11 Jan 2011 22:41:51 +0530 Subject: removed all the buildout files --- parts/django/docs/topics/auth.txt | 1612 ------------------- parts/django/docs/topics/cache.txt | 917 ----------- .../docs/topics/conditional-view-processing.txt | 199 --- parts/django/docs/topics/db/aggregation.txt | 378 ----- parts/django/docs/topics/db/index.txt | 18 - parts/django/docs/topics/db/managers.txt | 376 ----- parts/django/docs/topics/db/models.txt | 1234 --------------- parts/django/docs/topics/db/multi-db.txt | 574 ------- parts/django/docs/topics/db/optimization.txt | 260 ---- parts/django/docs/topics/db/queries.txt | 1110 -------------- parts/django/docs/topics/db/sql.txt | 279 ---- parts/django/docs/topics/db/transactions.txt | 328 ---- parts/django/docs/topics/email.txt | 618 -------- parts/django/docs/topics/files.txt | 147 -- parts/django/docs/topics/forms/formsets.txt | 440 ------ parts/django/docs/topics/forms/index.txt | 402 ----- parts/django/docs/topics/forms/media.txt | 309 ---- parts/django/docs/topics/forms/modelforms.txt | 885 ----------- parts/django/docs/topics/generic-views.txt | 501 ------ .../django/docs/topics/http/_images/middleware.png | Bin 56301 -> 0 bytes parts/django/docs/topics/http/file-uploads.txt | 394 ----- parts/django/docs/topics/http/generic-views.txt | 5 - parts/django/docs/topics/http/index.txt | 15 - parts/django/docs/topics/http/middleware.txt | 179 --- parts/django/docs/topics/http/sessions.txt | 529 ------- parts/django/docs/topics/http/shortcuts.txt | 229 --- parts/django/docs/topics/http/urls.txt | 890 ----------- parts/django/docs/topics/http/views.txt | 202 --- parts/django/docs/topics/i18n/deployment.txt | 191 --- parts/django/docs/topics/i18n/index.txt | 113 -- .../docs/topics/i18n/internationalization.txt | 624 -------- parts/django/docs/topics/i18n/localization.txt | 317 ---- parts/django/docs/topics/index.txt | 27 - parts/django/docs/topics/install.txt | 298 ---- parts/django/docs/topics/pagination.txt | 281 ---- parts/django/docs/topics/serialization.txt | 402 ----- parts/django/docs/topics/settings.txt | 255 ---- parts/django/docs/topics/signals.txt | 255 ---- parts/django/docs/topics/templates.txt | 617 -------- parts/django/docs/topics/testing.txt | 1613 -------------------- 40 files changed, 18023 deletions(-) delete mode 100644 parts/django/docs/topics/auth.txt delete mode 100644 parts/django/docs/topics/cache.txt delete mode 100644 parts/django/docs/topics/conditional-view-processing.txt delete mode 100644 parts/django/docs/topics/db/aggregation.txt delete mode 100644 parts/django/docs/topics/db/index.txt delete mode 100644 parts/django/docs/topics/db/managers.txt delete mode 100644 parts/django/docs/topics/db/models.txt delete mode 100644 parts/django/docs/topics/db/multi-db.txt delete mode 100644 parts/django/docs/topics/db/optimization.txt delete mode 100644 parts/django/docs/topics/db/queries.txt delete mode 100644 parts/django/docs/topics/db/sql.txt delete mode 100644 parts/django/docs/topics/db/transactions.txt delete mode 100644 parts/django/docs/topics/email.txt delete mode 100644 parts/django/docs/topics/files.txt delete mode 100644 parts/django/docs/topics/forms/formsets.txt delete mode 100644 parts/django/docs/topics/forms/index.txt delete mode 100644 parts/django/docs/topics/forms/media.txt delete mode 100644 parts/django/docs/topics/forms/modelforms.txt delete mode 100644 parts/django/docs/topics/generic-views.txt delete mode 100644 parts/django/docs/topics/http/_images/middleware.png delete mode 100644 parts/django/docs/topics/http/file-uploads.txt delete mode 100644 parts/django/docs/topics/http/generic-views.txt delete mode 100644 parts/django/docs/topics/http/index.txt delete mode 100644 parts/django/docs/topics/http/middleware.txt delete mode 100644 parts/django/docs/topics/http/sessions.txt delete mode 100644 parts/django/docs/topics/http/shortcuts.txt delete mode 100644 parts/django/docs/topics/http/urls.txt delete mode 100644 parts/django/docs/topics/http/views.txt delete mode 100644 parts/django/docs/topics/i18n/deployment.txt delete mode 100644 parts/django/docs/topics/i18n/index.txt delete mode 100644 parts/django/docs/topics/i18n/internationalization.txt delete mode 100644 parts/django/docs/topics/i18n/localization.txt delete mode 100644 parts/django/docs/topics/index.txt delete mode 100644 parts/django/docs/topics/install.txt delete mode 100644 parts/django/docs/topics/pagination.txt delete mode 100644 parts/django/docs/topics/serialization.txt delete mode 100644 parts/django/docs/topics/settings.txt delete mode 100644 parts/django/docs/topics/signals.txt delete mode 100644 parts/django/docs/topics/templates.txt delete mode 100644 parts/django/docs/topics/testing.txt (limited to 'parts/django/docs/topics') 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 ` 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 -` 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 - `: - - .. 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 ``"."``. (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 - ``"."``. 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* ` 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 ` 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 ` 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 `. - -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 ` for more information. - -Once you have those middlewares installed, you'll be able to access -:attr:`request.user ` in views. -:attr:`request.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 ` 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() -` 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 `, 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 `. 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 ` (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 ` 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'] `. - 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 %} -

Your username and password didn't match. Please try again.

- {% endif %} - -
- {% csrf_token %} - - - - - - - - - -
{{ form.username.label_tag }}{{ form.username }}
{{ form.password.label_tag }}{{ form.password }}
- - - -
- - {% 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 ` 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 ` 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 -` 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 ` 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 - ``"."`` (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 `. - -Limiting access to generic views --------------------------------- - -To limit access to a :doc:`generic view `, 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 -`; 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 -`. - -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 `. - -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 `. 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 `. - -Authentication data in templates -================================ - -The currently logged-in user and his/her permissions are made available in the -:doc:`template context ` 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 `. - -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 %} -

Welcome, {{ user.username }}. Thanks for logging in.

- {% else %} -

Welcome, new user. Please log in.

- {% 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 `. -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 `. 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 %} -

You have permission to do something in the foo app.

- {% if perms.foo.can_vote %} -

You can vote!

- {% endif %} - {% if perms.foo.can_drive %} -

You can drive!

- {% endif %} - {% else %} -

You don't have permission to do anything in the foo app.

- {% 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 ` 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() `, - 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 ` as the template variable -``{{ messages }}``. Here's an example of template code that displays messages: - -.. code-block:: html+django - - {% if messages %} -
    - {% for message in messages %} -
  • {{ message }}
  • - {% endfor %} -
- {% endif %} - -.. versionchanged:: 1.2 - The ``messages`` template variable uses a backwards compatible method in the - :doc:`messages framework ` 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 `. - -.. _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 ` -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 ` 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 ` 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 -`_ 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`. -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`. For the ``cache`` template -tag you could use one of the -:ref:`translation-specific variables` 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 ` -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 `. - -``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] - - >>> q[0].authors__count - 2 - # Interrogate the second object in the queryset - >>> q[1] - - >>> 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 -` 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 -`, 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 `: - - 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 ` 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 `. - -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 ` 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 `. - -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 ` to use in Django's admin interface, - if you care to use it (e.g. ````, `` - - -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() - - - - - - - -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 `. - -.. _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() - - - -.. 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() - - - - - - - - - - -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() - - - - - - - - - - - -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() - - - - -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 - -
- {{ formset.management_form }} - - {% for form in formset.forms %} - {{ form }} - {% endfor %} -
-
- -However the above can be slightly shortcutted and let the formset itself deal -with the management form: - -.. code-block:: html+django - -
- - {{ formset }} -
-
- -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. - ```` or ``