Added first draft of custom User docs.
Thanks to Greg Turner for the initial text.
This commit is contained in:
parent
75118bd242
commit
e6aaf65970
|
@ -57,6 +57,10 @@ API reference
|
||||||
Fields
|
Fields
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
|
TODO document which attributes/methods come from AbstractBaseUser
|
||||||
|
TODO tone down references to get_profile - it's not the best way of doing things
|
||||||
|
any more.
|
||||||
|
|
||||||
.. class:: models.User
|
.. class:: models.User
|
||||||
|
|
||||||
:class:`~django.contrib.auth.models.User` objects have the following
|
:class:`~django.contrib.auth.models.User` objects have the following
|
||||||
|
@ -1714,7 +1718,239 @@ Fields
|
||||||
Customizing the User model
|
Customizing the User model
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
TODO
|
.. versionadded:: 1.5
|
||||||
|
|
||||||
|
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 name of the Django app, and the name of the Django
|
||||||
|
model that you wish to use as your User model.
|
||||||
|
|
||||||
|
.. admonition:: Warning
|
||||||
|
|
||||||
|
Changing :setting:`AUTH_USER_MODEL` has a big effect on your database
|
||||||
|
structure. It changes the tables that are available, and it will affect the
|
||||||
|
construction of foreign keys and many-to-many relationships. If you intend
|
||||||
|
to set :setting:`AUTH_USER_MODEL`, you should set it before running
|
||||||
|
``manage.py syncdb`` for the first time.
|
||||||
|
|
||||||
|
Referencing the User model
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Instead of referring to :class:`~django.contrib.auth.models.User` directly,
|
||||||
|
you should reference the user model using
|
||||||
|
:meth:`~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.User` otherwise.
|
||||||
|
|
||||||
|
In 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)
|
||||||
|
|
||||||
|
Specifying a custom User model
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
.. admonition:: Model design considerations
|
||||||
|
|
||||||
|
Think carefully before handling information not directly related to
|
||||||
|
authentication in your custom User Model.
|
||||||
|
|
||||||
|
It may be better to store app-specific user information in a model
|
||||||
|
that has a relation with the User model. That allows each app to specify
|
||||||
|
its own user data requirements without risking conflicts with other
|
||||||
|
apps. On the other hand, queries to retrieve this related information
|
||||||
|
will involve a database join, which may have an effect on performance.
|
||||||
|
|
||||||
|
Django expects your custom User model to meet some minimum requirements. The
|
||||||
|
easiest way to construct a compliant custom User model is to inherit from
|
||||||
|
:class:`~django.contrib.auth.models.AbstractBaseUser` and provide some key
|
||||||
|
definitions:
|
||||||
|
|
||||||
|
.. attribute:: User.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.
|
||||||
|
|
||||||
|
.. method:: User.get_full_name():
|
||||||
|
|
||||||
|
A longer formal identifier for the user. A common interpretation
|
||||||
|
would be the full name name of the user, but it can be any string that
|
||||||
|
identifies the user.
|
||||||
|
|
||||||
|
.. method:: User.get_short_name():
|
||||||
|
|
||||||
|
A short, informal identifier for the user. A common interpretation
|
||||||
|
would be the first name of the user, but it can be any string that
|
||||||
|
identifies the user in an informal way. It may also return the same
|
||||||
|
value as :meth:`django.contrib.auth.User.get_full_name()`.
|
||||||
|
|
||||||
|
You should also define a custom manager for your User model. If your User
|
||||||
|
model defines `username` and `email` fields the same as Django's default User,
|
||||||
|
you can just install Django's
|
||||||
|
:class:`~django.contrib.auth.models.UserManager`; however, if your User model
|
||||||
|
defines different fields, you will need to define a custom manager with 2
|
||||||
|
methods.
|
||||||
|
|
||||||
|
.. method:: UserManager.create_user(username, password=None, **other_fields)
|
||||||
|
|
||||||
|
The prototype of `create_user()` should accept all required fields
|
||||||
|
as arguments. For example, if your user model defines `username`,
|
||||||
|
and `date_of_birth` as required fields, then create_user should be
|
||||||
|
defined as::
|
||||||
|
|
||||||
|
def create_user(self, username, date_of_birth, password=None):
|
||||||
|
# create user here
|
||||||
|
|
||||||
|
.. method:: UserManager.create_superuser(username, password, **other_fields)
|
||||||
|
|
||||||
|
The prototype of `create_superuser()` should accept all required fields
|
||||||
|
as arguments. For example, if your user model defines `username`,
|
||||||
|
and `date_of_birth` as required fields, then create_user should be
|
||||||
|
defined as::
|
||||||
|
|
||||||
|
def create_superuser(self, username, date_of_birth, password):
|
||||||
|
# create superuser here
|
||||||
|
|
||||||
|
Unlike `create_user()`, `create_superuser()` *must* require the caller
|
||||||
|
to provider a password.
|
||||||
|
|
||||||
|
Custom users and django.contrib.admin
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
If you want your custom User model to also work with 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:
|
||||||
|
|
||||||
|
.. attribute:: User.is_staff
|
||||||
|
|
||||||
|
Returns True if the user is a member of staff.
|
||||||
|
|
||||||
|
.. attribute:: User.is_active
|
||||||
|
|
||||||
|
Returns True if the user account is currently active.
|
||||||
|
|
||||||
|
.. method:: User.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:: User.has_module_perms(app_label):
|
||||||
|
|
||||||
|
Returns True if the user has permission to access models in
|
||||||
|
the given app.
|
||||||
|
|
||||||
|
|
||||||
|
Worked Example
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
As a worked example, here is a full models.py for 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 a simple
|
||||||
|
`admin` flag on the user account::
|
||||||
|
|
||||||
|
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=MyUserManager.normalize_email(email),
|
||||||
|
date_of_birth=date_of_birth,
|
||||||
|
)
|
||||||
|
|
||||||
|
user.set_password(password)
|
||||||
|
user.save(using=self._db)
|
||||||
|
return user
|
||||||
|
|
||||||
|
def create_superuser(self, username, date_of_birth, password):
|
||||||
|
"""
|
||||||
|
Creates and saves a superuser with the given email, date of
|
||||||
|
birth and password.
|
||||||
|
"""
|
||||||
|
u = self.create_user(username,
|
||||||
|
password=password,
|
||||||
|
date_of_birth=date_of_birth
|
||||||
|
)
|
||||||
|
u.is_admin = True
|
||||||
|
u.save(using=self._db)
|
||||||
|
return u
|
||||||
|
|
||||||
|
|
||||||
|
class MyUser(AbstractBaseUser):
|
||||||
|
email = models.EmailField(
|
||||||
|
verbose_name='email address',
|
||||||
|
max_length=255
|
||||||
|
)
|
||||||
|
date_of_birth = models.DateField()
|
||||||
|
is_admin = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
objects = MyUserManager()
|
||||||
|
|
||||||
|
USERNAME_FIELD = 'email'
|
||||||
|
|
||||||
|
def get_full_name(self):
|
||||||
|
# The user is identified by their email address
|
||||||
|
return self.email
|
||||||
|
|
||||||
|
def get_short_name(self):
|
||||||
|
# The user is identified by their email address
|
||||||
|
return self.email
|
||||||
|
|
||||||
|
def __unicode__(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
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_active(self):
|
||||||
|
"Is the user account currently active?"
|
||||||
|
# Simplest possible answer: User is always active
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
.. _authentication-backends:
|
.. _authentication-backends:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue