Django 用户认证系统:拓展 User 模型

本教程为系列教程,为方便阅读,每篇教程开头列出所有教程的目录索引:python


Django 用户认证系统提供了一个内置的 User 对象,用于记录用户的用户名,密码等我的信息。对于 Django 内置的 User 模型, 仅包含如下一些主要的属性:git

  • username,即用户名
  • password,密码
  • email,邮箱
  • first_name,名
  • last_name,姓

对于一些网站来讲,用户可能还包含有昵称、头像、个性签名等等其它属性,所以仅仅使用 Django 内置的 User 模型是不够。好在 Django 用户系统遵循可拓展的设计原则,咱们能够方便地拓展 User 模型。github

继承 AbstractUser 拓展用户模型

这是推荐作法。事实上,查看 User 模型的源码就知道,User 也是继承自 AbstractUser 抽象基类,并且仅仅就是继承了 AbstractUser,没有对 AbstractUser 作任何的拓展。如下就是 User 的源码:数据库

class User(AbstractUser):
    """ Users within the Django authentication system are represented by this model. Username, password and email are required. Other fields are optional. """
    class Meta(AbstractUser.Meta):
        swappable = 'AUTH_USER_MODEL'复制代码

因此,若是咱们继承 AbstractUser,将得到 User 的所有特性,并且还能够根据本身的需求进行拓展。django

咱们以前新建了一个 users 应用,一般咱们把和数据库模型相关的代码写在 models.py 文件里。打开 users/models.py 文件,写上咱们自定义的用户模型代码:bash

users/models.py

from django.db import models
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    nickname = models.CharField(max_length=50, blank=True)

    class Meta(AbstractUser.Meta):
        pass复制代码

咱们给自定义的用户模型新增了一个 nickname(昵称)属性,用来记录用户的昵称信息,设置 blank=True 的目的是让用户在注册时无需填写昵称。根据你的需求能够本身进一步拓展,例如增长用户头像、个性签名等等,添加多少属性字段没有任何限制。app

同时,咱们继承了 AbstractUser 的内部类属性 Meta ,不过目前什么也没作。在这里继承 Meta 的缘由是在你的项目中可能须要设置一些 Meta 类的属性值,不要忘记继承 AbstractUser.Meta 中已有的属性。post

注意:必定要继承 AbstractUser,而不是继承 auth.User。尽管 auth.User 继承自 AbstractUser 且并无对其进行任何额外拓展,但 AbstractUser 是一个抽象类,而 auth.User 不是。若是你继承了 auth.User 类,这会变成多表继承,在目前的状况下这种继承方式是不被推荐的。关于 Django 的抽象模型类和多表继承,请查阅 Django 的官方文档 模型继承网站

此外,AbstractUser 类又继承自 AbstractBaseUser,前者在后者的基础上拓展了一套用户权限(Permission)系统。所以如非特殊须要,尽可能不要从 AbstractBaseUser 拓展,不然你须要作更多的额外工做。ui

为了让 Django 用户认证系统使用咱们自定义的用户模型,必须在 settings.py 里经过 AUTH_USER_MODEL 指定自定义用户模型所在的位置,即须要以下设置:

django_auth_example/settings.py

# 其它设置...
AUTH_USER_MODEL = 'users.User'复制代码

即告诉 Django,使用 users 应用下的 User 用户模型。

顺便再修改一下语言设置和时区设置:

django_auth_example/settings.py

# 其它设置...

LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'复制代码

设置好自定义用户模型后,生成数据库迁移文件,而且迁移数据库以生成各个应用必要的数据库表。即运行以下两条命令:

$ python manage.py makemigrations
$ python manage.py migrate复制代码

OK,如今 Django 用户系统使用的用户模型就是自定义的 User 模型了。

注意:必定要在设置好 AUTH_USER_MODEL = 'users.User' 后在第一次迁移数据库,即指定好自定义的用户模型后再执行数据库迁移命令。

使用 Profile 模式拓展用户模型

若是想为一个已使用了 Django 内置 User 模型的项目拓展用户模型,上述继承 AbstractUser 的拓展方式会变得有点麻烦。Django 没有提供一套自动化的方式将内置的 User 迁移到自定义的用户模型,由于 Django 已经为内置的 User 模型生成了相关数据库迁移文件和数据库表。若是非要这么作的话,须要手工修改迁移文件和数据库表,而且移动数据库中相关的用户数据。

因此咱们采用另外一种不改动数据库表的方式来拓展用户模型,具体来讲,咱们在建立一个模型(一般命名为 Profile)来记录用户相关的数据,而后使用一对一的方式将这个 Profile 模型和 User 关联起来,就好像每一个用户都关联着一张记录我的资料的表同样。代码以下:

models.py

from django.contrib.auth.models import User

class Profile(models.Model):
    nickname = models.CharField(max_length=50, blank=True)
    user = models.OneToOneField(User)复制代码

这种方式和 AbstractUser 的区别是,继承 AbstractUser 的用户模型只有一张数据库表。而 Profile 这种模式有两张表,一张是 User 模型对应的表,一张是 Profile 模型对应的表,两张表经过一对一的关系关联。可见,当要查询某个用户的 Profile 时,须要执行额外的跨表查询操做,因此这种方式比起直接继承 AbstractUser 效率更低一点。所以对于新项目来讲,优先推荐使用继承 AbstractUser 的方式来拓展用户模型。

PS:若是你使用了Profile 模式,你可能但愿在建立 User 对象的时候同时也建立与之关联的 Profile 对象。你可使用 Django 的 Signal 实现这个需求。因为 Profile 模式不是咱们要介绍的重点内容,所以具体的实现细节请参照相关的文档,这里再也不赘述。

OK,自定义的 User 模型已经创建好了,接下来就是如何建立用户,即用户注册流程了。

总结

本教程的示例项目代码位于 GitHub:Django Auth Example

若是遇到问题,请经过下面的方式寻求帮助。

更多 Django 相关教程,请访问个人我的博客:追梦人物的博客

相关文章
相关标签/搜索