Django User 模塊之 AbstractUser 擴展

最近在寫博客,剛好寫到用戶註冊註銷模塊,覺得這一方面還是挺有趣的。當嘗試掀開 Django 的源代碼時一切 API 就不會變得那麼摸不着。順着讀Django 的各模塊源碼,我們可以更靈活地更改代碼以實現自己想要的功能。

現在,思考一個問題,主需求是實現博客中用戶的註冊登錄登出功能。如果只滿足於用戶註冊時只登記其郵箱或是用戶名,Django 自帶的 User 模塊既可以實現。但實際上,一個普遍的要求是註冊用戶應該能夠修改自己的頭像信息,郵箱信息,暱稱信息等其他更靈活的需求。

可以先看一下 Django 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'

注意:如果你的是 Anaconda 管理,可以在路徑 C:\Users\User\Anaconda3\Lib\site-packages\django\contrib\auth\models.py 查看

Django 中的 User 模塊實際上繼承了 AbstractUser 模塊,AbstractUser 模塊下有 :

  • username
  • first_name
  • last_name
  • email
  • date_joined

你可以看出,User 模塊繼承了 AbstractUser 抽象基類,而僅僅只是繼承了,並沒有對 AbstractUser 進行任何擴展。所以,對於一個需要更多需求的 User 模塊信息來說,我們可以繼承 AbstractUser 並根據自己的需求進行擴展。

現在,我們對用戶屬性添加一些需求,比如支持用戶修改頭像、支持用戶暱稱、qq、wechat 以及網站鏈接等。

class User(AbstractUser):
    nickname = models.CharField(max_length=30, blank=True, null=True, verbose_name='暱稱')
    qq = models.CharField(max_length=20, blank=True, null=True, verbose_name='QQ號碼')
    url = models.URLField(max_length=100, blank=True, null=True, verbose_name='個人網頁地址')
    avatar = ProcessedImageField(upload_to='avatar',
default='avatar/default.png', verbose_name='頭像')

    class Meta:
        verbose_name = '用戶'
        verbose_name_plural = verbose_name
        ordering = ['-id']

    def __str__(self):
        return self.username

我們給自定義的用戶模塊增加 nickname(暱稱), qq, url(網站鏈接),avatar(頭像)屬性。

注意:爲了讓 Django 能夠識別使用自定義的用戶模型,必須要在 settings.py 中設置自定義模塊位置,如在 settings.py 上添加

AUTH_USER_MODEL = 'blog.user'

其中,blog 爲你對應的應用 app 信息,user 爲 blog 應用下的 user 模塊,在這裏 bloguser 大小寫無關。

如果在你現在執行數據庫遷移命令,可能會出現 blog 不存在 user 模塊 的提示,而無法重新進行數據遷移。

ValueError: The field account.EmailAddress.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field admin.LogEntry.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field blog.Article.author was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field easy_comment.Comment.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field easy_comment.Like.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field notifications.Notification.recipient was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field online_status.OnlineStatus.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field socialaccount.SocialAccount.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.

所以,如果之前是使用例如 AUTH_USER_MODEL = auth.user 的用戶模型,並重新將其自定義爲 AUTH_USER_MODEL = blog.user 請刪掉 migrations 目錄下的所有文件 以及數據庫文件。

刪除之後,重新進行數據庫的遷移

$ python manage.py makemigrations myapp
$ python manage.py migrate

這個時候,所使用的用戶即爲自定義後的用戶了。

  File "C:\Users\Micky\Anaconda3\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Micky\Anaconda3\lib\site-packages\django\db\backends\sqlite3\base.py", line 303, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such table: blog_user

這裏可以在模板中指定數據庫 db_table = 'user'

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章