diff --git a/docs/authentication.txt b/docs/authentication.txt index eaf3cc2b99..55334b697a 100644 --- a/docs/authentication.txt +++ b/docs/authentication.txt @@ -147,8 +147,9 @@ The most basic way to create users is to use the standard Django ... is_active=True, is_superuser=False) >>> u.save() -Note that ``password_md5`` requires the raw MD5 hash. Because that's a pain, -there's a ``create_user`` helper function:: +Note that ``password_md5`` requires the raw MD5 hash (as created by +``md5.new().hexdigest()``). Because that's a pain, there's a ``create_user`` +helper function:: >>> from django.models.auth import users >>> u = users.create_user('john', 'lennon@thebeatles.com', 'johnpassword') @@ -196,7 +197,12 @@ previous section). You can tell them apart with ``is_anonymous()``, like so:: else: # Do something for logged-in users. +If you want to use ``request.user`` in your view code, make sure you have +``SessionMiddleware`` enabled. See the `session documentation`_ for more +information. + .. _request objects: http://www.djangoproject.com/documentation/request_response/#httprequest-objects +.. _session documentation: http://www.djangoproject.com/documentation/sessions/ Limiting access to logged-in users ---------------------------------- @@ -251,8 +257,8 @@ Here's the same thing, using Python 2.4's decorator syntax:: Limiting access to logged-in users that pass a test --------------------------------------------------- -To limit access based on certain permissions or another test, you'd do the same -thing as described in the previous section. +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 ``request.user`` in the view directly. For example, this view checks to make sure the user is logged in and has the @@ -276,13 +282,195 @@ As a shortcut, you can use the convenient ``user_passes_test`` decorator:: Note that ``user_passes_test`` does not automatically check that the ``User`` is not anonymous. - - 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 or publication date." The latter functionality is something +Django developers are currently discussing. + +Default permissions +------------------- + +Three basic permissions -- add, create and delete -- are automatically created +for each Django model that has ``admin`` set. Behind the scenes, these +permissions are added to the ``auth_permissions`` database table when you run +``django-admin.py install [app]``. You can view the exact SQL ``INSERT`` +statements by running ``django-admin.py sqlinitialdata [app]``. + +Note that if your model doesn't have ``admin`` set when you run +``django-admin.py install``, the permissions won't be created. If you +initialize your database and add ``admin`` to models after the fact, you'll +need to add the permissions to the database manually. Do this by running +``django-admin.py installperms [app]``, which creates any missing permissions +for the given app. + +Custom permissions +------------------ + +To create custom permissions for a given model object, use the ``permissions`` +`model META attribute`_. + +This example model creates three custom permissions:: + + class USCitizen(meta.Model): + # ... + class META: + permissions = ( + ("can_drive", "Can drive"), + ("can_vote", "Can vote in elections"), + ("can_drink", "Can drink alcohol"), + ) + +.. _model META attribute: http://www.djangoproject.com/documentation/model_api/#meta-options + +API reference +------------- + +Just like users, permissions are implemented in a Django model that lives in +`django/models/auth.py`_. + +Fields +~~~~~~ + +``Permission`` objects have the following fields: + + * ``name`` -- Required. 50 characters or fewer. Example: ``'Can vote'``. + * ``package`` -- Required. A reference to the ``packages`` database table, + which contains a record for each installed Django application. + * ``codename`` -- Required. 100 characters or fewer. Example: ``'can_vote'``. + +Methods +~~~~~~~ + +``Permission`` objects have the standard data-access methods like any other +`Django model`_: + +Authentication data in templates +================================ + +The currently logged-in user and his/her permissions are made available in the +`template context`_ when you use ``DjangoContext``. + +Users +----- + +The currently logged-in user, either a ``User`` object or an``AnonymousUser`` +instance, is stored in the template variable ``{{ user }}``:: + + {% if user.is_anonymous %} +
Welcome, new user. Please log in.
+ {% else %} +Welcome, {{ user.username }}. Thanks for logging in.
+ {% endif %} + +Permissions +----------- + +The currently logged-in user's permissions are stored in the template variable +``{{ perms }}``. This is an instance of ``django.core.extensions.PermWrapper``, +which is a template-friendly proxy of permissions. + +In the ``{{ perms }}`` object, single-attribute lookup is a proxy to +``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 ``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:: + + {% 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 %} + +.. _template context: http://www.djangoproject.com/documentation/models/templates_python/ + Groups ====== +Groups are a generic way of categorizing users to 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 apply +some label, or extended functionality, to them. For example, you could create +a group ``'Special users'``, and you could write code that would do special +things to those users -- such as giving them access to a members-only portion +of your site, or sending them members-only e-mail messages. + Messages ======== + +The message system is a lightweight way to queue messages for given users. + +A message is associated with a 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:: + + * To add messages, use ``user.add_message(message_text)``. + * To retrieve/delete messages, use ``user.get_and_delete_messages()``, + which returns a list of ``Message`` objects in the user's queue (if any) + and deletes the messages from the queue. + +In this example view, the system saves a message for the user after creating +a playlist:: + + def create_playlist(request, songs): + # Create the playlist with the given songs. + # ... + request.user.add_message("Your playlist was added successfully.") + return render_to_response("playlists/create", context_instance=DjangoContext) + +When you use ``DjangoContext``, the currently logged-in user and his/her +messages are made available in the `template context`_ as the template variable +``{{ messages }}``. Here's an example of template code that displays messages:: + + {% if messages %} +