1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408 |
- .. _topics-auth:
- =============================
- User authentication in Django
- =============================
- .. module:: django.contrib.auth
- :synopsis: Django's authentication framework.
- Django comes with a user authentication system. It handles user accounts,
- groups, permissions and cookie-based user sessions. This document explains how
- things work.
- Overview
- ========
- The auth system consists of:
- * Users
- * Permissions: Binary (yes/no) flags designating whether a user may perform
- a certain task.
- * Groups: A generic way of applying labels and permissions to more than one
- user.
- * Messages: A simple way to queue messages for given users.
- Installation
- ============
- Authentication support is bundled as a Django application in
- ``django.contrib.auth``. To install it, do the following:
- 1. Put ``'django.contrib.auth'`` in your :setting:`INSTALLED_APPS` setting.
- 2. Run the command ``manage.py syncdb``.
- Note that the default :file:`settings.py` file created by
- :djadmin:`django-admin.py startproject` includes ``'django.contrib.auth'`` in
- :setting:`INSTALLED_APPS` for convenience. If your :setting:`INSTALLED_APPS`
- already contains ``'django.contrib.auth'``, feel free to run
- :djadmin:`manage.py syncdb` again; you can run that command as many times as
- you'd like, and each time it'll only install what's needed.
- The :djadmin:`syncdb` command creates the necessary database tables, creates
- permission objects for all installed apps that need 'em, and prompts you to
- create a superuser account the first time you run it.
- Once you've taken those steps, that's it.
- Users
- =====
- .. class:: models.User
- API reference
- -------------
- Fields
- ~~~~~~
- .. class:: models.User
- :class:`~django.contrib.auth.models.User` objects have the following
- fields:
- .. attribute:: models.User.username
- Required. 30 characters or fewer. Alphanumeric characters only
- (letters, digits and underscores).
- .. attribute:: models.User.first_name
- Optional. 30 characters or fewer.
- .. attribute:: models.User.last_name
- Optional. 30 characters or fewer.
- .. attribute:: models.User.email
- Optional. E-mail address.
- .. attribute:: models.User.password
- Required. A hash of, and metadata about, the password. (Django doesn't
- store the raw password.) Raw passwords can be arbitrarily long and can
- contain any character. See the "Passwords" section below.
- .. attribute:: models.User.is_staff
- Boolean. Designates whether this user can access the admin site.
- .. attribute:: models.User.is_active
- Boolean. Designates whether this user account should be considered
- active. Set this flag to ``False`` instead of deleting accounts.
- This doesn't control whether or not the user can log in. Nothing in the
- authentication path checks the ``is_active`` flag, so if you want to
- reject a login based on ``is_active`` being ``False``, it is up to you
- to check that in your own login view. However, permission checking
- using the methods like :meth:`~models.User.has_perm` does check this
- flag and will always return ``False`` for inactive users.
- .. attribute:: models.User.is_superuser
- Boolean. Designates that this user has all permissions without
- explicitly assigning them.
- .. attribute:: models.User.last_login
- A datetime of the user's last login. Is set to the current date/time by
- default.
- .. attribute:: models.User.date_joined
- A datetime designating when the account was created. Is set to the
- current date/time by default when the account is created.
- Methods
- ~~~~~~~
- .. class:: models.User
- :class:`~django.contrib.auth.models.User` objects have two many-to-many
- fields: models.User. ``groups`` and ``user_permissions``.
- :class:`~django.contrib.auth.models.User` objects can access their related
- objects in the same way as any other :ref:`Django model
- <topics-db-models>`:
- .. code-block:: python
- myuser.groups = [group_list]
- myuser.groups.add(group, group, ...)
- myuser.groups.remove(group, group, ...)
- myuser.groups.clear()
- myuser.user_permissions = [permission_list]
- myuser.user_permissions.add(permission, permission, ...)
- myuser.user_permissions.remove(permission, permission, ...)
- myuser.user_permissions.clear()
- In addition to those automatic API methods,
- :class:`~django.contrib.auth.models.User` objects have the following custom
- methods:
- .. method:: models.User.is_anonymous()
- Always returns ``False``. This is a way of differentiating
- :class:`~django.contrib.auth.models.User` and
- :class:`~django.contrib.auth.models.AnonymousUser` objects.
- Generally, you should prefer using
- :meth:`~django.contrib.auth.models.User.is_authenticated()` to this
- method.
- .. method:: models.User.is_authenticated()
- Always returns ``True``. This is a way to tell if the user has been
- authenticated. This does not imply any permissions, and doesn't check
- if the user is active - it only indicates that the user has provided a
- valid username and password.
- .. method:: models.User.get_full_name()
- Returns the :attr:`~django.contrib.auth.models.User.first_name` plus
- the :attr:`~django.contrib.auth.models.User.last_name`, with a space in
- between.
- .. method:: models.User.set_password(raw_password)
- Sets the user's password to the given raw string, taking care of the
- password hashing. Doesn't save the
- :class:`~django.contrib.auth.models.User` object.
- .. method:: models.User.check_password(raw_password)
- Returns ``True`` if the given raw string is the correct password for
- the user. (This takes care of the password hashing in making the
- comparison.)
- .. method:: models.User.set_unusable_password()
- .. versionadded:: 1.0
- Marks the user as having no password set. This isn't the same as
- having a blank string for a password.
- :meth:`~django.contrib.auth.models.User.check_password()` for this user
- will never return ``True``. Doesn't save the
- :class:`~django.contrib.auth.models.User` object.
- You may need this if authentication for your application takes place
- against an existing external source such as an LDAP directory.
- .. method:: models.User.has_usable_password()
- .. versionadded:: 1.0
- Returns ``False`` if
- :meth:`~django.contrib.auth.models.User.set_unusable_password()` has
- been called for this user.
- .. method:: models.User.get_group_permissions()
- Returns a list of permission strings that the user has, through his/her
- groups.
- .. method:: models.User.get_all_permissions()
- Returns a list of permission strings that the user has, both through
- group and user permissions.
- .. method:: models.User.has_perm(perm)
- Returns ``True`` if the user has the specified permission, where perm
- is in the format ``"package.codename"``. If the user is inactive, this
- method will always return ``False``.
- .. method:: models.User.has_perms(perm_list)
- Returns ``True`` if the user has each of the specified permissions,
- where each perm is in the format ``"package.codename"``. If the user is
- inactive, this method will always return ``False``.
- .. method:: models.User.has_module_perms(package_name)
- Returns ``True`` if the user has any permissions in the given package
- (the Django app label). If the user is inactive, this method will
- always return ``False``.
- .. method:: models.User.get_and_delete_messages()
- Returns a list of :class:`~django.contrib.auth.models.Message` objects
- in the user's queue and deletes the messages from the queue.
- .. method:: models.User.email_user(subject, message, from_email=None)
- Sends an e-mail to the user. If
- :attr:`~django.contrib.auth.models.User.from_email` is ``None``, Django
- uses the :setting:`DEFAULT_FROM_EMAIL`.
- .. method:: models.User.get_profile()
- Returns a site-specific profile for this user. Raises
- :exc:`django.contrib.auth.models.SiteProfileNotAvailable` if the
- current site doesn't allow profiles. For information on how to define a
- site-specific user profile, see the section on `storing additional user
- information`_ below.
- .. _storing additional user information: #storing-additional-information-about-users
- Manager functions
- ~~~~~~~~~~~~~~~~~
- .. class:: models.UserManager
- The :class:`~django.contrib.auth.models.User` model has a custom manager
- that has the following helper functions:
- .. method:: models.UserManager.create_user(username, email, password=None)
- Creates, saves and returns a :class:`~django.contrib.auth.models.User`.
- The :attr:`~django.contrib.auth.models.User.username`,
- :attr:`~django.contrib.auth.models.User.email` and
- :attr:`~django.contrib.auth.models.User.password` are set as given, and
- the :class:`~django.contrib.auth.models.User` gets ``is_active=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
- ~~~~~~~~~~~~~~~~~~
- Change a password with :meth:`~django.contrib.auth.models.User.set_password()`:
- .. code-block:: python
- >>> from django.contrib.auth.models import User
- >>> u = User.objects.get(username__exact='john')
- >>> u.set_password('new password')
- >>> u.save()
- Don't set the :attr:`~django.contrib.auth.models.User.password` attribute
- directly unless you know what you're doing. This is explained in the next
- section.
- Passwords
- ---------
- The :attr:`~django.contrib.auth.models.User.password` attribute of a
- :class:`~django.contrib.auth.models.User` object is a string in this format::
- hashtype$salt$hash
- That's hashtype, salt and hash, separated by the dollar-sign character.
- Hashtype is either ``sha1`` (default), ``md5`` or ``crypt`` -- the algorithm
- used to perform a one-way hash of the password. Salt is a random string used
- to salt the raw password to create the hash. Note that the ``crypt`` method is
- only supported on platforms that have the standard Python ``crypt`` module
- available.
- .. versionadded:: 1.0
- Support for the ``crypt`` module is new in Django 1.0.
- For example::
- sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4
- The :meth:`~django.contrib.auth.models.User.set_password` and
- :meth:`~django.contrib.auth.models.User.check_password` functions handle the
- setting and checking of these values behind the scenes.
- Previous Django versions, such as 0.90, used simple MD5 hashes without password
- salts. For backwards compatibility, those are still supported; they'll be
- converted automatically to the new style the first time
- :meth:`~django.contrib.auth.models.User.check_password()` works correctly for
- a given user.
- Anonymous users
- ---------------
- .. class:: models.AnonymousUser
- :class:`django.contrib.auth.models.AnonymousUser` is a class that
- implements the :class:`django.contrib.auth.models.User` interface, with
- these differences:
- * :attr:`~django.contrib.auth.models.User.id` is always ``None``.
- * :attr:`~django.contrib.auth.models.User.is_staff` and
- :attr:`~django.contrib.auth.models.User.is_superuser` are always
- ``False``.
- * :attr:`~django.contrib.auth.models.User.is_active` is always ``False``.
- * :attr:`~django.contrib.auth.models.User.groups` and
- :attr:`~django.contrib.auth.models.User.user_permissions` are always
- empty.
- * :meth:`~django.contrib.auth.models.User.is_anonymous()` returns ``True``
- instead of ``False``.
- * :meth:`~django.contrib.auth.models.User.is_authenticated()` returns
- ``False`` instead of ``True``.
- * :meth:`~django.contrib.auth.models.User.has_perm()` always returns
- ``False``.
- * :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.
- Creating superusers
- -------------------
- .. versionadded:: 1.0
- The ``manage.py createsuperuser`` command is new.
- :djadmin:`manage.py syncdb <syncdb>` prompts you to create a superuser the
- first time you run it after adding ``'django.contrib.auth'`` to your
- :setting:`INSTALLED_APPS`. If you need to create a superuser at a later date,
- you can use a command line utility::
- manage.py createsuperuser --username=joe --email=joe@example.com
- You will be prompted for a password. After you enter one, the user will be
- created immediately. If you leave off the :djadminopt:`--username` or the
- :djadminopt:`--email` options, it will prompt you for those values.
- If you're using an older release of Django, the old way of creating a superuser
- on the command line still works::
- python /path/to/django/contrib/auth/create_superuser.py
- ...where :file:`/path/to` is the path to the Django codebase on your
- filesystem. The ``manage.py`` command is preferred because it figures out the
- correct path and environment for you.
- .. _auth-profiles:
- Storing additional information about users
- ------------------------------------------
- If you'd like to store additional information related to your users, Django
- provides a method to specify a site-specific related model -- termed a "user
- profile" -- for this purpose.
- To make use of this feature, define a model with fields for the additional
- information you'd like to store, or additional methods you'd like to have
- available, and also add a :class:`~django.db.models.Field.ForeignKey` from your
- model to the :class:`~django.contrib.auth.models.User` model, specified with
- ``unique=True`` to ensure only one instance of your model can be created for
- each :class:`~django.contrib.auth.models.User`.
- To indicate that this model is the user profile model for a given site, fill in
- the setting :setting:`AUTH_PROFILE_MODULE` with a string consisting of the
- following items, separated by a dot:
- 1. The (normalized to lower-case) name of the application in which the user
- profile model is defined (in other words, an all-lowercase version of the
- name which was passed to :djadmin:`manage.py startapp <startapp>` to create
- the application).
- 2. The (normalized to lower-case) name of the model 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`.
- For more information, see `Chapter 12 of the Django book`_.
- .. _Chapter 12 of the Django book: http://www.djangobook.com/en/1.0/chapter12/#cn222
- Authentication in Web requests
- ==============================
- Until now, this document has dealt with the low-level APIs for manipulating
- authentication-related objects. On a higher level, Django can hook this
- authentication framework into its system of
- :class:`request objects <django.http.HttpRequest>`.
- First, install the
- :class:`~django.contrib.sessions.middleware.SessionMiddleware` and
- :class:`~django.contrib.auth.middleware.AuthenticationMiddleware`
- middlewares by adding them to your :setting:`MIDDLEWARE_CLASSES` setting. See
- the :ref:`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.
- .. _howtologauserin:
- How to log a user in
- --------------------
- Django provides two functions in :mod:`django.contrib.auth`:
- :func:`~django.contrib.auth.authenticate()` and
- :func:`~django.contrib.auth.login()`.
- .. function:: authenticate()
- To authenticate a given username and password, use
- :func:`~django.contrib.auth.authenticate()`. It takes two keyword
- arguments, ``username`` and ``password``, and it returns a
- :class:`~django.contrib.auth.models.User` object if the password is valid
- for the given username. If the password is invalid,
- :func:`~django.contrib.auth.authenticate()` returns ``None``. Example::
- from django.contrib.auth import authenticate
- user = authenticate(username='john', password='secret')
- if user is not None:
- if user.is_active:
- print "You provided a correct username and password!"
- else:
- print "Your account has been disabled!"
- else:
- print "Your username and password were incorrect."
- .. function:: login()
- To log a user in, in a view, use :func:`~django.contrib.auth.login()`. It
- takes an :class:`~django.http.HttpRequest` object and a
- :class:`~django.contrib.auth.models.User` object.
- :func:`~django.contrib.auth.login()` saves the user's ID in the session,
- using Django's session framework, so, as mentioned above, you'll need to
- make sure to have the session middleware installed.
- This example shows how you might use both
- :func:`~django.contrib.auth.authenticate()` and
- :func:`~django.contrib.auth.login()`::
- from django.contrib.auth import authenticate, login
- def my_view(request):
- username = request.POST['username']
- password = request.POST['password']
- user = authenticate(username=username, password=password)
- if user is not None:
- if user.is_active:
- login(request, user)
- # Redirect to a success page.
- else:
- # Return a 'disabled account' error message
- else:
- # Return an 'invalid login' error message.
- .. admonition:: Calling ``authenticate()`` first
- When you're manually logging a user in, you *must* call
- :func:`~django.contrib.auth.authenticate()` before you call
- :func:`~django.contrib.auth.login()`.
- :func:`~django.contrib.auth.authenticate()`
- sets an attribute on the :class:`~django.contrib.auth.models.User` noting
- which authentication backend successfully authenticated that user (see the
- `backends documentation`_ for details), and this information is needed
- later during the login process.
- .. _backends documentation: #other-authentication-sources
- Manually checking a user's password
- -----------------------------------
- .. function:: check_password()
- If you'd like to manually authenticate a user by comparing a plain-text
- password to the hashed password in the database, use the convenience
- function :func:`django.contrib.auth.models.check_password`. It takes two
- arguments: the plain-text password to check, and the full value of a user's
- ``password`` field in the database to check against, and returns ``True``
- if they match, ``False`` otherwise.
- How to log a user out
- ---------------------
- .. function:: logout()
- To log out a user who has been logged in via
- :func:`django.contrib.auth.login()`, use
- :func:`django.contrib.auth.logout()` within your view. It takes an
- :class:`~django.http.HttpRequest` object and has no return value.
- Example::
- from django.contrib.auth import logout
- def logout_view(request):
- logout(request)
- # Redirect to a success page.
- Note that :func:`~django.contrib.auth.logout()` doesn't throw any errors if
- the user wasn't logged in.
- .. versionchanged:: 1.0
- Calling ``logout()`` now cleans session data.
- When you call :func:`~django.contrib.auth.logout()`, the session data for
- the current request is completely cleaned out. All existing data is
- removed. This is to prevent another person from using the same web browser
- to log in and have access to the previous user's session data. If you want
- to put anything into the session that will be available to the user
- immediately after logging out, do that *after* calling
- :func:`django.contrib.auth.logout()`.
- Limiting access to logged-in users
- ----------------------------------
- The raw way
- ~~~~~~~~~~~
- The simple, raw way to limit access to pages is to check
- :meth:`request.user.is_authenticated()
- <django.contrib.auth.models.User.is_authenticated()>` and either redirect to a
- login page::
- from django.http import HttpResponseRedirect
- def my_view(request):
- if not request.user.is_authenticated():
- return HttpResponseRedirect('/login/?next=%s' % request.path)
- # ...
- ...or display an error message::
- def my_view(request):
- if not request.user.is_authenticated():
- return render_to_response('myapp/login_error.html')
- # ...
- The login_required decorator
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- .. function:: decorators.login_required()
- As a shortcut, you can use the convenient
- :func:`~django.contrib.auth.decorators.login_required` decorator::
- from django.contrib.auth.decorators import login_required
- def my_view(request):
- # ...
- my_view = login_required(my_view)
- Here's an equivalent example, using the more compact decorator syntax
- introduced in Python 2.4::
- from django.contrib.auth.decorators import login_required
- @login_required
- def my_view(request):
- # ...
- :func:`~django.contrib.auth.decorators.login_required` also takes an
- optional ``redirect_field_name`` parameter. Example::
- from django.contrib.auth.decorators import login_required
- def my_view(request):
- # ...
- my_view = login_required(redirect_field_name='redirect_to')(my_view)
- Again, an equivalent example of the more compact decorator syntax
- introduced in Python 2.4::
- from django.contrib.auth.decorators import login_required
- @login_required(redirect_field_name='redirect_to')
- 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>` (``/accounts/login/`` by
- default), passing the current absolute URL in the query string as
- ``next`` or the value of ``redirect_field_name``. For 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.
- Note that you'll need to map the appropriate Django view to
- :setting:`settings.LOGIN_URL <LOGIN_URL>`. For example, using the defaults, add
- the following line to your URLconf::
- (r'^accounts/login/$', 'django.contrib.auth.views.login'),
- .. function:: views.login()
- 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 three
- template context variables:
- * ``form``: A :class:`~django.forms.Form` object representing the login
- form. See the :ref:`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_name``: The name of the current
- :class:`~django.contrib.sites.models.Site`, according to the
- :setting:`SITE_ID` setting. If you're using the Django development
- version and 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
- :ref:`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'}),
- 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
- {% extends "base.html" %}
- {% block content %}
- {% if form.errors %}
- <p>Your username and password didn't match. Please try again.</p>
- {% endif %}
- <form method="post" action=".">
- <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 %}
- .. _forms documentation: ../forms/
- .. _site framework docs: ../sites/
- Other built-in views
- --------------------
- In addition to the :func:`~views.login` view, the authentication system
- includes a few other useful built-in views located in
- :mod:`django.contrib.auth.views`:
- .. function:: views.logout(request, [next_page, template_name])
- Logs a user out.
- **Optional arguments:**
- * ``next_page``: The URL to redirect to after logout.
- * ``template_name``: The full name of a template to display after
- logging the user out. This will default to
- :file:`registration/logged_out.html` if no argument is supplied.
- **Template context:**
- * ``title``: The string "Logged out", localized.
- .. function:: views.logout_then_login(request[, login_url])
- Logs a user out, then redirects to the login page.
- **Optional arguments:**
- * ``login_url``: The URL of the login page to redirect to. This will
- default to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied.
- .. function:: views.password_change(request[, template_name, post_change_redirect])
- Allows a user to change their password.
- **Optional arguments:**
- * ``template_name``: The full name of a template to use for
- displaying the password change form. This will default to
- :file:`registration/password_change_form.html` if not supplied.
- * ``post_change_redirect``: The URL to redirect to after successful
- password change.
- **Template context:**
- * ``form``: The password change form.
- .. function:: views.password_change_done(request[, template_name])
- The page shown after a user has changed their password.
- **Optional arguments:**
- * ``template_name``: The full name of a template to use. This will
- default to :file:`registration/password_change_done.html` if not
- supplied.
- .. function:: views.password_reset
- Allows a user to reset their password, and sends them the new password
- in an e-mail.
- **Optional arguments:**
- * ``template_name``: The full name of a template to use for
- displaying the password reset form. This will default to
- :file:`registration/password_reset_form.html` if not supplied.
- * ``email_template_name``: The full name of a template to use for
- generating the e-mail with the new password. This will default to
- :file:`registration/password_reset_email.html` if not supplied.
- **Template context:**
- * ``form``: The form for resetting the user's password.
- .. function:: views.password_reset_done
- The page shown after a user has reset their password.
- **Optional arguments:**
- * ``template_name``: The full name of a template to use. This will
- default to :file:`registration/password_reset_done.html` if not
- supplied.
- .. function:: views.redirect_to_login
- Redirects to the login page, and then back to another URL after a
- successful login.
- **Required arguments:**
- * ``next``: The URL to redirect to after a successful login.
- **Optional arguments:**
- * ``login_url``: The URL of the login page to redirect to. This will
- default to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied.
- 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 resetting a user's password and e-mailing the new password to
- them.
- .. class:: UserCreationForm
- A form for creating a new user.
- Limiting access to logged-in users that pass a test
- ---------------------------------------------------
- .. currentmodule:: django.contrib.auth
- To limit access based on certain permissions or some other test, you'd do
- essentially the same thing as described in the previous section.
- The simple way is to run your test on :attr:`request.user
- <django.http.HttpRequest.user>` in the view directly. For example, this view
- checks to make sure the user is logged in and has the permission
- ``polls.can_vote``::
- def my_view(request):
- if not (request.user.is_authenticated() and request.user.has_perm('polls.can_vote')):
- return HttpResponse("You can't vote in this poll.")
- # ...
- .. function:: decorators.user_passes_test()
- As a shortcut, you can use the convenient ``user_passes_test`` decorator::
- from django.contrib.auth.decorators import user_passes_test
- def my_view(request):
- # ...
- my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'))(my_view)
- 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.
- Here's the same thing, using Python 2.4's decorator syntax::
- from django.contrib.auth.decorators import user_passes_test
- @user_passes_test(lambda u: u.has_perm('polls.can_vote'))
- def my_view(request):
- # ...
- :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).
- Example in Python 2.3 syntax::
- from django.contrib.auth.decorators import user_passes_test
- def my_view(request):
- # ...
- my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')(my_view)
- Example in Python 2.4 syntax::
- from django.contrib.auth.decorators import user_passes_test
- @user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')
- def my_view(request):
- # ...
- The permission_required decorator
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- .. function:: decorators.permission_required()
- It's a relatively common task to check whether a user has a particular
- permission. For that reason, Django provides a shortcut for that case: the
- :func:`~django.contrib.auth.decorators.permission_required()` decorator.
- Using this decorator, the earlier example can be written as::
- from django.contrib.auth.decorators import permission_required
- def my_view(request):
- # ...
- my_view = permission_required('polls.can_vote')(my_view)
- 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
- def my_view(request):
- # ...
- my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view)
- As in the :func:`~decorators.login_required` decorator, ``login_url``
- defaults to :setting:`settings.LOGIN_URL <LOGIN_URL>`.
- Limiting access to generic views
- --------------------------------
- To limit access to a :ref:`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
- ===========
- Django comes with a simple permissions system. It provides a way to assign
- permissions to specific users and groups of users.
- It's used by the Django admin site, but you're welcome to use it in your own
- code.
- The Django admin site uses permissions as follows:
- * Access to view the "add" form and add an object is limited to users with
- the "add" permission for that type of object.
- * Access to view the change list, view the "change" form and change an
- object is limited to users with the "change" permission for that type of
- object.
- * Access to delete an object is limited to users with the "delete"
- permission for that type of object.
- Permissions are set globally per type of object, not per specific object
- instance. For example, it's possible to say "Mary may change news stories," but
- it's not currently possible to say "Mary may change news stories, but only the
- ones she created herself" or "Mary may only change news stories that have a
- certain status, publication date or ID." The latter functionality is something
- Django developers are currently discussing.
- Default permissions
- -------------------
- When ``django.contrib.auth`` is listed in your :setting:`INSTALLED_APPS`
- setting, it will ensure that three default permissions -- add, change and
- delete -- are created for each Django model defined in one of your installed
- applications.
- These permissions will be created when you run :djadmin:`manage.py syncdb
- <syncdb>`; the first time you run ``syncdb`` after adding
- ``django.contrib.auth`` to :setting:`INSTALLED_APPS`, the default permissions
- will be created for all previously-installed models, as well as for any new
- models being installed at that time. Afterward, it will create default
- permissions for new models each time you run :djadmin:`manage.py syncdb
- <syncdb>`.
- .. _custom-permissions:
- Custom permissions
- ------------------
- To create custom permissions for a given model object, use the ``permissions``
- :ref:`model Meta attribute <meta-options>`.
- This example model creates three custom permissions::
- class USCitizen(models.Model):
- # ...
- class Meta:
- permissions = (
- ("can_drive", "Can drive"),
- ("can_vote", "Can vote in elections"),
- ("can_drink", "Can drink alcohol"),
- )
- The only thing this does is create those extra permissions when you run
- :djadmin:`manage.py syncdb <syncdb>`.
- API reference
- -------------
- .. class:: models.Permission
- Just like users, permissions are implemented in a Django model that lives
- in `django/contrib/auth/models.py`_.
- .. _django/contrib/auth/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py
- Fields
- ~~~~~~
- :class:`~django.contrib.auth.models.Permission` objects have the following
- fields:
- .. attribute:: models.Permission.name
- Required. 50 characters or fewer. Example: ``'Can vote'``.
- .. attribute:: models.Permission.content_type
- Required. A reference to the ``django_content_type`` database table, which
- contains a record for each installed Django model.
- .. attribute:: models.Permission.codename
- Required. 100 characters or fewer. Example: ``'can_vote'``.
- Methods
- ~~~~~~~
- :class:`~django.contrib.auth.models.Permission` objects have the standard
- data-access methods like any other :ref:`Django model <ref-models-instances>`.
- Authentication data in templates
- ================================
- The currently logged-in user and his/her permissions are made available in the
- :ref:`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.core.context_processors.auth"``, which is default. For more, see
- the :ref:`RequestContext docs <subclassing-context-requestcontext>`.
- Users
- -----
- 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
- {% if user.is_authenticated %}
- <p>Welcome, {{ user.username }}. Thanks for logging in.</p>
- {% else %}
- <p>Welcome, new user. Please log in.</p>
- {% endif %}
- Permissions
- -----------
- The currently logged-in user's permissions are stored in the template variable
- ``{{ perms }}``. This is an instance of
- :class:`django.core.context_processors.PermWrapper`, which is a
- template-friendly proxy of permissions.
- In the ``{{ perms }}`` object, single-attribute lookup is a proxy to
- :meth:`User.has_module_perms <django.contrib.auth.models.User.has_module_perms>`.
- This example would display ``True`` if the logged-in user had any permissions
- in the ``foo`` app::
- {{ perms.foo }}
- Two-level-attribute lookup is a proxy to
- :meth:`User.has_perm <django.contrib.auth.models.User.has_perm>`. This example
- would display ``True`` if the logged-in user had the permission
- ``foo.can_vote``::
- {{ perms.foo.can_vote }}
- Thus, you can check permissions in template ``{% if %}`` statements:
- .. code-block:: html
- {% if perms.foo %}
- <p>You have permission to do something in the foo app.</p>
- {% if perms.foo.can_vote %}
- <p>You can vote!</p>
- {% endif %}
- {% if perms.foo.can_drive %}
- <p>You can drive!</p>
- {% endif %}
- {% else %}
- <p>You don't have permission to do anything in the foo app.</p>
- {% endif %}
- Groups
- ======
- Groups are a generic way of categorizing users so you can apply permissions, or
- some other label, to those users. A user can belong to any number of groups.
- A user in a group automatically has the permissions granted to that group. For
- example, if the group ``Site editors`` has the permission
- ``can_edit_home_page``, any user in that group will have that permission.
- Beyond permissions, groups are a convenient way to categorize users to give
- them some label, or extended functionality. For example, you could create a
- group ``'Special users'``, and you could write code that could, say, give them
- access to a members-only portion of your site, or send them members-only e-mail
- messages.
- Messages
- ========
- The message system is a lightweight way to queue messages for given users.
- A message is associated with a :class:`~django.contrib.auth.models.User`.
- There's no concept of expiration or timestamps.
- Messages are used by the Django admin after successful actions. For example,
- ``"The poll Foo was created successfully."`` is a message.
- The API is simple:
- .. method:: models.User.message_set.create(message)
- To create a new message, use
- ``user_obj.message_set.create(message='message_text')``.
- To retrieve/delete messages, use
- :meth:`user_obj.get_and_delete_messages() <django.contrib.auth.models.User.get_and_delete_messages>`,
- which returns a list of ``Message`` objects in the user's queue (if any)
- and deletes the messages from the queue.
- In this example view, the system saves a message for the user after creating
- a playlist::
- def create_playlist(request, songs):
- # Create the playlist with the given songs.
- # ...
- request.user.message_set.create(message="Your playlist was added successfully.")
- return render_to_response("playlists/create.html",
- context_instance=RequestContext(request))
- When you use :class:`~django.template.context.RequestContext`, the currently
- logged-in user and his/her messages are made available in the
- :ref:`template context <ref-templates-api>` as the template variable
- ``{{ messages }}``. Here's an example of template code that displays messages:
- .. code-block:: html
- {% if messages %}
- <ul>
- {% for message in messages %}
- <li>{{ message }}</li>
- {% endfor %}
- </ul>
- {% endif %}
- Note that :class:`~django.template.context.RequestContext` calls
- :meth:`~django.contrib.auth.models.User.get_and_delete_messages` behind the
- scenes, so any messages will be deleted even if you don't display them.
- Finally, note that this messages framework only works with users in the user
- database. To send messages to anonymous users, use the
- :ref:`session framework <topics-http-sessions>`.
- .. _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 :ref:`authentication backend reference <ref-authentication-backends>`
- for information on the authentication backends included with Django.
- Specifying authentication backends
- ----------------------------------
- Behind the scenes, Django maintains a list of "authentication backends" that it
- checks for authentication. When somebody calls
- :func:`django.contrib.auth.authenticate()` -- as described in :ref:`How to log
- a user in` above -- Django tries authenticating across all of its
- authentication backends. If the first authentication method fails, Django tries
- the second one, and so on, until all backends have been attempted.
- The list of authentication backends to use is specified in the
- :setting:`AUTHENTICATION_BACKENDS` setting. This should be a tuple of Python
- path names that point to Python classes that know how to authenticate. These
- classes can be anywhere on your Python path.
- By default, :setting:`AUTHENTICATION_BACKENDS` is set to::
- ('django.contrib.auth.backends.ModelBackend',)
- That's the basic authentication scheme that checks the Django users database.
- The order of :setting:`AUTHENTICATION_BACKENDS` matters, so if the same
- username and password is valid in multiple backends, Django will stop
- processing at the first positive match.
- Writing an authentication backend
- ---------------------------------
- An authentication backend is a class that implements two methods:
- ``get_user(user_id)`` and ``authenticate(**credentials)``.
- The ``get_user`` method takes a ``user_id`` -- which could be a username,
- database ID or whatever -- and returns a ``User`` object.
- The ``authenticate`` method takes credentials as keyword arguments. Most of
- the time, it'll just look like this::
- class MyBackend:
- def authenticate(self, username=None, password=None):
- # Check the username/password and return a User.
- But it could also authenticate a token, like so::
- class MyBackend:
- def authenticate(self, token=None):
- # Check the token and return a User.
- Either way, ``authenticate`` should check the credentials it gets, and it
- should return a ``User`` object that matches those credentials, if the
- credentials are valid. If they're not valid, it should return ``None``.
- The Django admin system is tightly coupled to the Django ``User`` object
- described at the beginning of this document. For now, the best way to deal with
- this is to create a Django ``User`` object for each user that exists for your
- backend (e.g., in your LDAP directory, your external SQL database, etc.) You
- can either write a script to do this in advance, or your ``authenticate``
- method can do it the first time a user logs in.
- Here's an example backend that authenticates against a username and password
- variable defined in your ``settings.py`` file and creates a Django ``User``
- object the first time a user authenticates::
- from django.conf import settings
- from django.contrib.auth.models import User, check_password
- class SettingsBackend:
- """
- Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.
- Use the login name, and a hash of the password. For example:
- ADMIN_LOGIN = 'admin'
- ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de'
- """
- def authenticate(self, username=None, password=None):
- login_valid = (settings.ADMIN_LOGIN == username)
- pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
- if login_valid and pwd_valid:
- try:
- user = User.objects.get(username=username)
- except User.DoesNotExist:
- # Create a new user. Note that we can set password
- # to anything, because it won't be checked; the password
- # from settings.py will.
- user = User(username=username, password='get from settings.py')
- user.is_staff = True
- user.is_superuser = True
- user.save()
- return user
- return None
- def get_user(self, user_id):
- try:
- return User.objects.get(pk=user_id)
- except User.DoesNotExist:
- return None
- Handling authorization in custom backends
- -----------------------------------------
- Custom auth backends can provide their own permissions.
- The user model will delegate permission lookup functions
- (:meth:`~django.contrib.auth.models.User.get_group_permissions()`,
- :meth:`~django.contrib.auth.models.User.get_all_permissions()`,
- :meth:`~django.contrib.auth.models.User.has_perm()`, and
- :meth:`~django.contrib.auth.models.User.has_module_perms()`) to any
- authentication backend that implements these functions.
- The permissions given to the user will be the superset of all permissions
- returned by all backends. That is, Django grants a permission to a user that
- any one backend grants.
- The simple backend above could implement permissions for the magic admin
- fairly simply::
- class SettingsBackend:
- # ...
- def has_perm(self, user_obj, perm):
- if user_obj.username == settings.ADMIN_LOGIN:
- return True
- else:
- return False
- This gives full permissions to the user granted access in the above example.
- Notice that the backend auth functions all take the user object as an argument,
- and they also accept the same arguments given to the associated
- :class:`django.contrib.auth.models.User` functions.
- A full authorization implementation can be found in
- `django/contrib/auth/backends.py`_, which is the default backend and queries
- the ``auth_permission`` table most of the time.
- .. _django/contrib/auth/backends.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py
|