django——重写用户模型
Django内建的User模型可能不适合某些类型的项目。例如,在某些网站上使用邮件地址而不是用户名作为身份的标识可能更合理。
1.修改配置文件,覆盖默认的User模型
Django允许你通过修改setting.py文件中的 AUTH_USER_MODEL 设置覆盖默认的User模型,其值引用一个自定义的模型。
AUTH_USER_MODEL = 'myapp.MyUser'
上面的值表示Django应用的名称(必须位于INSTALLLED_APPS中)和你想使用的User模型的名称。
注意:
1.在创建任何迁移或者第一次运行 manager.py migrate 前设置 AUTH_USER_MODEL。
设置AUTH_USER_MODEL对你的数据库结构有很大的影响。它改变了一些会使用到的表格,并且会影响到一些外键和多对多关系的构造。在你有表格被创建后更改此设置是不被 makemigrations 支持的,并且会导致你需要手动修改数据库结构,从旧用户表中导出数据,可能重新应用一些迁移。
警告 :
1.确保 AUTH_USER_MODEL 引用的模型在所属app中第一个迁移文件中被创建
由于Django的可交换模型的动态依赖特性的局限,你必须确保 AUTH_USER_MODEL 引用的模型在所属app中第一个迁移文件中被创建(通常命名为 0001_initial),否则你会碰到错误。
The easiest way to construct a compliant custom User model is to inherit fromAbstractBaseUser. AbstractBaseUser provides the core implementation of a Usermodel, including hashed passwords and tokenized password resets. You must then provide some key implementation details:
2.引用User模型
在 AUTH_USER_MODEL 设置为自定义用户模型时,如果你直接引用User(例如:通过一个外键引用它),你的代码将不能工作。你应该使用django.contrib.auth.get_user_model()来引用用户模型————指定的自定义用户模型或者User
from django.contrib.auth import get_user_model
User = get_user_model()
当你定义一个外键或者到用户模型的多对多关系是,你应该使用AUTH_USER_MODEL设置来指定自定义的模型。
from django.conf import settings
from django.db import models
class Article(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL)
一般来说,在导入时候执行的代码中,你应该使用 AUTH_USER_MODEL 设置引用用户模型。get_user_model() 只在Django已经导入所有的模型后才工作。
3.指定自定义的用户模型
3.1 Django 期望你自定义的 User model 满足一些最低要求:
- 模型必须有一个唯一的字段可被用于识别目的。可以是一个用户名,电子邮件地址,或任何其它独特属性。
- 定制一个User Model最简单的方式是构造一个兼容的用户模型继承于AbstractBaseUser。
AbstractBaseUser提供了User类最核心的实现,包括哈希的passwords和 标识的密码重置。
3.2 下面为一些AbstractBaseUser的子类必须定义的关键的字段和方法:
USERNAME_FIELD
必须设置。 设置认证标识,设置成标识的字段 unique=True
class MyUser(AbstractBaseUser):
identifier = models.CharField(max_length=40, unique=True)
...
USERNAME_FIELD = 'identifier'
REQUIRED_FIELDS
必须设置。当通过createsuperuser管理命令创建一个用户时,用于提示的一个字段名称列表。
class MyUser(AbstractBaseUser):
...
date_of_birth = models.DateField()
height = models.FloatField()
...
REQUIRED_FIELDS = ['date_of_birth', 'height']
列表中不应该包含USERNAME_FIELD字段和password字段。
is_active
必须定义。 一个布尔属性,标识用户是否是 "active" 的。AbstractBaseUser默认为 Ture。
get_full_name()
必须定义。 long格式的用户标识。
get_short_name()
必须定义。 short格式的用户标识。
3.3 下面为一些AbstractBaseUser的子类可以使用的方法:
get_username()
返回 USERNAME_FIELD 的值。
is_anonymous()
一直返回 False。用来区分 AnonymousUser。
is_authenticated()
一直返回 Ture。用来告诉用户已被认证。
set_password(raw_password)
设置密码。按照给定的原始字符串设置用户的密码,taking care of the password hashing。 不保存 AbstractBaseUser 对象。如果没有给定密码,密码就会被设置成不使用,同用set_unusable_password()。
check_password(raw_password)
检查密码是否正确。 给定的密码正确返回 True。
set_unusable_password()
设置user无密码。 不同于密码为空,如果使用 check_password(),则不会返回True。不保存AbstractBaseUser 对象。
has_usable_password()
如果设置了set_unusable_password(),返回False。
get_session_auth_hash()
返回密码字段的HMAC。 Used for Session invalidation on password change.
3.4 为你的User模型自定义一个管理器
如果你的User模型定义了这些字段:username, email, is_staff, is_active, is_superuser, last_login, and date_joined跟默认的User没什么区别, 那么你还不如仅仅替换Django的UserManager就行了; 总之,如果你的User定义了不同的字段, 你就要去自定义一个管理器,它继承