如何扩展 Django 默认用户模型

原生的Django用户模型,仅有简单的几个字段,往往难以满足实际应用的需求。比如应用中需要头像、昵称、手机号或微信UnionID等等,就需要开发者自定义扩展。

但是,每个实际应用中的用户模型,又都是最核心模块之一,往往会与其他领域模型发生各种关联关系。比如登录、验证、授权等等。所以,在系统设计之初,就应该考虑清楚。特别是在Django项目中,扩展的原生用户模型,需要是项目的第一个应用。

如何做呢?下面介绍基于Django用户模型中的AbstractUser类,自定义扩展以满足实际工程项目的需求。

用户模型

在创建Django项目后,接着创建第一个应用accounts

1
2
3
4
# 建项目
python manage.py startproject custom_user_model
# 建应用
python manage.py startapp accounts

将我们的自定义用户模型 AccountModel 作为 AbstractUser 的子类。另一个选择是扩展 AbstractBaseUser 类,二者差别在于所包含的字段不同,具体可阅读源码进一步了解。

1
2
3
4
5
6
7
8
9
10
11
12
13
# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models


class AccountModel(AbstractUser):
nickname = models.CharField('昵称')
mobile = models.CharField('手机号')
# ... 其他字段根据需要扩展

class Meta:
db_table = 'user_accounts'
managed = True'

有了自定义的用户模型,如何关联到 Django 应用体系中呢?答案是 AUTH_USER_MODEL。我们需要在项目的 settings.py 文件中,将 AccountModel 赋给这个变量。赋值方式要求按 应用名.自定义用户模型 格式。类似这样:

1
2
# custom_user_model/settings.py
AUTH_USER_MODEL = 'accounts.AccountModel'

模型管理

自定义的用户模型中,增加了额外的字段,所以我们期望在新增/修改用户的界面中,能够展示出这些额外字段。办法是,自定义新增/修改用户的表单类,并将其关联到用户模型管理界面中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from accounts.models import AccountModel


class AccountCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = AccountModel


class AccountChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = AccountModel


class AccountAdmin(UserAdmin):
form = AccountChangeForm
add_form = AccountCreationForm


admin.site.register(AccountModel, AccountAdmin)

通过以上的简单扩展,我们就可以新建/编辑用户信息时,对新增字段进行操作了。

测试运行

将我们扩展用户模型添加到应用列表中:

1
2
3
4
5
6
# custom_user_model/settings.py

INSTALLED_APPS = [
# ...
'accounts.apps.AccountsConfig',
]

执行数据库升级,创建超级用户,最后启动开发服务器:

1
2
3
4
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver

模型关联

因为自定义扩展了 Django 的用户模型,所以我们领域模型中的用户,需要以另外的方式进行关联。

1
2
3
4
5
6
7
8
from django.db import models
from custom_user_model import settings


class AccountCharge(models.Model):
account = models.ForeignKey(
settings.AUTH_USER_MODEL, # 这是新的外键关联方式!
on_delete=models.CASCADE)

通过以上几个步骤,我们就创建好了一个基于 Django 框架、适用于真实项目的基本骨架。