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
|
||||
~~~~~~
|
||||
|
||||
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:`~django.contrib.auth.models.User` objects have the following
|
||||
|
@ -1714,7 +1718,239 @@ Fields
|
|||
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:
|
||||
|
||||
|
|
Loading…
Reference in New Issue