1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213 |
- ====================================
- Customizing authentication in Django
- ====================================
- The authentication that comes with Django is good enough for most common cases,
- but you may have needs not met by the out-of-the-box defaults. Customizing
- authentication in your projects requires understanding what points of the
- provided system are extensible or replaceable. This document provides details
- about how the auth system can be customized.
- :ref:`Authentication backends <authentication-backends>` provide an extensible
- system for when a username and password stored with the user model need to be
- authenticated against a different service than Django's default.
- You can give your models :ref:`custom permissions <custom-permissions>` that
- can be checked through Django's authorization system.
- You can :ref:`extend <extending-user>` the default ``User`` model, or
- :ref:`substitute <auth-custom-user>` a completely customized model.
- .. _authentication-backends:
- Other authentication sources
- ============================
- There may be times you 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
- <authentication-backends-reference>` for information on the authentication
- backends included with Django.
- Specifying authentication backends
- ----------------------------------
- Behind the scenes, Django maintains a list of "authentication backends" that it
- checks for authentication. When somebody calls
- :func:`django.contrib.auth.authenticate()` -- as described in :ref:`How to log
- a user in <how-to-log-a-user-in>` -- 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 list 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 built-in 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.
- If a backend raises a :class:`~django.core.exceptions.PermissionDenied`
- exception, authentication will immediately fail. Django won't check the
- backends that follow.
- .. note::
- Once a user has authenticated, Django stores which backend was used to
- authenticate the user in the user's session, and reuses 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 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(request, **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, but has to be the primary key of your user object --
- and returns a user object or ``None``.
- The ``authenticate`` method takes a ``request`` argument and credentials as
- keyword arguments. Most of the time, it'll look like this::
- from django.contrib.auth.backends import BaseBackend
- class MyBackend(BaseBackend):
- def authenticate(self, request, username=None, password=None):
- # Check the username/password and return a user.
- ...
- But it could also authenticate a token, like so::
- from django.contrib.auth.backends import BaseBackend
- class MyBackend(BaseBackend):
- def authenticate(self, request, token=None):
- # Check the token and return a user.
- ...
- Either way, ``authenticate()`` should check the credentials it gets and return
- a user object that matches those credentials if the credentials are valid. If
- they're not valid, it should return ``None``.
- ``request`` is an :class:`~django.http.HttpRequest` and may be ``None`` if it
- wasn't provided to :func:`~django.contrib.auth.authenticate` (which passes it
- on to the backend).
- The Django admin is tightly coupled to the Django :ref:`User object
- <user-objects>`. 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.backends import BaseBackend
- from django.contrib.auth.hashers import check_password
- from django.contrib.auth.models import User
- class SettingsBackend(BaseBackend):
- """
- 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 = 'pbkdf2_sha256$30000$Vo0VlMnkR4Bk$qEvtdyZRWTcOsCnI/oQ7fVOu1XAURIZYoOZ3iq8Dr4M='
- """
- def authenticate(self, request, 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. There's no need to set a password
- # because only the password from settings.py is checked.
- user = User(username=username)
- 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 and its manager will delegate permission lookup functions
- (:meth:`~django.contrib.auth.models.User.get_user_permissions()`,
- :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()`,
- :meth:`~django.contrib.auth.models.User.has_module_perms()`, and
- :meth:`~django.contrib.auth.models.UserManager.with_perm()`) 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.
- If a backend raises a :class:`~django.core.exceptions.PermissionDenied`
- exception in :meth:`~django.contrib.auth.models.User.has_perm()` or
- :meth:`~django.contrib.auth.models.User.has_module_perms()`, the authorization
- will immediately fail and Django won't check the backends that follow.
- A backend could implement permissions for the magic admin like this::
- from django.contrib.auth.backends import BaseBackend
- class MagicAdminBackend(BaseBackend):
- def has_perm(self, user_obj, perm, obj=None):
- return user_obj.username == settings.ADMIN_LOGIN
- 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 :source:`django/contrib/auth/backends.py`, which is the default backend and
- queries the ``auth_permission`` table most of the time.
- .. _anonymous_auth:
- Authorization for anonymous users
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 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 websites
- 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 reusable 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
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- An inactive user is one that has its
- :attr:`~django.contrib.auth.models.User.is_active` field set to ``False``. The
- :class:`~django.contrib.auth.backends.ModelBackend` and
- :class:`~django.contrib.auth.backends.RemoteUserBackend` authentication
- backends prohibits these users from authenticating. If a custom user model
- doesn't have an :attr:`~django.contrib.auth.models.CustomUser.is_active` field,
- all users will be allowed to authenticate.
- You can use :class:`~django.contrib.auth.backends.AllowAllUsersModelBackend`
- or :class:`~django.contrib.auth.backends.AllowAllUsersRemoteUserBackend` if you
- want to allow inactive users to authenticate.
- 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.
- Do not forget to test for the ``is_active`` attribute of the user in your own
- backend permission 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.
- .. _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 two custom permissions, i.e., actions users
- can or cannot do with ``Task`` instances, specific to your application::
- class Task(models.Model):
- ...
- class Meta:
- permissions = [
- ("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 migrate <migrate>` (the function that creates permissions
- is connected to the :data:`~django.db.models.signals.post_migrate` signal).
- Your code is in charge of checking the value of these permissions when a user
- is trying to access the functionality provided by the application (changing the
- status of tasks or closing tasks.) Continuing the above example, the following
- checks if a user may close tasks::
- user.has_perm("app.close_task")
- .. _extending-user:
- Extending the existing ``User`` model
- =====================================
- There are two ways to extend the default
- :class:`~django.contrib.auth.models.User` model without substituting your own
- model. If the changes you need are purely behavioral, and don't require any
- change to what is stored in the database, you can create a :ref:`proxy model
- <proxy-models>` based on :class:`~django.contrib.auth.models.User`. This
- allows for any of the features offered by proxy models including default
- ordering, custom managers, or custom model methods.
- If you wish to store information related to ``User``, you can use a
- :class:`~django.db.models.OneToOneField` to a model containing the fields for
- additional information. This one-to-one model is often called a profile model,
- as it might store non-auth related information about a site user. For example
- you might create an Employee model::
- from django.contrib.auth.models import User
- class Employee(models.Model):
- user = models.OneToOneField(User, on_delete=models.CASCADE)
- department = models.CharField(max_length=100)
- Assuming an existing Employee Fred Smith who has both a User and Employee
- model, you can access the related information using Django's standard related
- model conventions:
- .. code-block:: pycon
- >>> u = User.objects.get(username="fsmith")
- >>> freds_department = u.employee.department
- To add a profile model's 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 as BaseUserAdmin
- from django.contrib.auth.models import User
- from my_user_profile_app.models import Employee
- # Define an inline admin descriptor for Employee model
- # which acts a bit like a singleton
- class EmployeeInline(admin.StackedInline):
- model = Employee
- can_delete = False
- verbose_name_plural = "employee"
- # Define a new User admin
- class UserAdmin(BaseUserAdmin):
- inlines = [EmployeeInline]
- # Re-register UserAdmin
- admin.site.unregister(User)
- admin.site.register(User, UserAdmin)
- These profile models are not special in any way - they are just Django models
- that happen to have a one-to-one link with a user model. As such, they aren't
- auto created when a user is created, but
- a :attr:`django.db.models.signals.post_save` could be used to create or update
- related models as appropriate.
- Using related models results in additional queries or joins to retrieve the
- related data. Depending on your needs, a custom user model that includes the
- related fields may be your better option, however, existing relations to the
- default user model within your project's apps may justify the extra database
- load.
- .. _auth-custom-user:
- Substituting a custom ``User`` model
- ====================================
- Some kinds of projects may have authentication requirements for which Django's
- built-in :class:`~django.contrib.auth.models.User` model is not always
- appropriate. For instance, on some sites it makes more sense to use an email
- address as your identification token instead of a username.
- Django allows you to override the default user model by providing a value for
- the :setting:`AUTH_USER_MODEL` setting that references a custom model::
- AUTH_USER_MODEL = "myapp.MyUser"
- This dotted pair describes the :attr:`~django.apps.AppConfig.label` of the
- Django app (which must be in your :setting:`INSTALLED_APPS`), and the name of
- the Django model that you wish to use as your user model.
- Using a custom user model when starting a project
- -------------------------------------------------
- If you're starting a new project, it's highly recommended to set up a custom
- user model, even if the default :class:`~django.contrib.auth.models.User` model
- is sufficient for you. This model behaves identically to the default user
- model, but you'll be able to customize it in the future if the need arises::
- from django.contrib.auth.models import AbstractUser
- class User(AbstractUser):
- pass
- Don't forget to point :setting:`AUTH_USER_MODEL` to it. Do this before creating
- any migrations or running ``manage.py migrate`` for the first time.
- Also, register the model in the app's ``admin.py``::
- from django.contrib import admin
- from django.contrib.auth.admin import UserAdmin
- from .models import User
- admin.site.register(User, UserAdmin)
- Changing to a custom user model mid-project
- -------------------------------------------
- Changing :setting:`AUTH_USER_MODEL` after you've created database tables is
- significantly more difficult since it affects foreign keys and many-to-many
- relationships, for example.
- This change can't be done automatically and requires manually fixing your
- schema, moving your data from the old user table, and possibly manually
- reapplying some migrations. See :ticket:`25313` for an outline of the steps.
- Due to limitations of Django's dynamic dependency feature for swappable
- models, the model referenced by :setting:`AUTH_USER_MODEL` must be created in
- the first migration of its app (usually called ``0001_initial``); otherwise,
- you'll have dependency issues.
- In addition, you may run into a ``CircularDependencyError`` when running your
- migrations as Django won't be able to automatically break the dependency loop
- due to the dynamic dependency. If you see this error, you should break the loop
- by moving the models depended on by your user model into a second migration.
- (You can try making two normal models that have a ``ForeignKey`` to each other
- and seeing how ``makemigrations`` resolves that circular dependency if you want
- to see how it's usually done.)
- Reusable apps and ``AUTH_USER_MODEL``
- -------------------------------------
- Reusable apps shouldn't implement a custom user model. A project may use many
- apps, and two reusable apps that implemented a custom user model couldn't be
- used together. If you need to store per user information in your app, use
- a :class:`~django.db.models.ForeignKey` or
- :class:`~django.db.models.OneToOneField` to ``settings.AUTH_USER_MODEL``
- as described below.
- Referencing the ``User`` model
- ------------------------------
- .. currentmodule:: django.contrib.auth
- If you reference :class:`~django.contrib.auth.models.User` directly (for
- example, by referring to it in a foreign key), your code will not work in
- projects where the :setting:`AUTH_USER_MODEL` setting has been changed to a
- different user model.
- .. function:: get_user_model()
- Instead of referring to :class:`~django.contrib.auth.models.User` directly,
- you should reference the user model using
- ``django.contrib.auth.get_user_model()``. This method will return the
- currently active user model -- the custom user model if one is specified, or
- :class:`~django.contrib.auth.models.User` otherwise.
- When you define a foreign key or many-to-many relations to the user model,
- you should specify the custom model using the :setting:`AUTH_USER_MODEL`
- setting. For example::
- from django.conf import settings
- from django.db import models
- class Article(models.Model):
- author = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- )
- When connecting to signals sent by the user model, you should specify
- the custom model using the :setting:`AUTH_USER_MODEL` setting. For example::
- from django.conf import settings
- from django.db.models.signals import post_save
- def post_save_receiver(sender, instance, created, **kwargs):
- pass
- post_save.connect(post_save_receiver, sender=settings.AUTH_USER_MODEL)
- Generally speaking, it's easiest to refer to the user model with the
- :setting:`AUTH_USER_MODEL` setting in code that's executed at import time,
- however, it's also possible to call ``get_user_model()`` while Django
- is importing models, so you could use
- ``models.ForeignKey(get_user_model(), ...)``.
- If your app is tested with multiple user models, using
- ``@override_settings(AUTH_USER_MODEL=...)`` for example, and you cache the
- result of ``get_user_model()`` in a module-level variable, you may need to
- listen to the :data:`~django.test.signals.setting_changed` signal to clear
- the cache. For example::
- from django.apps import apps
- from django.contrib.auth import get_user_model
- from django.core.signals import setting_changed
- from django.dispatch import receiver
- @receiver(setting_changed)
- def user_model_swapped(*, setting, **kwargs):
- if setting == "AUTH_USER_MODEL":
- apps.clear_cache()
- from myapp import some_module
- some_module.UserModel = get_user_model()
- .. _specifying-custom-user-model:
- Specifying a custom user model
- ------------------------------
- When you start your project with a custom user model, stop to consider if this
- is the right choice for your project.
- Keeping all user related information in one model removes the need for
- additional or more complex database queries to retrieve related models. On the
- other hand, it may be more suitable to store app-specific user information in a
- model that has a relation with your custom user model. That allows each app to
- specify its own user data requirements without potentially conflicting or
- breaking assumptions by other apps. It also means that you would keep your user
- model as simple as possible, focused on authentication, and following the
- minimum requirements Django expects custom user models to meet.
- If you use the default authentication backend, then your model must have a
- single unique field that can be used for identification purposes. This can
- be a username, an email address, or any other unique attribute. A non-unique
- username field is allowed if you use a custom authentication backend that
- can support it.
- The easiest way to construct a compliant custom user model is to inherit from
- :class:`~django.contrib.auth.models.AbstractBaseUser`.
- :class:`~django.contrib.auth.models.AbstractBaseUser` provides the core
- implementation of a user model, including hashed passwords and tokenized
- password resets. You must then provide some key implementation details:
- .. currentmodule:: django.contrib.auth
- .. class:: models.CustomUser
- .. attribute:: USERNAME_FIELD
- A string describing the name of the field on the user model that is
- used as the unique identifier. This will usually be a username of some
- kind, but it can also be an email address, or any other unique
- identifier. The field *must* be unique (e.g. have ``unique=True`` set
- in its definition), unless you use a custom authentication backend that
- can support non-unique usernames.
- In the following example, the field ``identifier`` is used
- as the identifying field::
- class MyUser(AbstractBaseUser):
- identifier = models.CharField(max_length=40, unique=True)
- ...
- USERNAME_FIELD = "identifier"
- .. attribute:: EMAIL_FIELD
- A string describing the name of the email field on the ``User`` model.
- This value is returned by
- :meth:`~models.AbstractBaseUser.get_email_field_name`.
- .. attribute:: REQUIRED_FIELDS
- A list of the field names that will be prompted for when creating a
- user via the :djadmin:`createsuperuser` management command. The user
- will be prompted to supply a value for each of these fields. It must
- include any field for which :attr:`~django.db.models.Field.blank` is
- ``False`` or undefined and may include additional fields you want
- prompted for when a user is created interactively.
- ``REQUIRED_FIELDS`` has no effect in other parts of Django, like
- creating a user in the admin.
- For example, here is the partial definition for a user model that
- defines two required fields - a date of birth and height::
- class MyUser(AbstractBaseUser):
- ...
- date_of_birth = models.DateField()
- height = models.FloatField()
- ...
- REQUIRED_FIELDS = ["date_of_birth", "height"]
- .. note::
- ``REQUIRED_FIELDS`` must contain all required fields on your user
- model, but should *not* contain the ``USERNAME_FIELD`` or
- ``password`` as these fields will always be prompted for.
- .. attribute:: is_active
- A boolean attribute that indicates whether the user is considered
- "active". This attribute is provided as an attribute on
- ``AbstractBaseUser`` defaulting to ``True``. How you choose to
- implement it will depend on the details of your chosen auth backends.
- See the documentation of the :attr:`is_active attribute on the built-in
- user model <django.contrib.auth.models.User.is_active>` for details.
- .. method:: get_full_name()
- Optional. A longer formal identifier for the user such as their full
- name. If implemented, this appears alongside the username in an
- object's history in :mod:`django.contrib.admin`.
- .. method:: get_short_name()
- Optional. A short, informal identifier for the user such as their
- first name. If implemented, this replaces the username in the greeting
- to the user in the header of :mod:`django.contrib.admin`.
- .. admonition:: Importing ``AbstractBaseUser``
- ``AbstractBaseUser`` and ``BaseUserManager`` are importable from
- ``django.contrib.auth.base_user`` so that they can be imported without
- including ``django.contrib.auth`` in :setting:`INSTALLED_APPS`.
- The following attributes and methods are available on any subclass of
- :class:`~django.contrib.auth.models.AbstractBaseUser`:
- .. class:: models.AbstractBaseUser
- .. method:: get_username()
- Returns the value of the field nominated by ``USERNAME_FIELD``.
- .. method:: clean()
- Normalizes the username by calling :meth:`normalize_username`. If you
- override this method, be sure to call ``super()`` to retain the
- normalization.
- .. classmethod:: get_email_field_name()
- Returns the name of the email field specified by the
- :attr:`~models.CustomUser.EMAIL_FIELD` attribute. Defaults to
- ``'email'`` if ``EMAIL_FIELD`` isn't specified.
- .. classmethod:: normalize_username(username)
- Applies NFKC Unicode normalization to usernames so that visually
- identical characters with different Unicode code points are considered
- identical.
- .. attribute:: models.AbstractBaseUser.is_authenticated
- Read-only attribute which is always ``True`` (as opposed to
- ``AnonymousUser.is_authenticated`` which is always ``False``).
- 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 or has
- a valid session. Even though normally you will check this attribute on
- ``request.user`` to find out whether it has been populated by the
- :class:`~django.contrib.auth.middleware.AuthenticationMiddleware`
- (representing the currently logged-in user), you should know this
- attribute is ``True`` for any :class:`~models.User` instance.
- .. attribute:: models.AbstractBaseUser.is_anonymous
- Read-only attribute which is always ``False``. This is a way of
- differentiating :class:`~models.User` and :class:`~models.AnonymousUser`
- objects. Generally, you should prefer using
- :attr:`~models.User.is_authenticated` to this attribute.
- .. method:: models.AbstractBaseUser.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.AbstractBaseUser` object.
- When the raw_password is ``None``, the password will be set to an
- unusable password, as if
- :meth:`~django.contrib.auth.models.AbstractBaseUser.set_unusable_password()`
- were used.
- .. method:: models.AbstractBaseUser.check_password(raw_password)
- .. method:: models.AbstractBaseUser.acheck_password(raw_password)
- *Asynchronous version*: ``acheck_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.)
- .. versionchanged:: 5.0
- ``acheck_password()`` method was added.
- .. method:: models.AbstractBaseUser.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.AbstractBaseUser.check_password()` for this user
- will never return ``True``. Doesn't save the
- :class:`~django.contrib.auth.models.AbstractBaseUser` object.
- You may need this if authentication for your application takes place
- against an existing external source such as an LDAP directory.
- .. method:: models.AbstractBaseUser.has_usable_password()
- Returns ``False`` if
- :meth:`~django.contrib.auth.models.AbstractBaseUser.set_unusable_password()` has
- been called for this user.
- .. method:: models.AbstractBaseUser.get_session_auth_hash()
- Returns an HMAC of the password field. Used for
- :ref:`session-invalidation-on-password-change`.
- .. method:: models.AbstractBaseUser.get_session_auth_fallback_hash()
- .. versionadded:: 4.1.8
- Yields the HMAC of the password field using
- :setting:`SECRET_KEY_FALLBACKS`. Used by ``get_user()``.
- :class:`~models.AbstractUser` subclasses :class:`~models.AbstractBaseUser`:
- .. class:: models.AbstractUser
- .. method:: clean()
- Normalizes the email by calling
- :meth:`.BaseUserManager.normalize_email`. If you override this method,
- be sure to call ``super()`` to retain the normalization.
- Writing a manager for a custom user model
- -----------------------------------------
- You should also define a custom manager for your user model. If your user model
- defines ``username``, ``email``, ``is_staff``, ``is_active``, ``is_superuser``,
- ``last_login``, and ``date_joined`` fields the same as Django's default user,
- you can install Django's :class:`~django.contrib.auth.models.UserManager`;
- however, if your user model defines different fields, you'll need to define a
- custom manager that extends :class:`~django.contrib.auth.models.BaseUserManager`
- providing two additional methods:
- .. class:: models.CustomUserManager
- .. method:: models.CustomUserManager.create_user(username_field, password=None, **other_fields)
- The prototype of ``create_user()`` should accept the username field,
- plus all required fields as arguments. For example, if your user model
- uses ``email`` as the username field, and has ``date_of_birth`` as a
- required field, then ``create_user`` should be defined as::
- def create_user(self, email, date_of_birth, password=None):
- # create user here
- ...
- .. method:: models.CustomUserManager.create_superuser(username_field, password=None, **other_fields)
- The prototype of ``create_superuser()`` should accept the username
- field, plus all required fields as arguments. For example, if your user
- model uses ``email`` as the username field, and has ``date_of_birth``
- as a required field, then ``create_superuser`` should be defined as::
- def create_superuser(self, email, date_of_birth, password=None):
- # create superuser here
- ...
- For a :class:`~.ForeignKey` in :attr:`.USERNAME_FIELD` or
- :attr:`.REQUIRED_FIELDS`, these methods receive the value of the
- :attr:`~.ForeignKey.to_field` (the :attr:`~django.db.models.Field.primary_key`
- by default) of an existing instance.
- :class:`~django.contrib.auth.models.BaseUserManager` provides the following
- utility methods:
- .. class:: models.BaseUserManager
- .. classmethod:: models.BaseUserManager.normalize_email(email)
- Normalizes email addresses by lowercasing the domain portion of the
- email address.
- .. method:: models.BaseUserManager.get_by_natural_key(username)
- Retrieves a user instance using the contents of the field
- nominated by ``USERNAME_FIELD``.
- .. method:: models.BaseUserManager.make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')
- .. deprecated:: 4.2
- 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`` (lowercase letter o, uppercase letter o,
- and zero)
- Extending Django's default ``User``
- -----------------------------------
- If you're entirely happy with Django's :class:`~django.contrib.auth.models.User`
- model, but you want to add some additional profile information, you could
- subclass :class:`django.contrib.auth.models.AbstractUser` and add your custom
- profile fields, although we'd recommend a separate model as described in
- :ref:`specifying-custom-user-model`. ``AbstractUser`` provides the full
- implementation of the default :class:`~django.contrib.auth.models.User` as an
- :ref:`abstract model <abstract-base-classes>`.
- .. _custom-users-and-the-built-in-auth-forms:
- Custom users and the built-in auth forms
- ----------------------------------------
- Django's built-in :ref:`forms <built-in-auth-forms>` and :ref:`views
- <built-in-auth-views>` make certain assumptions about the user model that they
- are working with.
- The following forms are compatible with any subclass of
- :class:`~django.contrib.auth.models.AbstractBaseUser`:
- * :class:`~django.contrib.auth.forms.AuthenticationForm`: Uses the username
- field specified by :attr:`~models.CustomUser.USERNAME_FIELD`.
- * :class:`~django.contrib.auth.forms.SetPasswordForm`
- * :class:`~django.contrib.auth.forms.PasswordChangeForm`
- * :class:`~django.contrib.auth.forms.AdminPasswordChangeForm`
- The following forms make assumptions about the user model and can be used as-is
- if those assumptions are met:
- * :class:`~django.contrib.auth.forms.PasswordResetForm`: Assumes that the user
- model has a field that stores the user's email address with the name returned
- by :meth:`~models.AbstractBaseUser.get_email_field_name` (``email`` by
- default) that can be used to identify the user and a boolean field named
- ``is_active`` to prevent password resets for inactive users.
- Finally, the following forms are tied to
- :class:`~django.contrib.auth.models.User` and need to be rewritten or extended
- to work with a custom user model:
- * :class:`~django.contrib.auth.forms.UserCreationForm`
- * :class:`~django.contrib.auth.forms.UserChangeForm`
- If your custom user model is a subclass of ``AbstractUser``, then you can
- extend these forms in this manner::
- from django.contrib.auth.forms import UserCreationForm
- from myapp.models import CustomUser
- class CustomUserCreationForm(UserCreationForm):
- class Meta(UserCreationForm.Meta):
- model = CustomUser
- fields = UserCreationForm.Meta.fields + ("custom_field",)
- .. versionchanged:: 4.2
- In older versions, :class:`~django.contrib.auth.forms.UserCreationForm`
- didn't save many-to-many form fields for a custom user model.
- Custom users and :mod:`django.contrib.admin`
- --------------------------------------------
- If you want your custom user model to also work with the admin, your user model
- must define some additional attributes and methods. These methods allow the
- admin to control access of the user to admin content:
- .. class:: models.CustomUser
- :noindex:
- .. attribute:: is_staff
- Returns ``True`` if the user is allowed to have access to the admin site.
- .. attribute:: is_active
- Returns ``True`` if the user account is currently active.
- .. method:: has_perm(perm, obj=None):
- Returns ``True`` if the user has the named permission. If ``obj`` is
- provided, the permission needs to be checked against a specific object
- instance.
- .. method:: has_module_perms(app_label):
- Returns ``True`` if the user has permission to access models in
- the given app.
- You will also need to register your custom user model with the admin. If
- your custom user model extends ``django.contrib.auth.models.AbstractUser``,
- you can use Django's existing ``django.contrib.auth.admin.UserAdmin``
- class. However, if your user model extends
- :class:`~django.contrib.auth.models.AbstractBaseUser`, you'll need to define
- a custom ``ModelAdmin`` class. It may be possible to subclass the default
- ``django.contrib.auth.admin.UserAdmin``; however, you'll need to
- override any of the definitions that refer to fields on
- ``django.contrib.auth.models.AbstractUser`` that aren't on your
- custom user class.
- .. note::
- If you are using a custom ``ModelAdmin`` which is a subclass of
- ``django.contrib.auth.admin.UserAdmin``, then you need to add your custom
- fields to ``fieldsets`` (for fields to be used in editing users) and to
- ``add_fieldsets`` (for fields to be used when creating a user). For
- example::
- from django.contrib.auth.admin import UserAdmin
- class CustomUserAdmin(UserAdmin):
- ...
- fieldsets = UserAdmin.fieldsets + ((None, {"fields": ["custom_field"]}),)
- add_fieldsets = UserAdmin.add_fieldsets + ((None, {"fields": ["custom_field"]}),)
- See :ref:`a full example <custom-users-admin-full-example>` for more
- details.
- Custom users and permissions
- ----------------------------
- To make it easy to include Django's permission framework into your own user
- class, Django provides :class:`~django.contrib.auth.models.PermissionsMixin`.
- This is an abstract model you can include in the class hierarchy for your user
- model, giving you all the methods and database fields necessary to support
- Django's permission model.
- :class:`~django.contrib.auth.models.PermissionsMixin` provides the following
- methods and attributes:
- .. class:: models.PermissionsMixin
- .. attribute:: models.PermissionsMixin.is_superuser
- Boolean. Designates that this user has all permissions without
- explicitly assigning them.
- .. method:: models.PermissionsMixin.get_user_permissions(obj=None)
- Returns a set of permission strings that the user has directly.
- If ``obj`` is passed in, only returns the user permissions for this
- specific object.
- .. method:: models.PermissionsMixin.get_group_permissions(obj=None)
- Returns a set of permission strings that the user has, through their
- groups.
- If ``obj`` is passed in, only returns the group permissions for
- this specific object.
- .. method:: models.PermissionsMixin.get_all_permissions(obj=None)
- Returns a set of permission strings that the user has, both through
- group and user permissions.
- If ``obj`` is passed in, only returns the permissions for this
- specific object.
- .. method:: models.PermissionsMixin.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
- :ref:`permissions <topic-authorization>`). If :attr:`.User.is_active`
- and :attr:`~.User.is_superuser` are both ``True``, this method always
- returns ``True``.
- If ``obj`` is passed in, this method won't check for a permission for
- the model, but for this specific object.
- .. method:: models.PermissionsMixin.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 :attr:`.User.is_active` and
- :attr:`~.User.is_superuser` are both ``True``, this method always
- returns ``True``.
- If ``obj`` is passed in, this method won't check for permissions for
- the model, but for the specific object.
- .. method:: models.PermissionsMixin.has_module_perms(package_name)
- Returns ``True`` if the user has any permissions in the given package
- (the Django app label). If :attr:`.User.is_active` and
- :attr:`~.User.is_superuser` are both ``True``, this method always
- returns ``True``.
- .. admonition:: ``PermissionsMixin`` and ``ModelBackend``
- If you don't include the
- :class:`~django.contrib.auth.models.PermissionsMixin`, you must ensure you
- don't invoke the permissions methods on ``ModelBackend``. ``ModelBackend``
- assumes that certain fields are available on your user model. If your user
- model doesn't provide those fields, you'll receive database errors when
- you check permissions.
- Custom users and proxy models
- -----------------------------
- One limitation of custom user models is that installing a custom user model
- will break any proxy model extending :class:`~django.contrib.auth.models.User`.
- Proxy models must be based on a concrete base class; by defining a custom user
- model, you remove the ability of Django to reliably identify the base class.
- If your project uses proxy models, you must either modify the proxy to extend
- the user model that's in use in your project, or merge your proxy's behavior
- into your :class:`~django.contrib.auth.models.User` subclass.
- .. _custom-users-admin-full-example:
- A full example
- --------------
- Here is an example of an admin-compliant custom user app. This user model uses
- an email address as the username, and has a required date of birth; it
- provides no permission checking beyond an ``admin`` flag on the user account.
- This model would be compatible with all the built-in auth forms and views,
- except for the user creation forms. This example illustrates how most of the
- components work together, but is not intended to be copied directly into
- projects for production use.
- This code would all live in a ``models.py`` file for a custom
- authentication app::
- from django.db import models
- from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
- class MyUserManager(BaseUserManager):
- def create_user(self, email, date_of_birth, password=None):
- """
- Creates and saves a User with the given email, date of
- birth and password.
- """
- if not email:
- raise ValueError("Users must have an email address")
- user = self.model(
- email=self.normalize_email(email),
- date_of_birth=date_of_birth,
- )
- user.set_password(password)
- user.save(using=self._db)
- return user
- def create_superuser(self, email, date_of_birth, password=None):
- """
- Creates and saves a superuser with the given email, date of
- birth and password.
- """
- user = self.create_user(
- email,
- password=password,
- date_of_birth=date_of_birth,
- )
- user.is_admin = True
- user.save(using=self._db)
- return user
- class MyUser(AbstractBaseUser):
- email = models.EmailField(
- verbose_name="email address",
- max_length=255,
- unique=True,
- )
- date_of_birth = models.DateField()
- is_active = models.BooleanField(default=True)
- is_admin = models.BooleanField(default=False)
- objects = MyUserManager()
- USERNAME_FIELD = "email"
- REQUIRED_FIELDS = ["date_of_birth"]
- def __str__(self):
- return self.email
- def has_perm(self, perm, obj=None):
- "Does the user have a specific permission?"
- # Simplest possible answer: Yes, always
- return True
- def has_module_perms(self, app_label):
- "Does the user have permissions to view the app `app_label`?"
- # Simplest possible answer: Yes, always
- return True
- @property
- def is_staff(self):
- "Is the user a member of staff?"
- # Simplest possible answer: All admins are staff
- return self.is_admin
- Then, to register this custom user model with Django's admin, the following
- code would be required in the app's ``admin.py`` file::
- from django import forms
- from django.contrib import admin
- from django.contrib.auth.models import Group
- from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
- from django.contrib.auth.forms import ReadOnlyPasswordHashField
- from django.core.exceptions import ValidationError
- from customauth.models import MyUser
- class UserCreationForm(forms.ModelForm):
- """A form for creating new users. Includes all the required
- fields, plus a repeated password."""
- password1 = forms.CharField(label="Password", widget=forms.PasswordInput)
- password2 = forms.CharField(
- label="Password confirmation", widget=forms.PasswordInput
- )
- class Meta:
- model = MyUser
- fields = ["email", "date_of_birth"]
- def clean_password2(self):
- # Check that the two password entries match
- password1 = self.cleaned_data.get("password1")
- password2 = self.cleaned_data.get("password2")
- if password1 and password2 and password1 != password2:
- raise ValidationError("Passwords don't match")
- return password2
- def save(self, commit=True):
- # Save the provided password in hashed format
- user = super().save(commit=False)
- user.set_password(self.cleaned_data["password1"])
- if commit:
- user.save()
- return user
- class UserChangeForm(forms.ModelForm):
- """A form for updating users. Includes all the fields on
- the user, but replaces the password field with admin's
- disabled password hash display field.
- """
- password = ReadOnlyPasswordHashField()
- class Meta:
- model = MyUser
- fields = ["email", "password", "date_of_birth", "is_active", "is_admin"]
- class UserAdmin(BaseUserAdmin):
- # The forms to add and change user instances
- form = UserChangeForm
- add_form = UserCreationForm
- # The fields to be used in displaying the User model.
- # These override the definitions on the base UserAdmin
- # that reference specific fields on auth.User.
- list_display = ["email", "date_of_birth", "is_admin"]
- list_filter = ["is_admin"]
- fieldsets = [
- (None, {"fields": ["email", "password"]}),
- ("Personal info", {"fields": ["date_of_birth"]}),
- ("Permissions", {"fields": ["is_admin"]}),
- ]
- # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
- # overrides get_fieldsets to use this attribute when creating a user.
- add_fieldsets = [
- (
- None,
- {
- "classes": ["wide"],
- "fields": ["email", "date_of_birth", "password1", "password2"],
- },
- ),
- ]
- search_fields = ["email"]
- ordering = ["email"]
- filter_horizontal = []
- # Now register the new UserAdmin...
- admin.site.register(MyUser, UserAdmin)
- # ... and, since we're not using Django's built-in permissions,
- # unregister the Group model from admin.
- admin.site.unregister(Group)
- Finally, specify the custom model as the default user model for your project
- using the :setting:`AUTH_USER_MODEL` setting in your ``settings.py``::
- AUTH_USER_MODEL = "customauth.MyUser"
|