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 相關教程,請訪問個人我的博客:追夢人物的博客

相關文章
相關標籤/搜索