| ============================= |
| 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. |
| |
| Installation |
| ============ |
| |
| Authentication support is bundled as a Django application in |
| ``django.contrib.auth``. To install it, do the following: |
| |
| 1. Put ``'django.contrib.auth'`` and ``'django.contrib.contenttypes'`` in |
| your :setting:`INSTALLED_APPS` setting. |
| (The :class:`~django.contrib.auth.models.Permission` model in |
| :mod:`django.contrib.auth` depends on :mod:`django.contrib.contenttypes`.) |
| 2. Run the command ``manage.py syncdb``. |
| |
| Note that the default :file:`settings.py` file created by |
| :djadmin:`django-admin.py startproject <startproject>` includes |
| ``'django.contrib.auth'`` and ``'django.contrib.contenttypes'`` in |
| :setting:`INSTALLED_APPS` for convenience. If your :setting:`INSTALLED_APPS` |
| already contains these apps, feel free to run :djadmin:`manage.py syncdb |
| <syncdb>` again; you can run that command as many times as you'd like, and each |
| time it'll only install what's needed. |
| |
| The :djadmin:`syncdb` command creates the necessary database tables, creates |
| permission objects for all installed apps that need 'em, and prompts you to |
| create a superuser account the first time you run it. |
| |
| Once you've taken those steps, that's it. |
| |
| Users |
| ===== |
| |
| .. class:: models.User |
| |
| API reference |
| ------------- |
| |
| Fields |
| ~~~~~~ |
| |
| .. class:: models.User |
| |
| :class:`~django.contrib.auth.models.User` objects have the following |
| fields: |
| |
| .. attribute:: models.User.username |
| |
| Required. 30 characters or fewer. Alphanumeric characters only |
| (letters, digits and underscores). |
| |
| .. versionchanged:: 1.2 |
| Usernames may now contain ``@``, ``+``, ``.`` and ``-`` characters. |
| |
| .. attribute:: models.User.first_name |
| |
| Optional. 30 characters or fewer. |
| |
| .. attribute:: models.User.last_name |
| |
| Optional. 30 characters or fewer. |
| |
| .. attribute:: models.User.email |
| |
| Optional. Email 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, and the default backends do not. 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 or a custom authentication backend. However, the |
| :class:`~django.contrib.auth.forms.AuthenticationForm` used by the |
| :func:`~django.contrib.auth.views.login` view (which is the default) |
| *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: ``groups`` and ``user_permissions``. |
| :class:`~django.contrib.auth.models.User` objects can access their related |
| objects in the same way as any other :doc:`Django model |
| </topics/db/models>`: |
| |
| .. code-block:: python |
| |
| myuser.groups = [group_list] |
| myuser.groups.add(group, group, ...) |
| myuser.groups.remove(group, group, ...) |
| myuser.groups.clear() |
| myuser.user_permissions = [permission_list] |
| myuser.user_permissions.add(permission, permission, ...) |
| myuser.user_permissions.remove(permission, permission, ...) |
| myuser.user_permissions.clear() |
| |
| In addition to those automatic API methods, |
| :class:`~django.contrib.auth.models.User` objects have the following custom |
| methods: |
| |
| .. method:: models.User.is_anonymous() |
| |
| Always returns ``False``. This is a way of differentiating |
| :class:`~django.contrib.auth.models.User` and |
| :class:`~django.contrib.auth.models.AnonymousUser` objects. |
| Generally, you should prefer using |
| :meth:`~django.contrib.auth.models.User.is_authenticated()` to this |
| method. |
| |
| .. method:: models.User.is_authenticated() |
| |
| Always returns ``True``. This is a way to tell if the user has been |
| authenticated. This does not imply any permissions, and doesn't check |
| if the user is active - it only indicates that the user has provided a |
| valid username and password. |
| |
| .. method:: models.User.get_full_name() |
| |
| Returns the :attr:`~django.contrib.auth.models.User.first_name` plus |
| the :attr:`~django.contrib.auth.models.User.last_name`, with a space in |
| between. |
| |
| .. method:: models.User.set_password(raw_password) |
| |
| Sets the user's password to the given raw string, taking care of the |
| password hashing. Doesn't save the |
| :class:`~django.contrib.auth.models.User` object. |
| |
| .. method:: models.User.check_password(raw_password) |
| |
| Returns ``True`` if the given raw string is the correct password for |
| the user. (This takes care of the password hashing in making the |
| comparison.) |
| |
| .. method:: models.User.set_unusable_password() |
| |
| 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() |
| |
| Returns ``False`` if |
| :meth:`~django.contrib.auth.models.User.set_unusable_password()` has |
| been called for this user. |
| |
| .. method:: models.User.get_group_permissions(obj=None) |
| |
| Returns a set of permission strings that the user has, through his/her |
| groups. |
| |
| .. versionadded:: 1.2 |
| |
| If ``obj`` is passed in, only returns the group permissions for |
| this specific object. |
| |
| .. method:: models.User.get_all_permissions(obj=None) |
| |
| Returns a set of permission strings that the user has, both through |
| group and user permissions. |
| |
| .. versionadded:: 1.2 |
| |
| If ``obj`` is passed in, only returns the permissions for this |
| specific object. |
| |
| .. method:: models.User.has_perm(perm, obj=None) |
| |
| Returns ``True`` if the user has the specified permission, where perm is |
| in the format ``"<app label>.<permission codename>"``. (see |
| `permissions`_ section below). If the user is inactive, this method will |
| always return ``False``. |
| |
| .. versionadded:: 1.2 |
| |
| If ``obj`` is passed in, this method won't check for a permission for |
| the model, but for this specific object. |
| |
| .. method:: models.User.has_perms(perm_list, obj=None) |
| |
| Returns ``True`` if the user has each of the specified permissions, |
| where each perm is in the format |
| ``"<app label>.<permission codename>"``. If the user is inactive, |
| this method will always return ``False``. |
| |
| .. versionadded:: 1.2 |
| |
| If ``obj`` is passed in, this method won't check for permissions for |
| the model, but for the specific object. |
| |
| .. method:: models.User.has_module_perms(package_name) |
| |
| Returns ``True`` if the user has any permissions in the given package |
| (the Django app label). If the user is inactive, this method will |
| always return ``False``. |
| |
| .. method:: models.User.email_user(subject, message, from_email=None) |
| |
| Sends an email 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, or |
| :exc:`django.core.exceptions.ObjectDoesNotExist` if the user does not |
| have a profile. 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=None, password=None) |
| |
| .. versionchanged:: 1.4 |
| The ``email`` parameter was made optional. The username |
| parameter is now checked for emptiness and raises a |
| :exc:`ValueError` in case of a negative result. |
| |
| 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 converted to lowercase, and the returned |
| :class:`~django.contrib.auth.models.User` object will have |
| :attr:`~models.User.is_active` set to ``True``. |
| |
| If no password is provided, |
| :meth:`~django.contrib.auth.models.User.set_unusable_password()` will |
| be called. |
| |
| See `Creating users`_ for example usage. |
| |
| .. method:: models.UserManager.make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789') |
| |
| Returns a random password with the given length and given string of |
| allowed characters. (Note that the default value of ``allowed_chars`` |
| doesn't contain letters that can cause user confusion, including: |
| |
| * ``i``, ``l``, ``I``, and ``1`` (lowercase letter i, lowercase |
| letter L, uppercase letter i, and the number one) |
| * ``o``, ``O``, and ``0`` (uppercase letter o, lowercase letter o, |
| and zero) |
| |
| Basic usage |
| ----------- |
| |
| .. _topics-auth-creating-users: |
| |
| Creating users |
| ~~~~~~~~~~~~~~ |
| |
| The most basic way to create users is to use the |
| :meth:`~django.contrib.auth.models.UserManager.create_user` helper function |
| that comes with Django:: |
| |
| >>> from django.contrib.auth.models import User |
| >>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword') |
| |
| # At this point, user is a User object that has already been saved |
| # to the database. You can continue to change its attributes |
| # if you want to change other fields. |
| >>> user.is_staff = True |
| >>> user.save() |
| |
| You can also create users using the Django admin site. Assuming you've enabled |
| the admin site and hooked it to the URL ``/admin/``, the "Add user" page is at |
| ``/admin/auth/user/add/``. You should also see a link to "Users" in the "Auth" |
| section of the main admin index page. The "Add user" admin page is different |
| than standard admin pages in that it requires you to choose a username and |
| password before allowing you to edit the rest of the user's fields. |
| |
| Also note: if you want your own user account to be able to create users using |
| the Django admin site, you'll need to give yourself permission to add users |
| *and* change users (i.e., the "Add user" and "Change user" permissions). If |
| your account has permission to add users but not to change them, you won't be |
| able to add users. Why? Because if you have permission to add users, you have |
| the power to create superusers, which can then, in turn, change other users. So |
| Django requires add *and* change permissions as a slight security measure. |
| |
| Changing passwords |
| ~~~~~~~~~~~~~~~~~~ |
| |
| .. versionadded:: 1.2 |
| The ``manage.py changepassword`` command was added. |
| |
| :djadmin:`manage.py changepassword *username* <changepassword>` offers a method |
| of changing a User's password from the command line. It prompts you to |
| change the password of a given user which you must enter twice. If |
| they both match, the new password will be changed immediately. If you |
| do not supply a user, the command will attempt to change the password |
| whose username matches the current user. |
| |
| You can also change a password programmatically, using |
| :meth:`~django.contrib.auth.models.User.set_password()`: |
| |
| .. code-block:: python |
| |
| >>> from django.contrib.auth.models import User |
| >>> u = User.objects.get(username__exact='john') |
| >>> u.set_password('new password') |
| >>> u.save() |
| |
| Don't set the :attr:`~django.contrib.auth.models.User.password` attribute |
| directly unless you know what you're doing. This is explained in the next |
| section. |
| |
| .. _auth_password_storage: |
| |
| How Django stores passwords |
| --------------------------- |
| |
| .. versionadded:: 1.4 |
| Django 1.4 introduces a new flexible password storage system and uses |
| PBKDF2 by default. Previous versions of Django used SHA1, and other |
| algorithms couldn't be chosen. |
| |
| The :attr:`~django.contrib.auth.models.User.password` attribute of a |
| :class:`~django.contrib.auth.models.User` object is a string in this format:: |
| |
| algorithm$hash |
| |
| That's a storage algorithm, and hash, separated by the dollar-sign |
| character. The algorithm is one of a number of one way hashing or password |
| storage algorithms Django can use; see below. The hash is the result of the one- |
| way function. |
| |
| By default, Django uses the PBKDF2_ algorithm with a SHA256 hash, a |
| password stretching mechanism recommended by NIST_. This should be |
| sufficient for most users: it's quite secure, requiring massive |
| amounts of computing time to break. |
| |
| However, depending on your requirements, you may choose a different |
| algorithm, or even use a custom algorithm to match your specific |
| security situation. Again, most users shouldn't need to do this -- if |
| you're not sure, you probably don't. If you do, please read on: |
| |
| Django chooses the an algorithm by consulting the :setting:`PASSWORD_HASHERS` |
| setting. This is a list of hashing algorithm classes that this Django |
| installation supports. The first entry in this list (that is, |
| ``settings.PASSWORD_HASHERS[0]``) will be used to store passwords, and all the |
| other entries are valid hashers that can be used to check existing passwords. |
| This means that if you want to use a different algorithm, you'll need to modify |
| :setting:`PASSWORD_HASHERS` to list your prefered algorithm first in the list. |
| |
| The default for :setting:`PASSWORD_HASHERS` is:: |
| |
| PASSWORD_HASHERS = ( |
| 'django.contrib.auth.hashers.PBKDF2PasswordHasher', |
| 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', |
| 'django.contrib.auth.hashers.BCryptPasswordHasher', |
| 'django.contrib.auth.hashers.SHA1PasswordHasher', |
| 'django.contrib.auth.hashers.MD5PasswordHasher', |
| 'django.contrib.auth.hashers.CryptPasswordHasher', |
| ) |
| |
| This means that Django will use PBKDF2_ to store all passwords, but will support |
| checking passwords stored with PBKDF2SHA1, bcrypt_, SHA1_, etc. The next few |
| sections describe a couple of common ways advanced users may want to modify this |
| setting. |
| |
| .. _bcrypt_usage: |
| |
| Using bcrypt with Django |
| ~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Bcrypt_ is a popular password storage algorithm that's specifically designed |
| for long-term password storage. It's not the default used by Django since it |
| requires the use of third-party libraries, but since many people may want to |
| use it Django supports bcrypt with minimal effort. |
| |
| To use Bcrypt as your default storage algorithm, do the following: |
| |
| 1. Install the `py-bcrypt`_ library (probably by running ``sudo pip install |
| py-bcrypt``, or downloading the library and installing it with ``python |
| setup.py install``). |
| |
| 2. Modify :setting:`PASSWORD_HASHERS` to list ``BCryptPasswordHasher`` |
| first. That is, in your settings file, you'd put:: |
| |
| PASSWORD_HASHERS = ( |
| 'django.contrib.auth.hashers.BCryptPasswordHasher', |
| 'django.contrib.auth.hashers.PBKDF2PasswordHasher', |
| 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', |
| 'django.contrib.auth.hashers.SHA1PasswordHasher', |
| 'django.contrib.auth.hashers.MD5PasswordHasher', |
| 'django.contrib.auth.hashers.CryptPasswordHasher', |
| ) |
| |
| (You need to keep the other entries in this list, or else Django won't |
| be able to upgrade passwords; see below). |
| |
| That's it -- now your Django install will use Bcrypt as the default storage |
| algorithm. |
| |
| .. admonition:: Password truncation with BCryptPasswordHasher |
| |
| The designers of bcrypt truncate all passwords at 72 characters which means |
| that ``bcrypt(password_with_100_chars) == bcrypt(password_with_100_chars[:72])``. |
| ``BCryptPasswordHasher`` does not have any special handling and |
| thus is also subject to this hidden password length limit. The practical |
| ramification of this truncation is pretty marginal as the average user does |
| not have a password greater than 72 characters in length and even being |
| truncated at 72 the compute powered required to brute force bcrypt in any |
| useful amount of time is still astronomical. |
| |
| .. admonition:: Other bcrypt implementations |
| |
| There are several other implementations that allow bcrypt to be |
| used with Django. Django's bcrypt support is NOT directly |
| compatible with these. To upgrade, you will need to modify the |
| hashes in your database to be in the form `bcrypt$(raw bcrypt |
| output)`. For example: |
| `bcrypt$$2a$12$NT0I31Sa7ihGEWpka9ASYrEFkhuTNeBQ2xfZskIiiJeyFXhRgS.Sy`. |
| |
| Increasing the work factor |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The PDKDF2 and bcrypt algorithms use a number of iterations or rounds of |
| hashing. This deliberately slows down attackers, making attacks against hashed |
| passwords harder. However, as computing power increases, the number of |
| iterations needs to be increased. We've chosen a reasonable default (and will |
| increase it with each release of Django), but you may wish to tune it up or |
| down, depending on your security needs and available processing power. To do so, |
| you'll subclass the appropriate algorithm and override the ``iterations`` |
| parameters. For example, to increase the number of iterations used by the |
| default PDKDF2 algorithm: |
| |
| 1. Create a subclass of ``django.contrib.auth.hashers.PBKDF2PasswordHasher``:: |
| |
| from django.contrib.auth.hashers import PBKDF2PasswordHasher |
| |
| class MyPBKDF2PasswordHasher(PBKDF2PasswordHasher): |
| """ |
| A subclass of PBKDF2PasswordHasher that uses 100 times more iterations. |
| """ |
| iterations = PBKDF2PasswordHasher.iterations * 100 |
| |
| Save this somewhere in your project. For example, you might put this in |
| a file like ``myproject/hashers.py``. |
| |
| 2. Add your new hasher as the first entry in :setting:`PASSWORD_HASHERS`:: |
| |
| PASSWORD_HASHERS = ( |
| 'myproject.hashers.MyPBKDF2PasswordHasher', |
| 'django.contrib.auth.hashers.PBKDF2PasswordHasher', |
| 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', |
| 'django.contrib.auth.hashers.BCryptPasswordHasher', |
| 'django.contrib.auth.hashers.SHA1PasswordHasher', |
| 'django.contrib.auth.hashers.MD5PasswordHasher', |
| 'django.contrib.auth.hashers.CryptPasswordHasher', |
| ) |
| |
| |
| That's it -- now your Django install will use more iterations when it |
| stores passwords using PBKDF2. |
| |
| Password upgrading |
| ~~~~~~~~~~~~~~~~~~ |
| |
| When users log in, if their passwords are stored with anything other than |
| the preferred algorithm, Django will automatically upgrade the algorithm |
| to the preferred one. This means that old installs of Django will get |
| automatically more secure as users log in, and it also means that you |
| can switch to new (and better) storage algorithms as they get invented. |
| |
| However, Django can only upgrade passwords that use algorithms mentioned in |
| :setting:`PASSWORD_HASHERS`, so as you upgrade to new systems you should make |
| sure never to *remove* entries from this list. If you do, users using un- |
| mentioned algorithms won't be able to upgrade. |
| |
| .. _sha1: http://en.wikipedia.org/wiki/SHA1 |
| .. _pbkdf2: http://en.wikipedia.org/wiki/PBKDF2 |
| .. _nist: http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf |
| .. _bcrypt: http://en.wikipedia.org/wiki/Bcrypt |
| .. _py-bcrypt: http://pypi.python.org/pypi/py-bcrypt/ |
| |
| 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 |
| ------------------- |
| |
| :djadmin:`manage.py syncdb <syncdb>` prompts you to create a superuser the |
| first time you run it after adding ``'django.contrib.auth'`` to your |
| :setting:`INSTALLED_APPS`. If you need to create a superuser at a later date, |
| you can use a command line utility:: |
| |
| manage.py createsuperuser --username=joe --email=joe@example.com |
| |
| You will be prompted for a password. After you enter one, the user will be |
| created immediately. If you leave off the :djadminopt:`--username` or the |
| :djadminopt:`--email` options, it will prompt you for those values. |
| |
| If you're using an older release of Django, the old way of creating a superuser |
| on the command line still works:: |
| |
| python /path/to/django/contrib/auth/create_superuser.py |
| |
| ...where :file:`/path/to` is the path to the Django codebase on your |
| filesystem. The ``manage.py`` command is preferred because it figures out the |
| correct path and environment for you. |
| |
| .. _auth-profiles: |
| |
| Storing additional information about users |
| ------------------------------------------ |
| |
| If you'd like to store additional information related to your users, Django |
| provides a method to specify a site-specific related model -- termed a "user |
| profile" -- for this purpose. |
| |
| To make use of this feature, define a model with fields for the |
| additional information you'd like to store, or additional methods |
| you'd like to have available, and also add a |
| :class:`~django.db.models.Field.OneToOneField` named ``user`` 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`. For example:: |
| |
| from django.contrib.auth.models import User |
| |
| class UserProfile(models.Model): |
| # This field is required. |
| user = models.OneToOneField(User) |
| |
| # Other fields here |
| accepted_eula = models.BooleanField() |
| favorite_animal = models.CharField(max_length=20, default="Dragons.") |
| |
| |
| To indicate that this model is the user profile model for a given site, fill in |
| the setting :setting:`AUTH_PROFILE_MODULE` with a string consisting of the |
| following items, separated by a dot: |
| |
| 1. The name of the application (case sensitive) in which the user |
| profile model is defined (in other words, the |
| name which was passed to :djadmin:`manage.py startapp <startapp>` to create |
| the application). |
| |
| 2. The name of the model (not case sensitive) class. |
| |
| For example, if the profile model was a class named ``UserProfile`` and was |
| defined inside an application named ``accounts``, the appropriate setting would |
| be:: |
| |
| AUTH_PROFILE_MODULE = 'accounts.UserProfile' |
| |
| When a user profile model has been defined and specified in this manner, each |
| :class:`~django.contrib.auth.models.User` object will have a method -- |
| :class:`~django.contrib.auth.models.User.get_profile()` -- which returns the |
| instance of the user profile model associated with that |
| :class:`~django.contrib.auth.models.User`. |
| |
| The method :class:`~django.contrib.auth.models.User.get_profile()` |
| does not create a profile if one does not exist. You need to register a handler |
| for the User model's :attr:`django.db.models.signals.post_save` signal and, in |
| the handler, if ``created`` is ``True``, create the associated user profile:: |
| |
| # in models.py |
| |
| from django.contrib.auth.models import User |
| from django.db.models.signals import post_save |
| |
| # definition of UserProfile from above |
| # ... |
| |
| def create_user_profile(sender, instance, created, **kwargs): |
| if created: |
| UserProfile.objects.create(user=instance) |
| |
| post_save.connect(create_user_profile, sender=User) |
| |
| .. seealso:: :doc:`/topics/signals` for more information on Django's signal |
| dispatcher. |
| |
| Adding UserProfile fields to the admin |
| -------------------------------------- |
| |
| To add the UserProfile fields to the user page in the admin, define an |
| :class:`~django.contrib.admin.InlineModelAdmin` (for this example, we'll use a |
| :class:`~django.contrib.admin.StackedInline`) in your app's ``admin.py`` and |
| add it to a ``UserAdmin`` class which is registered with the |
| :class:`~django.contrib.auth.models.User` class:: |
| |
| from django.contrib import admin |
| from django.contrib.auth.admin import UserAdmin |
| from django.contrib.auth.models import User |
| |
| from my_user_profile_app.models import UserProfile |
| |
| # Define an inline admin descriptor for UserProfile model |
| # which acts a bit like a singleton |
| class UserProfileInline(admin.StackedInline): |
| model = UserProfile |
| can_delete = False |
| verbose_name_plural = 'profile' |
| |
| # Define a new User admin |
| class UserAdmin(UserAdmin): |
| inlines = (UserProfileInline, ) |
| |
| # Re-register UserAdmin |
| admin.site.unregister(User) |
| admin.site.register(User, UserAdmin) |
| |
| Authentication in Web requests |
| ============================== |
| |
| Until now, this document has dealt with the low-level APIs for manipulating |
| authentication-related objects. On a higher level, Django can hook this |
| authentication framework into its system of |
| :class:`request objects <django.http.HttpRequest>`. |
| |
| First, install the |
| :class:`~django.contrib.sessions.middleware.SessionMiddleware` and |
| :class:`~django.contrib.auth.middleware.AuthenticationMiddleware` |
| middlewares by adding them to your :setting:`MIDDLEWARE_CLASSES` setting. See |
| the :doc:`session documentation </topics/http/sessions>` for more information. |
| |
| Once you have those middlewares installed, you'll be able to access |
| :attr:`request.user <django.http.HttpRequest.user>` in views. |
| :attr:`request.user <django.http.HttpRequest.user>` will give you a |
| :class:`~django.contrib.auth.models.User` object representing the currently |
| logged-in user. If a user isn't currently logged in, |
| :attr:`request.user <django.http.HttpRequest.user>` will be set to an instance |
| of :class:`~django.contrib.auth.models.AnonymousUser` (see the previous |
| section). You can tell them apart with |
| :meth:`~django.contrib.auth.models.User.is_authenticated()`, like so:: |
| |
| if request.user.is_authenticated(): |
| # Do something for authenticated users. |
| else: |
| # Do something for anonymous users. |
| |
| .. _how-to-log-a-user-in: |
| |
| How to log a user in |
| -------------------- |
| |
| Django provides two functions in :mod:`django.contrib.auth`: |
| :func:`~django.contrib.auth.authenticate()` and |
| :func:`~django.contrib.auth.login()`. |
| |
| .. function:: authenticate() |
| |
| To authenticate a given username and password, use |
| :func:`~django.contrib.auth.authenticate()`. It takes two keyword |
| arguments, ``username`` and ``password``, and it returns a |
| :class:`~django.contrib.auth.models.User` object if the password is valid |
| for the given username. If the password is invalid, |
| :func:`~django.contrib.auth.authenticate()` returns ``None``. Example:: |
| |
| from django.contrib.auth import authenticate |
| user = authenticate(username='john', password='secret') |
| if user is not None: |
| if user.is_active: |
| print "You provided a correct username and password!" |
| else: |
| print "Your account has been disabled!" |
| else: |
| print "Your username and password were incorrect." |
| |
| .. function:: login() |
| |
| To log a user in, in a view, use :func:`~django.contrib.auth.login()`. It |
| takes an :class:`~django.http.HttpRequest` object and a |
| :class:`~django.contrib.auth.models.User` object. |
| :func:`~django.contrib.auth.login()` saves the user's ID in the session, |
| using Django's session framework, so, as mentioned above, you'll need to |
| make sure to have the session middleware installed. |
| |
| Note that data set during the anonymous session is retained when the user |
| logs in. |
| |
| 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 managing a user's password |
| ----------------------------------- |
| |
| .. currentmodule:: django.contrib.auth.hashers |
| |
| .. versionadded:: 1.4 |
| The :mod:`django.contrib.auth.hashers` module provides a set of functions |
| to create and validate hashed password. You can use them independently |
| from the ``User`` model. |
| |
| .. function:: check_password(password, encoded) |
| |
| .. versionadded:: 1.4 |
| |
| 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.hashers.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. |
| |
| .. function:: make_password(password[, salt, hashers]) |
| |
| .. versionadded:: 1.4 |
| |
| Creates a hashed password in the format used by this application. It takes |
| one mandatory argument: the password in plain-text. Optionally, you can |
| provide a salt and a hashing algorithm to use, if you don't want to use the |
| defaults (first entry of ``PASSWORD_HASHERS`` setting). |
| Currently supported algorithms are: ``'pbkdf2_sha256'``, ``'pbkdf2_sha1'``, |
| ``'bcrypt'`` (see :ref:`bcrypt_usage`), ``'sha1'``, ``'md5'``, |
| ``'unsalted_md5'`` (only for backward compatibility) and ``'crypt'`` |
| if you have the ``crypt`` library installed. If the password argument is |
| ``None``, an unusable password is returned (a one that will be never |
| accepted by :func:`django.contrib.auth.hashers.check_password`). |
| |
| .. function:: is_password_usable(encoded_password) |
| |
| .. versionadded:: 1.4 |
| |
| Checks if the given string is a hashed password that has a chance |
| of being verified against :func:`django.contrib.auth.hashers.check_password`. |
| |
| |
| How to log a user out |
| --------------------- |
| |
| .. currentmodule:: django.contrib.auth |
| |
| .. 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. |
| |
| 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()`. |
| |
| .. _topics-auth-signals: |
| |
| Login and logout signals |
| ------------------------ |
| |
| .. versionadded:: 1.3 |
| |
| The auth framework uses two :doc:`signals </topics/signals>` that can be used |
| for notification when a user logs in or out. |
| |
| .. data:: django.contrib.auth.signals.user_logged_in |
| |
| Sent when a user logs in successfully. |
| |
| Arguments sent with this signal: |
| |
| ``sender`` |
| As above: the class of the user that just logged in. |
| |
| ``request`` |
| The current :class:`~django.http.HttpRequest` instance. |
| |
| ``user`` |
| The user instance that just logged in. |
| |
| .. data:: django.contrib.auth.signals.user_logged_out |
| |
| Sent when the logout method is called. |
| |
| ``sender`` |
| As above: the class of the user that just logged out or ``None`` |
| if the user was not authenticated. |
| |
| ``request`` |
| The current :class:`~django.http.HttpRequest` instance. |
| |
| ``user`` |
| The user instance that just logged out or ``None`` if the |
| user was not authenticated. |
| |
| Limiting access to logged-in users |
| ---------------------------------- |
| |
| The raw way |
| ~~~~~~~~~~~ |
| |
| The simple, raw way to limit access to pages is to check |
| :meth:`request.user.is_authenticated() |
| <django.contrib.auth.models.User.is_authenticated()>` and either redirect to a |
| login page:: |
| |
| from django.http import HttpResponseRedirect |
| |
| def my_view(request): |
| if not request.user.is_authenticated(): |
| return HttpResponseRedirect('/login/?next=%s' % request.path) |
| # ... |
| |
| ...or display an error message:: |
| |
| def my_view(request): |
| if not request.user.is_authenticated(): |
| return render_to_response('myapp/login_error.html') |
| # ... |
| |
| The login_required decorator |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. function:: decorators.login_required([redirect_field_name=REDIRECT_FIELD_NAME, login_url=None]) |
| |
| As a shortcut, you can use the convenient |
| :func:`~django.contrib.auth.decorators.login_required` decorator:: |
| |
| from django.contrib.auth.decorators import login_required |
| |
| @login_required |
| def my_view(request): |
| ... |
| |
| :func:`~django.contrib.auth.decorators.login_required` does the following: |
| |
| * If the user isn't logged in, redirect to |
| :setting:`settings.LOGIN_URL <LOGIN_URL>`, passing the current absolute |
| path in the query string. Example: ``/accounts/login/?next=/polls/3/``. |
| |
| * If the user is logged in, execute the view normally. The view code is |
| free to assume the user is logged in. |
| |
| By default, the path that the user should be redirected to upon |
| successful authentication is stored in a query string parameter called |
| ``"next"``. If you would prefer to use a different name for this parameter, |
| :func:`~django.contrib.auth.decorators.login_required` takes an |
| optional ``redirect_field_name`` parameter:: |
| |
| from django.contrib.auth.decorators import login_required |
| |
| @login_required(redirect_field_name='my_redirect_field') |
| def my_view(request): |
| ... |
| |
| Note that 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 its key rather than ``"next"`` (the default). |
| |
| .. versionadded:: 1.3 |
| |
| :func:`~django.contrib.auth.decorators.login_required` also takes an |
| optional ``login_url`` parameter. Example:: |
| |
| from django.contrib.auth.decorators import login_required |
| |
| @login_required(login_url='/accounts/login/') |
| def my_view(request): |
| ... |
| |
| Note that if you don't specify the ``login_url`` parameter, you'll need to map |
| the appropriate Django view to :setting:`settings.LOGIN_URL <LOGIN_URL>`. For |
| example, using the defaults, add the following line to your URLconf:: |
| |
| (r'^accounts/login/$', 'django.contrib.auth.views.login'), |
| |
| .. function:: views.login(request, [template_name, redirect_field_name, authentication_form]) |
| |
| **URL name:** ``login`` |
| |
| See :doc:`the URL documentation </topics/http/urls>` for details on using |
| named URL patterns. |
| |
| Here's what ``django.contrib.auth.views.login`` does: |
| |
| * If called via ``GET``, it displays a login form that POSTs to the |
| same URL. More on this in a bit. |
| |
| * If called via ``POST``, it tries to log the user in. If login is |
| successful, the view redirects to the URL specified in ``next``. If |
| ``next`` isn't provided, it redirects to |
| :setting:`settings.LOGIN_REDIRECT_URL <LOGIN_REDIRECT_URL>` (which |
| defaults to ``/accounts/profile/``). If login isn't successful, it |
| redisplays the login form. |
| |
| It's your responsibility to provide the login form in a template called |
| ``registration/login.html`` by default. This template gets passed four |
| template context variables: |
| |
| * ``form``: A :class:`~django.forms.Form` object representing the login |
| form. See the :doc:`forms documentation </topics/forms/index>` for |
| more on ``Form`` objects. |
| |
| * ``next``: The URL to redirect to after successful login. This may |
| contain a query string, too. |
| |
| * ``site``: The current :class:`~django.contrib.sites.models.Site`, |
| according to the :setting:`SITE_ID` setting. If you don't have the |
| site framework installed, this will be set to an instance of |
| :class:`~django.contrib.sites.models.RequestSite`, which derives the |
| site name and domain from the current |
| :class:`~django.http.HttpRequest`. |
| |
| * ``site_name``: An alias for ``site.name``. If you don't have the site |
| framework installed, this will be set to the value of |
| :attr:`request.META['SERVER_NAME'] <django.http.HttpRequest.META>`. |
| For more on sites, see :doc:`/ref/contrib/sites`. |
| |
| If you'd prefer not to call the template :file:`registration/login.html`, |
| you can pass the ``template_name`` parameter via the extra arguments to |
| the view in your URLconf. For example, this URLconf line would use |
| :file:`myapp/login.html` instead:: |
| |
| (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}), |
| |
| You can also specify the name of the ``GET`` field which contains the URL |
| to redirect to after login by passing ``redirect_field_name`` to the view. |
| By default, the field is called ``next``. |
| |
| Here's a sample :file:`registration/login.html` template you can use as a |
| starting point. It assumes you have a :file:`base.html` template that |
| defines a ``content`` block: |
| |
| .. code-block:: html+django |
| |
| {% extends "base.html" %} |
| {% load url from future %} |
| |
| {% block content %} |
| |
| {% if form.errors %} |
| <p>Your username and password didn't match. Please try again.</p> |
| {% endif %} |
| |
| <form method="post" action="{% url 'django.contrib.auth.views.login' %}"> |
| {% csrf_token %} |
| <table> |
| <tr> |
| <td>{{ form.username.label_tag }}</td> |
| <td>{{ form.username }}</td> |
| </tr> |
| <tr> |
| <td>{{ form.password.label_tag }}</td> |
| <td>{{ form.password }}</td> |
| </tr> |
| </table> |
| |
| <input type="submit" value="login" /> |
| <input type="hidden" name="next" value="{{ next }}" /> |
| </form> |
| |
| {% endblock %} |
| |
| .. versionadded:: 1.2 |
| |
| If you are using alternate authentication (see |
| :ref:`authentication-backends`) you can pass a custom authentication form |
| to the login view via the ``authentication_form`` parameter. This form must |
| accept a ``request`` keyword argument in its ``__init__`` method, and |
| provide a ``get_user`` method which returns the authenticated user object |
| (this method is only ever called after successful form validation). |
| |
| .. _forms documentation: ../forms/ |
| .. _site framework docs: ../sites/ |
| |
| .. versionadded:: 1.4 |
| |
| The :func:`~views.login` view and the :ref:`other-built-in-views` now all |
| return a :class:`~django.template.response.TemplateResponse` instance, |
| which allows you to easily customize the response data before rendering. |
| For more details, see the |
| :doc:`TemplateResponse documentation </ref/template-response>`. |
| |
| .. _other-built-in-views: |
| |
| Other built-in views |
| -------------------- |
| |
| .. module:: django.contrib.auth.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:: logout(request, [next_page, template_name, redirect_field_name]) |
| |
| Logs a user out. |
| |
| **URL name:** ``logout`` |
| |
| See :doc:`the URL documentation </topics/http/urls>` for details on using |
| named URL patterns. |
| |
| **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. Defaults 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. |
| |
| * ``site``: The current :class:`~django.contrib.sites.models.Site`, |
| according to the :setting:`SITE_ID` setting. If you don't have the |
| site framework installed, this will be set to an instance of |
| :class:`~django.contrib.sites.models.RequestSite`, which derives the |
| site name and domain from the current |
| :class:`~django.http.HttpRequest`. |
| |
| * ``site_name``: An alias for ``site.name``. If you don't have the site |
| framework installed, this will be set to the value of |
| :attr:`request.META['SERVER_NAME'] <django.http.HttpRequest.META>`. |
| For more on sites, see :doc:`/ref/contrib/sites`. |
| |
| .. function:: logout_then_login(request[, login_url]) |
| |
| Logs a user out, then redirects to the login page. |
| |
| **URL name:** No default URL provided |
| |
| **Optional arguments:** |
| |
| * ``login_url``: The URL of the login page to redirect to. |
| Defaults to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied. |
| |
| .. function:: password_change(request[, template_name, post_change_redirect, password_change_form]) |
| |
| Allows a user to change their password. |
| |
| **URL name:** ``password_change`` |
| |
| **Optional arguments:** |
| |
| * ``template_name``: The full name of a template to use for |
| displaying the password change form. Defaults 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. Defaults to |
| :class:`~django.contrib.auth.forms.PasswordChangeForm`. |
| |
| **Template context:** |
| |
| * ``form``: The password change form (see ``password_change_form`` above). |
| |
| .. function:: password_change_done(request[, template_name]) |
| |
| The page shown after a user has changed their password. |
| |
| **URL name:** ``password_change_done`` |
| |
| **Optional arguments:** |
| |
| * ``template_name``: The full name of a template to use. |
| Defaults to :file:`registration/password_change_done.html` if not |
| supplied. |
| |
| .. function:: password_reset(request[, is_admin_site, template_name, email_template_name, password_reset_form, token_generator, post_reset_redirect, from_email]) |
| |
| 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 email address. |
| |
| .. versionchanged:: 1.3 |
| The ``from_email`` argument was added. |
| |
| .. versionchanged:: 1.4 |
| Users flagged with an unusable password (see |
| :meth:`~django.contrib.auth.models.User.set_unusable_password()` |
| will not be able to request a password reset to prevent misuse |
| when using an external authentication source like LDAP. |
| |
| **URL name:** ``password_reset`` |
| |
| **Optional arguments:** |
| |
| * ``template_name``: The full name of a template to use for |
| displaying the password reset form. Defaults to |
| :file:`registration/password_reset_form.html` if not supplied. |
| |
| * ``email_template_name``: The full name of a template to use for |
| generating the email with the reset password link. Defaults to |
| :file:`registration/password_reset_email.html` if not supplied. |
| |
| * ``subject_template_name``: The full name of a template to use for |
| the subject of the email with the reset password link. Defaults |
| to :file:`registration/password_reset_subject.txt` if not supplied. |
| |
| .. versionadded:: 1.4 |
| |
| * ``password_reset_form``: Form that will be used to get the email of |
| the user to reset the password for. Defaults to |
| :class:`~django.contrib.auth.forms.PasswordResetForm`. |
| |
| * ``token_generator``: Instance of the class to check the one time link. |
| 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 reset request. |
| |
| * ``from_email``: A valid email address. By default Django uses |
| the :setting:`DEFAULT_FROM_EMAIL`. |
| |
| **Template context:** |
| |
| * ``form``: The form (see ``password_reset_form`` above) for resetting |
| the user's password. |
| |
| **Email template context:** |
| |
| * ``email``: An alias for ``user.email`` |
| |
| * ``user``: The current :class:`~django.contrib.auth.models.User`, |
| according to the ``email`` form field. Only active users are able to |
| reset their passwords (``User.is_active is True``). |
| |
| * ``site_name``: An alias for ``site.name``. If you don't have the site |
| framework installed, this will be set to the value of |
| :attr:`request.META['SERVER_NAME'] <django.http.HttpRequest.META>`. |
| For more on sites, see :doc:`/ref/contrib/sites`. |
| |
| * ``domain``: An alias for ``site.domain``. If you don't have the site |
| framework installed, this will be set to the value of |
| ``request.get_host()``. |
| |
| * ``protocol``: http or https |
| |
| * ``uid``: The user's id encoded in base 36. |
| |
| * ``token``: Token to check that the reset link is valid. |
| |
| Sample ``registration/password_reset_email.html`` (email body template): |
| |
| .. code-block:: html+django |
| |
| {% load url from future %} |
| Someone asked for password reset for email {{ email }}. Follow the link below: |
| {{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb36=uid token=token %} |
| |
| The same template context is used for subject template. Subject must be |
| single line plain text string. |
| |
| |
| .. function:: password_reset_done(request[, template_name]) |
| |
| The page shown after a user has been emailed a link to reset their |
| password. This view is called by default if the :func:`password_reset` view |
| doesn't have an explicit ``post_reset_redirect`` URL set. |
| |
| **URL name:** ``password_reset_done`` |
| |
| **Optional arguments:** |
| |
| * ``template_name``: The full name of a template to use. |
| Defaults to :file:`registration/password_reset_done.html` if not |
| supplied. |
| |
| .. 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. |
| |
| **URL name:** ``password_reset_confirm`` |
| |
| **Optional arguments:** |
| |
| * ``uidb36``: The user's id encoded in base 36. Defaults to ``None``. |
| |
| * ``token``: Token to check that the password is valid. Defaults 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. |
| Defaults to :class:`~django.contrib.auth.forms.SetPasswordForm` |
| |
| * ``post_reset_redirect``: URL to redirect after the password reset |
| done. Defaults to ``None``. |
| |
| **Template context:** |
| |
| * ``form``: The form (see ``set_password_form`` above) for setting the |
| new user's password. |
| |
| * ``validlink``: Boolean, True if the link (combination of uidb36 and |
| token) is valid or unused yet. |
| |
| .. function:: password_reset_complete(request[,template_name]) |
| |
| Presents a view which informs the user that the password has been |
| successfully changed. |
| |
| **URL name:** ``password_reset_complete`` |
| |
| **Optional arguments:** |
| |
| * ``template_name``: The full name of a template to display the view. |
| Defaults to :file:`registration/password_reset_complete.html`. |
| |
| Helper functions |
| ---------------- |
| |
| .. currentmodule:: django.contrib.auth.views |
| |
| .. function:: 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. |
| Defaults to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied. |
| |
| * ``redirect_field_name``: The name of a ``GET`` field containing the |
| URL to redirect to after log out. Overrides ``next`` if the given |
| ``GET`` parameter is passed. |
| |
| 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 emailing 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.decorators |
| |
| To limit access based on certain permissions or some other test, you'd do |
| essentially the same thing as described in the previous section. |
| |
| The simple way is to run your test on :attr:`request.user |
| <django.http.HttpRequest.user>` in the view directly. For example, this view |
| checks to make sure the user is logged in and has the permission |
| ``polls.can_vote``:: |
| |
| def my_view(request): |
| if not request.user.has_perm('polls.can_vote'): |
| return HttpResponse("You can't vote in this poll.") |
| # ... |
| |
| .. function:: user_passes_test(func, [login_url=None]) |
| |
| As a shortcut, you can use the convenient ``user_passes_test`` decorator:: |
| |
| from django.contrib.auth.decorators import user_passes_test |
| |
| @user_passes_test(lambda u: u.has_perm('polls.can_vote')) |
| def my_view(request): |
| ... |
| |
| We're using this particular test as a relatively simple example. However, |
| if you just want to test whether a permission is available to a user, you |
| can use the :func:`~django.contrib.auth.decorators.permission_required()` |
| decorator, described later in this document. |
| |
| :func:`~django.contrib.auth.decorators.user_passes_test` takes a required |
| argument: a callable that takes a |
| :class:`~django.contrib.auth.models.User` object and returns ``True`` if |
| the user is allowed to view the page. Note that |
| :func:`~django.contrib.auth.decorators.user_passes_test` does not |
| automatically check that the :class:`~django.contrib.auth.models.User` is |
| not anonymous. |
| |
| :func:`~django.contrib.auth.decorators.user_passes_test()` takes an |
| optional ``login_url`` argument, which lets you specify the URL for your |
| login page (:setting:`settings.LOGIN_URL <LOGIN_URL>` by default). |
| |
| For example:: |
| |
| from django.contrib.auth.decorators import user_passes_test |
| |
| @user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/') |
| def my_view(request): |
| ... |
| |
| The permission_required decorator |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. function:: permission_required([login_url=None, raise_exception=False]) |
| |
| It's a relatively common task to check whether a user has a particular |
| permission. For that reason, Django provides a shortcut for that case: the |
| :func:`~django.contrib.auth.decorators.permission_required()` decorator. |
| Using this decorator, the earlier example can be written as:: |
| |
| from django.contrib.auth.decorators import permission_required |
| |
| @permission_required('polls.can_vote') |
| def my_view(request): |
| ... |
| |
| As for the :meth:`User.has_perm` method, permission names take the form |
| ``"<app label>.<permission codename>"`` (i.e. ``polls.can_vote`` for a |
| permission on a model in the ``polls`` application). |
| |
| Note that :func:`~django.contrib.auth.decorators.permission_required()` |
| also takes an optional ``login_url`` parameter. Example:: |
| |
| from django.contrib.auth.decorators import permission_required |
| |
| @permission_required('polls.can_vote', login_url='/loginpage/') |
| def my_view(request): |
| ... |
| |
| As in the :func:`~decorators.login_required` decorator, ``login_url`` |
| defaults to :setting:`settings.LOGIN_URL <LOGIN_URL>`. |
| |
| .. versionchanged:: 1.4 |
| |
| Added ``raise_exception`` parameter. If given, the decorator will raise |
| :exc:`~django.core.exceptions.PermissionDenied`, prompting |
| :ref:`the 403 (HTTP Forbidden) view<http_forbidden_view>` instead of |
| redirecting to the login page. |
| |
| .. currentmodule:: django.contrib.auth |
| |
| Applying permissions to generic views |
| ------------------------------------- |
| |
| To apply a permission to a :doc:`class-based generic view |
| </ref/class-based-views>`, decorate the :meth:`View.dispatch |
| <django.views.generic.base.View.dispatch>` method on the class. See |
| :ref:`decorating-class-based-views` for details. |
| |
| Function-based generic views |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| To limit access to a :doc:`function-based generic view </ref/generic-views>`, |
| write a thin wrapper around the view, and point your URLconf to your wrapper |
| instead of the generic view itself. For example:: |
| |
| from django.views.generic.date_based import object_detail |
| |
| @login_required |
| def limited_object_detail(*args, **kwargs): |
| return object_detail(*args, **kwargs) |
| |
| .. _permissions: |
| |
| Permissions |
| =========== |
| |
| Django comes with a simple permissions system. It provides a way to assign |
| permissions to specific users and groups of users. |
| |
| It's used by the Django admin site, but you're welcome to use it in your own |
| code. |
| |
| The Django admin site uses permissions as follows: |
| |
| * Access to view the "add" form and add an object is limited to users with |
| the "add" permission for that type of object. |
| * Access to view the change list, view the "change" form and change an |
| object is limited to users with the "change" permission for that type of |
| object. |
| * Access to delete an object is limited to users with the "delete" |
| permission for that type of object. |
| |
| Permissions can be set not only per type of object, but also per specific |
| object instance. By using the |
| :meth:`~django.contrib.admin.ModelAdmin.has_add_permission`, |
| :meth:`~django.contrib.admin.ModelAdmin.has_change_permission` and |
| :meth:`~django.contrib.admin.ModelAdmin.has_delete_permission` methods provided |
| by the :class:`~django.contrib.admin.ModelAdmin` class, it is possible to |
| customize permissions for different object instances of the same type. |
| |
| Default permissions |
| ------------------- |
| |
| When ``django.contrib.auth`` is listed in your :setting:`INSTALLED_APPS` |
| setting, it will ensure that three default permissions -- add, change and |
| delete -- are created for each Django model defined in one of your installed |
| applications. |
| |
| These permissions will be created when you run :djadmin:`manage.py syncdb |
| <syncdb>`; the first time you run ``syncdb`` after adding |
| ``django.contrib.auth`` to :setting:`INSTALLED_APPS`, the default permissions |
| will be created for all previously-installed models, as well as for any new |
| models being installed at that time. Afterward, it will create default |
| permissions for new models each time you run :djadmin:`manage.py syncdb |
| <syncdb>`. |
| |
| Assuming you have an application with an |
| :attr:`~django.db.models.Options.app_label` ``foo`` and a model named ``Bar``, |
| to test for basic permissions you should use: |
| |
| * add: ``user.has_perm('foo.add_bar')`` |
| * change: ``user.has_perm('foo.change_bar')`` |
| * delete: ``user.has_perm('foo.delete_bar')`` |
| |
| .. _custom-permissions: |
| |
| Custom permissions |
| ------------------ |
| |
| To create custom permissions for a given model object, use the ``permissions`` |
| :ref:`model Meta attribute <meta-options>`. |
| |
| This example Task model creates three custom permissions, i.e., actions users |
| can or cannot do with Task instances, specific to your application:: |
| |
| class Task(models.Model): |
| ... |
| class Meta: |
| permissions = ( |
| ("view_task", "Can see available tasks"), |
| ("change_task_status", "Can change the status of tasks"), |
| ("close_task", "Can remove a task by setting its status as closed"), |
| ) |
| |
| The only thing this does is create those extra permissions when you run |
| :djadmin:`manage.py syncdb <syncdb>`. Your code is in charge of checking the |
| value of these permissions when an user is trying to access the functionality |
| provided by the application (viewing tasks, changing the status of tasks, |
| closing tasks.) Continuing the above example, the following checks if a user may |
| view tasks:: |
| |
| user.has_perm('app.view_task') |
| |
| API reference |
| ------------- |
| |
| .. currentmodule:: django.contrib.auth.models |
| |
| .. class:: models.Permission |
| |
| Fields |
| ~~~~~~ |
| |
| :class:`~django.contrib.auth.models.Permission` objects have the following |
| fields: |
| |
| .. attribute:: Permission.name |
| |
| Required. 50 characters or fewer. Example: ``'Can vote'``. |
| |
| .. attribute:: Permission.content_type |
| |
| Required. A reference to the ``django_content_type`` database table, which |
| contains a record for each installed Django model. |
| |
| .. attribute:: Permission.codename |
| |
| Required. 100 characters or fewer. Example: ``'can_vote'``. |
| |
| Methods |
| ~~~~~~~ |
| |
| :class:`~django.contrib.auth.models.Permission` objects have the standard |
| data-access methods like any other :doc:`Django model </ref/models/instances>`. |
| |
| .. currentmodule:: django.contrib.auth |
| |
| Programmatically creating permissions |
| ------------------------------------- |
| |
| While custom permissions can be defined within a model's ``Meta`` class, you |
| can also create permissions directly. For example, you can create the |
| ``can_publish`` permission for a ``BlogPost`` model in ``myapp``:: |
| |
| from myapp.models import BlogPost |
| from django.contrib.auth.models import Group, Permission |
| from django.contrib.contenttypes.models import ContentType |
| |
| content_type = ContentType.objects.get_for_model(BlogPost) |
| permission = Permission.objects.create(codename='can_publish', |
| name='Can Publish Posts', |
| content_type=content_type) |
| |
| The permission can then be assigned to a |
| :class:`~django.contrib.auth.models.User` via its ``user_permissions`` |
| attribute or to a :class:`~django.contrib.auth.models.Group` via its |
| ``permissions`` attribute. |
| |
| Authentication data in templates |
| ================================ |
| |
| The currently logged-in user and his/her permissions are made available in the |
| :doc:`template context </ref/templates/api>` when you use |
| :class:`~django.template.context.RequestContext`. |
| |
| .. admonition:: Technicality |
| |
| Technically, these variables are only made available in the template context |
| if you use :class:`~django.template.context.RequestContext` *and* your |
| :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting contains |
| ``"django.contrib.auth.context_processors.auth"``, which is default. For |
| more, see the :ref:`RequestContext docs <subclassing-context-requestcontext>`. |
| |
| Users |
| ----- |
| |
| When rendering a template :class:`~django.template.context.RequestContext`, the |
| currently logged-in user, either a :class:`~django.contrib.auth.models.User` |
| instance or an :class:`~django.contrib.auth.models.AnonymousUser` instance, is |
| stored in the template variable ``{{ user }}``: |
| |
| .. code-block:: html+django |
| |
| {% if user.is_authenticated %} |
| <p>Welcome, {{ user.username }}. Thanks for logging in.</p> |
| {% else %} |
| <p>Welcome, new user. Please log in.</p> |
| {% endif %} |
| |
| This template context variable is not available if a ``RequestContext`` is not |
| being used. |
| |
| Permissions |
| ----------- |
| |
| The currently logged-in user's permissions are stored in the template variable |
| ``{{ perms }}``. This is an instance of |
| :class:`django.contrib.auth.context_processors.PermWrapper`, which is a |
| template-friendly proxy of permissions. |
| |
| .. versionchanged:: 1.3 |
| Prior to version 1.3, ``PermWrapper`` was located in |
| ``django.core.context_processors``. |
| |
| In the ``{{ perms }}`` object, single-attribute lookup is a proxy to |
| :meth:`User.has_module_perms <django.contrib.auth.models.User.has_module_perms>`. |
| This example would display ``True`` if the logged-in user had any permissions |
| in the ``foo`` app:: |
| |
| {{ perms.foo }} |
| |
| Two-level-attribute lookup is a proxy to |
| :meth:`User.has_perm <django.contrib.auth.models.User.has_perm>`. This example |
| would display ``True`` if the logged-in user had the permission |
| ``foo.can_vote``:: |
| |
| {{ perms.foo.can_vote }} |
| |
| Thus, you can check permissions in template ``{% if %}`` statements: |
| |
| .. code-block:: html+django |
| |
| {% if perms.foo %} |
| <p>You have permission to do something in the foo app.</p> |
| {% if perms.foo.can_vote %} |
| <p>You can vote!</p> |
| {% endif %} |
| {% if perms.foo.can_drive %} |
| <p>You can drive!</p> |
| {% endif %} |
| {% else %} |
| <p>You don't have permission to do anything in the foo app.</p> |
| {% endif %} |
| |
| Groups |
| ====== |
| |
| Groups are a generic way of categorizing users so you can apply permissions, or |
| some other label, to those users. A user can belong to any number of groups. |
| |
| A user in a group automatically has the permissions granted to that group. For |
| example, if the group ``Site editors`` has the permission |
| ``can_edit_home_page``, any user in that group will have that permission. |
| |
| Beyond permissions, groups are a convenient way to categorize users to give |
| them some label, or extended functionality. For example, you could create a |
| group ``'Special users'``, and you could write code that could, say, give them |
| access to a members-only portion of your site, or send them members-only email |
| messages. |
| |
| API reference |
| ------------- |
| |
| .. class:: models.Group |
| |
| Fields |
| ~~~~~~ |
| |
| :class:`~django.contrib.auth.models.Group` objects have the following fields: |
| |
| .. attribute:: Group.name |
| |
| Required. 80 characters or fewer. Any characters are permitted. Example: |
| ``'Awesome Users'``. |
| |
| .. attribute:: Group.permissions |
| |
| Many-to-many field to :class:`~django.contrib.auth.models.Permissions`:: |
| |
| group.permissions = [permission_list] |
| group.permissions.add(permission, permission, ...) |
| group.permissions.remove(permission, permission, ...) |
| group.permissions.clear() |
| |
| .. _authentication-backends: |
| |
| Other authentication sources |
| ============================ |
| |
| The authentication that comes with Django is good enough for most common cases, |
| but you may have the need to hook into another authentication source -- that |
| is, another source of usernames and passwords or authentication methods. |
| |
| For example, your company may already have an LDAP setup that stores a username |
| and password for every employee. It'd be a hassle for both the network |
| administrator and the users themselves if users had separate accounts in LDAP |
| and the Django-based applications. |
| |
| So, to handle situations like this, the Django authentication system lets you |
| plug in other authentication sources. You can override Django's default |
| database-based scheme, or you can use the default system in tandem with other |
| systems. |
| |
| See the :doc:`authentication backend reference </ref/authbackends>` |
| for information on the authentication backends included with Django. |
| |
| Specifying authentication backends |
| ---------------------------------- |
| |
| Behind the scenes, Django maintains a list of "authentication backends" that it |
| checks for authentication. When somebody calls |
| :func:`django.contrib.auth.authenticate()` -- as described in :ref:`How to log |
| a user in <how-to-log-a-user-in>` above -- Django tries authenticating across |
| all of its authentication backends. If the first authentication method fails, |
| Django tries the second one, and so on, until all backends have been attempted. |
| |
| The list of authentication backends to use is specified in the |
| :setting:`AUTHENTICATION_BACKENDS` setting. This should be a tuple of Python |
| path names that point to Python classes that know how to authenticate. These |
| classes can be anywhere on your Python path. |
| |
| By default, :setting:`AUTHENTICATION_BACKENDS` is set to:: |
| |
| ('django.contrib.auth.backends.ModelBackend',) |
| |
| That's the basic authentication backend that checks the Django users database |
| and queries the builtin permissions. It does not provide protection against |
| brute force attacks via any rate limiting mechanism. You may either implement |
| your own rate limiting mechanism in a custom auth backend, or use the |
| mechanisms provided by most Web servers. |
| |
| 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 the duration of that session whenever access to the currently |
| authenticated user is needed. This effectively means that authentication |
| sources are cached on a per-session basis, 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 required methods: |
| ``get_user(user_id)`` and ``authenticate(**credentials)``, as well as a set of |
| optional permission related :ref:`authorization methods <authorization_methods>`. |
| |
| 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(object): |
| 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(object): |
| 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(object): |
| """ |
| 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' |
| """ |
| |
| supports_inactive_user = False |
| |
| 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 |
| |
| .. _authorization_methods: |
| |
| 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(object): |
| |
| # ... |
| |
| def has_perm(self, user_obj, perm, obj=None): |
| 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 in addition to the same arguments given to the associated |
| :class:`django.contrib.auth.models.User` functions, the backend auth functions |
| all take the user object, which may be an anonymous user, as an argument. |
| |
| A full authorization implementation can be found in the ``ModelBackend`` class |
| in `django/contrib/auth/backends.py`_, which is the default backend and queries |
| the ``auth_permission`` table most of the time. If you wish to provide |
| custom behavior for only part of the backend API, you can take advantage of |
| Python inheritence and subclass ``ModelBackend`` instead of implementing the |
| complete API in a custom backend. |
| |
| .. _django/contrib/auth/backends.py: https://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py |
| |
| .. _anonymous_auth: |
| |
| 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, the user object passed to an authentication backend |
| may be an :class:`django.contrib.auth.models.AnonymousUser` object, allowing |
| the backend to specify custom authorization behavior 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. |
| |
| .. _inactive_auth: |
| |
| Authorization for inactive users |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. versionchanged:: 1.3 |
| |
| An inactive user is a one that is authenticated but has its attribute |
| ``is_active`` set to ``False``. However this does not mean they are not |
| authorized to do anything. For example they are allowed to activate their |
| account. |
| |
| The support for anonymous users in the permission system allows for a scenario |
| where anonymous users have permissions to do something while inactive |
| authenticated users do not. |
| |
| To enable this on your own backend, you must set the class attribute |
| ``supports_inactive_user`` to ``True``. |
| |
| A nonexisting ``supports_inactive_user`` attribute will raise a |
| ``PendingDeprecationWarning`` if used in Django 1.3. In Django 1.4, this |
| warning will be updated to a ``DeprecationWarning`` which will be displayed |
| loudly. Additionally ``supports_inactive_user`` will be set to ``False``. |
| Django 1.5 will assume that every backend supports inactive 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). An authentication backend will receive the keyword |
| parameters ``obj`` and ``user_obj`` for each object related authorization |
| method and can return the object level permission as appropriate. |