| 1 |
============================= |
|---|
| 2 |
User authentication in Django |
|---|
| 3 |
============================= |
|---|
| 4 |
|
|---|
| 5 |
Django comes with a user authentication system. It handles user accounts, |
|---|
| 6 |
groups, permissions and cookie-based user sessions. This document explains how |
|---|
| 7 |
things work. |
|---|
| 8 |
|
|---|
| 9 |
The basics |
|---|
| 10 |
========== |
|---|
| 11 |
|
|---|
| 12 |
Django supports authentication out of the box. The ``django-admin.py init`` |
|---|
| 13 |
command, used to initialize a database with Django's core database tables, |
|---|
| 14 |
creates the infrastructure for the auth system. You don't have to do anything |
|---|
| 15 |
else to use authentication. |
|---|
| 16 |
|
|---|
| 17 |
The auth system consists of: |
|---|
| 18 |
|
|---|
| 19 |
* Users |
|---|
| 20 |
* Permissions: Binary (yes/no) flags designating whether a user may perform |
|---|
| 21 |
a certain task. |
|---|
| 22 |
* Groups: A generic way of applying labels and permissions to more than one |
|---|
| 23 |
user. |
|---|
| 24 |
* Messages: A simple way to queue messages for given users. |
|---|
| 25 |
|
|---|
| 26 |
Users |
|---|
| 27 |
===== |
|---|
| 28 |
|
|---|
| 29 |
Users are represented by a standard Django model, which lives in |
|---|
| 30 |
`django/models/auth.py`_. |
|---|
| 31 |
|
|---|
| 32 |
.. _django/models/auth.py: http://code.djangoproject.com/browser/django/trunk/django/models/auth.py |
|---|
| 33 |
|
|---|
| 34 |
API reference |
|---|
| 35 |
------------- |
|---|
| 36 |
|
|---|
| 37 |
Fields |
|---|
| 38 |
~~~~~~ |
|---|
| 39 |
|
|---|
| 40 |
``User`` objects have the following fields: |
|---|
| 41 |
|
|---|
| 42 |
* ``username`` -- Required. 30 characters or fewer. Alphanumeric characters |
|---|
| 43 |
only (letters, digits and underscores). |
|---|
| 44 |
* ``first_name`` -- Optional. 30 characters or fewer. |
|---|
| 45 |
* ``last_name`` -- Optional. 30 characters or fewer. |
|---|
| 46 |
* ``email`` -- Optional. E-mail address. |
|---|
| 47 |
* ``password_md5`` -- Required. An MD5 hash of the password. (Django |
|---|
| 48 |
doesn't store the raw password.) Raw passwords can be arbitrarily long |
|---|
| 49 |
and can contain any character. |
|---|
| 50 |
* ``is_staff`` -- Boolean. Designates whether this user can access the |
|---|
| 51 |
admin site. |
|---|
| 52 |
* ``is_active`` -- Boolean. Designates whether this user account is valid. |
|---|
| 53 |
Set this to ``False`` instead of deleting accounts. |
|---|
| 54 |
* ``is_superuser`` -- Boolean. Designates whether this user has permission |
|---|
| 55 |
to do anything (according to the permission system). |
|---|
| 56 |
* ``last_login`` -- A datetime of the user's last login. Is set to the |
|---|
| 57 |
current date/time by default. |
|---|
| 58 |
* ``date_joined`` -- A datetime designating when the account was created. |
|---|
| 59 |
Is set to the current date/time by default when the account is created. |
|---|
| 60 |
|
|---|
| 61 |
Methods |
|---|
| 62 |
~~~~~~~ |
|---|
| 63 |
|
|---|
| 64 |
``User`` objects have two many-to-many fields: ``groups`` and |
|---|
| 65 |
``user_permissions``. Because of those relationships, ``User`` objects get |
|---|
| 66 |
data-access methods like any other `Django model`_: |
|---|
| 67 |
|
|---|
| 68 |
* ``get_group_list(**kwargs)`` |
|---|
| 69 |
* ``set_groups(id_list)`` |
|---|
| 70 |
* ``get_permission_list(**kwargs)`` |
|---|
| 71 |
* ``set_user_permissions(id_list)`` |
|---|
| 72 |
|
|---|
| 73 |
In addition to those automatic API methods, ``User`` objects have the following |
|---|
| 74 |
methods: |
|---|
| 75 |
|
|---|
| 76 |
* ``is_anonymous()`` -- Always returns ``False``. This is a way of |
|---|
| 77 |
comparing ``User`` objects to anonymous users. |
|---|
| 78 |
|
|---|
| 79 |
* ``get_full_name()`` -- Returns the ``first_name`` plus the ``last_name``, |
|---|
| 80 |
with a space in between. |
|---|
| 81 |
|
|---|
| 82 |
* ``set_password(raw_password)`` -- Sets the user's password to the given |
|---|
| 83 |
raw string, taking care of the MD5 hashing. Doesn't save the ``User`` |
|---|
| 84 |
object. |
|---|
| 85 |
|
|---|
| 86 |
* ``check_password(raw_password)`` -- Returns ``True`` if the given raw |
|---|
| 87 |
string is the correct password for the user. |
|---|
| 88 |
|
|---|
| 89 |
* ``get_group_permissions()`` -- Returns a list of permission strings that |
|---|
| 90 |
the user has, through his/her groups. |
|---|
| 91 |
|
|---|
| 92 |
* ``get_all_permissions()`` -- Returns a list of permission strings that |
|---|
| 93 |
the user has, both through group and user permissions. |
|---|
| 94 |
|
|---|
| 95 |
* ``has_perm(perm)`` -- Returns ``True`` if the user has the specified |
|---|
| 96 |
permission. |
|---|
| 97 |
|
|---|
| 98 |
* ``has_perms(perm_list)`` -- Returns ``True`` if the user has each of the |
|---|
| 99 |
specified permissions. |
|---|
| 100 |
|
|---|
| 101 |
* ``has_module_perms(package_name)`` -- Returns ``True`` if the user has |
|---|
| 102 |
any permissions in the given package (the Django app label). |
|---|
| 103 |
|
|---|
| 104 |
* ``get_and_delete_messages()`` -- Returns a list of ``Message`` objects in |
|---|
| 105 |
the user's queue and deletes the messages from the queue. |
|---|
| 106 |
|
|---|
| 107 |
* ``email_user(subject, message, from_email=None)`` -- Sends an e-mail to |
|---|
| 108 |
the user. If ``from_email`` is ``None``, Django uses the |
|---|
| 109 |
`DEFAULT_FROM_EMAIL`_ setting. |
|---|
| 110 |
|
|---|
| 111 |
* ``get_profile()`` -- Returns a site-specific profile for this user. |
|---|
| 112 |
Raises ``django.models.auth.SiteProfileNotAvailable`` if the current site |
|---|
| 113 |
doesn't allow profiles. |
|---|
| 114 |
|
|---|
| 115 |
.. _Django model: http://www.djangoproject.com/documentation/model_api/ |
|---|
| 116 |
.. _DEFAULT_FROM_EMAIL: http://www.djangoproject.com/documentation/settings/#default-from-email |
|---|
| 117 |
|
|---|
| 118 |
Module functions |
|---|
| 119 |
~~~~~~~~~~~~~~~~ |
|---|
| 120 |
|
|---|
| 121 |
The ``django.models.auth.users`` module has the following helper functions: |
|---|
| 122 |
|
|---|
| 123 |
* ``create_user(username, email, password)`` -- Creates, saves and returns |
|---|
| 124 |
a ``User``. The ``username``, ``email`` and ``password`` are set as |
|---|
| 125 |
given, and the ``User`` gets ``is_active=True``. |
|---|
| 126 |
|
|---|
| 127 |
* ``make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')`` |
|---|
| 128 |
-- Returns a random password with the given length and given string of |
|---|
| 129 |
allowed characters. (Note that the default value of ``allowed_chars`` |
|---|
| 130 |
doesn't contain ``"I"`` or letters that look like it, to avoid user |
|---|
| 131 |
confusion. |
|---|
| 132 |
|
|---|
| 133 |
Basic usage |
|---|
| 134 |
----------- |
|---|
| 135 |
|
|---|
| 136 |
Creating users |
|---|
| 137 |
~~~~~~~~~~~~~~ |
|---|
| 138 |
|
|---|
| 139 |
The most basic way to create users is to use the standard Django |
|---|
| 140 |
`database API`_. Just create and save a ``User`` object:: |
|---|
| 141 |
|
|---|
| 142 |
>>> from django.models.auth import users |
|---|
| 143 |
>>> import md5 |
|---|
| 144 |
>>> p = md5.new('johnpassword').hexdigest() |
|---|
| 145 |
>>> u = users.User(username='john', first_name='John', last_name='lennon', |
|---|
| 146 |
... email='lennon@thebeatles.com', password_md5=p, is_staff=True, |
|---|
| 147 |
... is_active=True, is_superuser=False) |
|---|
| 148 |
>>> u.save() |
|---|
| 149 |
|
|---|
| 150 |
Note that ``password_md5`` requires the raw MD5 hash (as created by |
|---|
| 151 |
``md5.new().hexdigest()``). Because that's a pain, there's a ``create_user`` |
|---|
| 152 |
helper function:: |
|---|
| 153 |
|
|---|
| 154 |
>>> from django.models.auth import users |
|---|
| 155 |
>>> u = users.create_user('john', 'lennon@thebeatles.com', 'johnpassword') |
|---|
| 156 |
|
|---|
| 157 |
.. _database API: http://www.djangoproject.com/documentation/db_api/ |
|---|
| 158 |
|
|---|
| 159 |
Changing passwords |
|---|
| 160 |
~~~~~~~~~~~~~~~~~~ |
|---|
| 161 |
|
|---|
| 162 |
Change a password with ``set_password()``:: |
|---|
| 163 |
|
|---|
| 164 |
>>> from django.models.auth import users |
|---|
| 165 |
>>> u = users.get_object(username__exact='john') |
|---|
| 166 |
>>> u.set_password('new password') |
|---|
| 167 |
>>> u.save() |
|---|
| 168 |
|
|---|
| 169 |
Anonymous users |
|---|
| 170 |
--------------- |
|---|
| 171 |
|
|---|
| 172 |
``django.parts.auth.anonymoususers.AnonymousUser`` is a class that implements |
|---|
| 173 |
the ``django.models.auth.users.User`` interface, with these differences: |
|---|
| 174 |
|
|---|
| 175 |
* ``id`` is always ``None``. |
|---|
| 176 |
* ``is_anonymous()`` returns ``True`` instead of ``False``. |
|---|
| 177 |
* ``has_perm()`` always returns ``False``. |
|---|
| 178 |
* ``set_password()``, ``check_password()``, ``set_groups()`` and |
|---|
| 179 |
``set_permissions()`` raise ``NotImplementedError``. |
|---|
| 180 |
|
|---|
| 181 |
In practice, you probably won't need to use ``AnonymousUser`` objects on your |
|---|
| 182 |
own, but they're used by Web requests, as explained in the next section. |
|---|
| 183 |
|
|---|
| 184 |
Authentication in Web requests |
|---|
| 185 |
============================== |
|---|
| 186 |
|
|---|
| 187 |
Until now, this document has dealt with the low-level APIs for manipulating |
|---|
| 188 |
authentication-related objects. On a higher level, Django hooks this |
|---|
| 189 |
authentication framework into its system of `request objects`_. |
|---|
| 190 |
|
|---|
| 191 |
In any Django view, ``request.user`` will give you a ``User`` object |
|---|
| 192 |
representing the currently logged-in user. If a user isn't currently logged in, |
|---|
| 193 |
``request.user`` will be set to an instance of ``AnonymousUser`` (see the |
|---|
| 194 |
previous section). You can tell them apart with ``is_anonymous()``, like so:: |
|---|
| 195 |
|
|---|
| 196 |
if request.user.is_anonymous(): |
|---|
| 197 |
# Do something for anonymous users. |
|---|
| 198 |
else: |
|---|
| 199 |
# Do something for logged-in users. |
|---|
| 200 |
|
|---|
| 201 |
If you want to use ``request.user`` in your view code, make sure you have |
|---|
| 202 |
``SessionMiddleware`` enabled. See the `session documentation`_ for more |
|---|
| 203 |
information. |
|---|
| 204 |
|
|---|
| 205 |
.. _request objects: http://www.djangoproject.com/documentation/request_response/#httprequest-objects |
|---|
| 206 |
.. _session documentation: http://www.djangoproject.com/documentation/sessions/ |
|---|
| 207 |
|
|---|
| 208 |
Limiting access to logged-in users |
|---|
| 209 |
---------------------------------- |
|---|
| 210 |
|
|---|
| 211 |
The raw way |
|---|
| 212 |
~~~~~~~~~~~ |
|---|
| 213 |
|
|---|
| 214 |
The simple, raw way to limit access to pages is to check |
|---|
| 215 |
``request.user.is_anonymous()`` and either redirect to a login page:: |
|---|
| 216 |
|
|---|
| 217 |
from django.utils.httpwrappers import HttpResponseRedirect |
|---|
| 218 |
|
|---|
| 219 |
def my_view(request): |
|---|
| 220 |
if request.user.is_anonymous(): |
|---|
| 221 |
return HttpResponseRedirect('/login/?next=%s' % request.path) |
|---|
| 222 |
# ... |
|---|
| 223 |
|
|---|
| 224 |
...or display an error message:: |
|---|
| 225 |
|
|---|
| 226 |
def my_view(request): |
|---|
| 227 |
if request.user.is_anonymous(): |
|---|
| 228 |
return render_to_response('myapp/login_error') |
|---|
| 229 |
# ... |
|---|
| 230 |
|
|---|
| 231 |
The login_required decorator |
|---|
| 232 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 233 |
|
|---|
| 234 |
As a shortcut, you can use the convenient ``login_required`` decorator:: |
|---|
| 235 |
|
|---|
| 236 |
from django.views.decorators.auth import login_required |
|---|
| 237 |
|
|---|
| 238 |
def my_view(request): |
|---|
| 239 |
# ... |
|---|
| 240 |
my_view = login_required(my_view) |
|---|
| 241 |
|
|---|
| 242 |
Here's the same thing, using Python 2.4's decorator syntax:: |
|---|
| 243 |
|
|---|
| 244 |
from django.views.decorators.auth import login_required |
|---|
| 245 |
|
|---|
| 246 |
@login_required |
|---|
| 247 |
def my_view(request): |
|---|
| 248 |
# ... |
|---|
| 249 |
|
|---|
| 250 |
``login_required`` does the following: |
|---|
| 251 |
|
|---|
| 252 |
* If the user isn't logged in, redirect to ``/accounts/login/``, passing |
|---|
| 253 |
the current absolute URL in the query string as ``next``. For example: |
|---|
| 254 |
``/accounts/login/?next=/polls/3/``. |
|---|
| 255 |
* If the user is logged in, execute the view normally. The view code is |
|---|
| 256 |
free to assume the user is logged in. |
|---|
| 257 |
|
|---|
| 258 |
Limiting access to logged-in users that pass a test |
|---|
| 259 |
--------------------------------------------------- |
|---|
| 260 |
|
|---|
| 261 |
To limit access based on certain permissions or some other test, you'd do |
|---|
| 262 |
essentially the same thing as described in the previous section. |
|---|
| 263 |
|
|---|
| 264 |
The simple way is to run your test on ``request.user`` in the view directly. |
|---|
| 265 |
For example, this view checks to make sure the user is logged in and has the |
|---|
| 266 |
permission ``polls.can_vote``:: |
|---|
| 267 |
|
|---|
| 268 |
def my_view(request): |
|---|
| 269 |
if request.user.is_anonymous() or not request.user.has_perm('polls.can_vote'): |
|---|
| 270 |
return HttpResponse("You can't vote in this poll.") |
|---|
| 271 |
# ... |
|---|
| 272 |
|
|---|
| 273 |
As a shortcut, you can use the convenient ``user_passes_test`` decorator:: |
|---|
| 274 |
|
|---|
| 275 |
from django.views.decorators.auth import user_passes_test |
|---|
| 276 |
|
|---|
| 277 |
@user_passes_test(lambda u: u.has_perm('polls.can_vote')) |
|---|
| 278 |
def my_view(request): |
|---|
| 279 |
# ... |
|---|
| 280 |
|
|---|
| 281 |
``user_passes_test`` takes a required argument: a callable that takes a |
|---|
| 282 |
``User`` object and returns ``True`` if the user is allowed to view the page. |
|---|
| 283 |
Note that ``user_passes_test`` does not automatically check that the ``User`` |
|---|
| 284 |
is not anonymous. |
|---|
| 285 |
|
|---|
| 286 |
Limiting access to generic views |
|---|
| 287 |
-------------------------------- |
|---|
| 288 |
|
|---|
| 289 |
To limit access to a `generic view`_, write a thin wrapper around the view, |
|---|
| 290 |
and point your URLconf to your wrapper instead of the generic view itself. |
|---|
| 291 |
For example:: |
|---|
| 292 |
|
|---|
| 293 |
from django.views.generic.date_based import object_detail |
|---|
| 294 |
|
|---|
| 295 |
@login_required |
|---|
| 296 |
def limited_object_detail(*args, **kwargs): |
|---|
| 297 |
return object_detail(*args, **kwargs) |
|---|
| 298 |
|
|---|
| 299 |
.. _generic view: http://www.djangoproject.com/documentation/generic_views/ |
|---|
| 300 |
|
|---|
| 301 |
Permissions |
|---|
| 302 |
=========== |
|---|
| 303 |
|
|---|
| 304 |
Django comes with a simple permissions system. It provides a way to assign |
|---|
| 305 |
permissions to specific users and groups of users. |
|---|
| 306 |
|
|---|
| 307 |
It's used by the Django admin site, but you're welcome to use it in your own |
|---|
| 308 |
code. |
|---|
| 309 |
|
|---|
| 310 |
The Django admin site uses permissions as follows: |
|---|
| 311 |
|
|---|
| 312 |
* Access to view the "add" form and add an object is limited to users with |
|---|
| 313 |
the "add" permission for that type of object. |
|---|
| 314 |
* Access to view the change list, view the "change" form and change an |
|---|
| 315 |
object is limited to users with the "change" permission for that type of |
|---|
| 316 |
object. |
|---|
| 317 |
* Access to delete an object is limited to users with the "delete" |
|---|
| 318 |
permission for that type of object. |
|---|
| 319 |
|
|---|
| 320 |
Permissions are set globally per type of object, not per specific object |
|---|
| 321 |
instance. For example, it's possible to say "Mary may change news stories," but |
|---|
| 322 |
it's not currently possible to say "Mary may change news stories, but only the |
|---|
| 323 |
ones she created herself" or "Mary may only change news stories that have a |
|---|
| 324 |
certain status or publication date." The latter functionality is something |
|---|
| 325 |
Django developers are currently discussing. |
|---|
| 326 |
|
|---|
| 327 |
Default permissions |
|---|
| 328 |
------------------- |
|---|
| 329 |
|
|---|
| 330 |
Three basic permissions -- add, create and delete -- are automatically created |
|---|
| 331 |
for each Django model that has ``admin`` set. Behind the scenes, these |
|---|
| 332 |
permissions are added to the ``auth_permissions`` database table when you run |
|---|
| 333 |
``django-admin.py install [app]``. You can view the exact SQL ``INSERT`` |
|---|
| 334 |
statements by running ``django-admin.py sqlinitialdata [app]``. |
|---|
| 335 |
|
|---|
| 336 |
Note that if your model doesn't have ``admin`` set when you run |
|---|
| 337 |
``django-admin.py install``, the permissions won't be created. If you |
|---|
| 338 |
initialize your database and add ``admin`` to models after the fact, you'll |
|---|
| 339 |
need to add the permissions to the database manually. Do this by running |
|---|
| 340 |
``django-admin.py installperms [app]``, which creates any missing permissions |
|---|
| 341 |
for the given app. |
|---|
| 342 |
|
|---|
| 343 |
Custom permissions |
|---|
| 344 |
------------------ |
|---|
| 345 |
|
|---|
| 346 |
To create custom permissions for a given model object, use the ``permissions`` |
|---|
| 347 |
`model META attribute`_. |
|---|
| 348 |
|
|---|
| 349 |
This example model creates three custom permissions:: |
|---|
| 350 |
|
|---|
| 351 |
class USCitizen(meta.Model): |
|---|
| 352 |
# ... |
|---|
| 353 |
class META: |
|---|
| 354 |
permissions = ( |
|---|
| 355 |
("can_drive", "Can drive"), |
|---|
| 356 |
("can_vote", "Can vote in elections"), |
|---|
| 357 |
("can_drink", "Can drink alcohol"), |
|---|
| 358 |
) |
|---|
| 359 |
|
|---|
| 360 |
.. _model META attribute: http://www.djangoproject.com/documentation/model_api/#meta-options |
|---|
| 361 |
|
|---|
| 362 |
API reference |
|---|
| 363 |
------------- |
|---|
| 364 |
|
|---|
| 365 |
Just like users, permissions are implemented in a Django model that lives in |
|---|
| 366 |
`django/models/auth.py`_. |
|---|
| 367 |
|
|---|
| 368 |
Fields |
|---|
| 369 |
~~~~~~ |
|---|
| 370 |
|
|---|
| 371 |
``Permission`` objects have the following fields: |
|---|
| 372 |
|
|---|
| 373 |
* ``name`` -- Required. 50 characters or fewer. Example: ``'Can vote'``. |
|---|
| 374 |
* ``package`` -- Required. A reference to the ``packages`` database table, |
|---|
| 375 |
which contains a record for each installed Django application. |
|---|
| 376 |
* ``codename`` -- Required. 100 characters or fewer. Example: ``'can_vote'``. |
|---|
| 377 |
|
|---|
| 378 |
Methods |
|---|
| 379 |
~~~~~~~ |
|---|
| 380 |
|
|---|
| 381 |
``Permission`` objects have the standard data-access methods like any other |
|---|
| 382 |
`Django model`_: |
|---|
| 383 |
|
|---|
| 384 |
Authentication data in templates |
|---|
| 385 |
================================ |
|---|
| 386 |
|
|---|
| 387 |
The currently logged-in user and his/her permissions are made available in the |
|---|
| 388 |
`template context`_ when you use ``DjangoContext``. |
|---|
| 389 |
|
|---|
| 390 |
Users |
|---|
| 391 |
----- |
|---|
| 392 |
|
|---|
| 393 |
The currently logged-in user, either a ``User`` object or an``AnonymousUser`` |
|---|
| 394 |
instance, is stored in the template variable ``{{ user }}``:: |
|---|
| 395 |
|
|---|
| 396 |
{% if user.is_anonymous %} |
|---|
| 397 |
<p>Welcome, new user. Please log in.</p> |
|---|
| 398 |
{% else %} |
|---|
| 399 |
<p>Welcome, {{ user.username }}. Thanks for logging in.</p> |
|---|
| 400 |
{% endif %} |
|---|
| 401 |
|
|---|
| 402 |
Permissions |
|---|
| 403 |
----------- |
|---|
| 404 |
|
|---|
| 405 |
The currently logged-in user's permissions are stored in the template variable |
|---|
| 406 |
``{{ perms }}``. This is an instance of ``django.core.extensions.PermWrapper``, |
|---|
| 407 |
which is a template-friendly proxy of permissions. |
|---|
| 408 |
|
|---|
| 409 |
In the ``{{ perms }}`` object, single-attribute lookup is a proxy to |
|---|
| 410 |
``User.has_module_perms``. This example would display ``True`` if the logged-in |
|---|
| 411 |
user had any permissions in the ``foo`` app:: |
|---|
| 412 |
|
|---|
| 413 |
{{ perms.foo }} |
|---|
| 414 |
|
|---|
| 415 |
Two-level-attribute lookup is a proxy to ``User.has_perm``. This example would |
|---|
| 416 |
display ``True`` if the logged-in user had the permission ``foo.can_vote``:: |
|---|
| 417 |
|
|---|
| 418 |
{{ perms.foo.can_vote }} |
|---|
| 419 |
|
|---|
| 420 |
Thus, you can check permissions in template ``{% if %}`` statements:: |
|---|
| 421 |
|
|---|
| 422 |
{% if perms.foo %} |
|---|
| 423 |
<p>You have permission to do something in the foo app.</p> |
|---|
| 424 |
{% if perms.foo.can_vote %} |
|---|
| 425 |
<p>You can vote!</p> |
|---|
| 426 |
{% endif %} |
|---|
| 427 |
{% if perms.foo.can_drive %} |
|---|
| 428 |
<p>You can drive!</p> |
|---|
| 429 |
{% endif %} |
|---|
| 430 |
{% else %} |
|---|
| 431 |
<p>You don't have permission to do anything in the foo app.</p> |
|---|
| 432 |
{% endif %} |
|---|
| 433 |
|
|---|
| 434 |
.. _template context: http://www.djangoproject.com/documentation/templates_python/ |
|---|
| 435 |
|
|---|
| 436 |
Groups |
|---|
| 437 |
====== |
|---|
| 438 |
|
|---|
| 439 |
Groups are a generic way of categorizing users to apply permissions, or some |
|---|
| 440 |
other label, to those users. A user can belong to any number of groups. |
|---|
| 441 |
|
|---|
| 442 |
A user in a group automatically has the permissions granted to that group. For |
|---|
| 443 |
example, if the group ``Site editors`` has the permission |
|---|
| 444 |
``can_edit_home_page``, any user in that group will have that permission. |
|---|
| 445 |
|
|---|
| 446 |
Beyond permissions, groups are a convenient way to categorize users to apply |
|---|
| 447 |
some label, or extended functionality, to them. For example, you could create |
|---|
| 448 |
a group ``'Special users'``, and you could write code that would do special |
|---|
| 449 |
things to those users -- such as giving them access to a members-only portion |
|---|
| 450 |
of your site, or sending them members-only e-mail messages. |
|---|
| 451 |
|
|---|
| 452 |
Messages |
|---|
| 453 |
======== |
|---|
| 454 |
|
|---|
| 455 |
The message system is a lightweight way to queue messages for given users. |
|---|
| 456 |
|
|---|
| 457 |
A message is associated with a User. There's no concept of expiration or |
|---|
| 458 |
timestamps. |
|---|
| 459 |
|
|---|
| 460 |
Messages are used by the Django admin after successful actions. For example, |
|---|
| 461 |
``"The poll Foo was created successfully."`` is a message. |
|---|
| 462 |
|
|---|
| 463 |
The API is simple:: |
|---|
| 464 |
|
|---|
| 465 |
* To add messages, use ``user.add_message(message_text)``. |
|---|
| 466 |
* To retrieve/delete messages, use ``user.get_and_delete_messages()``, |
|---|
| 467 |
which returns a list of ``Message`` objects in the user's queue (if any) |
|---|
| 468 |
and deletes the messages from the queue. |
|---|
| 469 |
|
|---|
| 470 |
In this example view, the system saves a message for the user after creating |
|---|
| 471 |
a playlist:: |
|---|
| 472 |
|
|---|
| 473 |
def create_playlist(request, songs): |
|---|
| 474 |
# Create the playlist with the given songs. |
|---|
| 475 |
# ... |
|---|
| 476 |
request.user.add_message("Your playlist was added successfully.") |
|---|
| 477 |
return render_to_response("playlists/create", context_instance=DjangoContext(request)) |
|---|
| 478 |
|
|---|
| 479 |
When you use ``DjangoContext``, the currently logged-in user and his/her |
|---|
| 480 |
messages are made available in the `template context`_ as the template variable |
|---|
| 481 |
``{{ messages }}``. Here's an example of template code that displays messages:: |
|---|
| 482 |
|
|---|
| 483 |
{% if messages %} |
|---|
| 484 |
<ul> |
|---|
| 485 |
{% for message in messages %} |
|---|
| 486 |
<li>{{ message.message }}</li> |
|---|
| 487 |
{% endfor %} |
|---|
| 488 |
</ul> |
|---|
| 489 |
{% endif %} |
|---|
| 490 |
|
|---|
| 491 |
Note that ``DjangoContext`` calls ``get_and_delete_messages`` behind the |
|---|
| 492 |
scenes, so any messages will be deleted even if you don't display them. |
|---|
| 493 |
|
|---|
| 494 |
Finally, note that this messages framework only works with users in the user |
|---|
| 495 |
database. To send messages to anonymous users, use the `session framework`_. |
|---|
| 496 |
|
|---|
| 497 |
.. _session framework: http://www.djangoproject.com/documentation/sessions/ |
|---|