Django 中自定义用户模型

1,590 阅读3分钟

这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战

Django 中,自定义用户模型的两种方式是:

  • 继承 AbstractUser
  • 继承 AbstractBaseUser

注意:如果使用默认的身份验证后端,那么用户模型必须有单一的可以用作身份验证的唯一字段。它可以是用户名、电子邮箱或者其他任何唯一属性。如果想要使用非唯一字段,需要有支持这个功能的自定义身份验证后端。

  • Django 中,对于新项目,最好自定义 User 模型,即便内置 User 模型的功能满足需求。下面的模型和默认的 User 模型行为完全一致,但是在未来如果有新的需求,可以对它进行定制化。
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    pass
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User

admin.site.register(User, UserAdmin)

继承 AbstractUser 来自定义用户模型示例

  • 在 models.py 中自定义用户模型以及自定义用户模型管理器
from django.contrib.auth.models import AbstractUser, BaseUserManager


class UserManager(BaseUserManager):
    def _create_user(self, telephone, username, password, **kwargs):
        if not telephone:
            raise ValueError('必须要填写手机号码!')
        if not password:
            raise ValueError('必须要填写密码!')
        user = self.model(telephone=telephone, username=username, **kwargs)
        user.set_password(password)
        user.save()
        return user

    def create_user(self, telephone, username, password, **kwargs):
        kwargs['is_superuser'] = False
        return self._create_user(telephone=telephone, username=username, password=password, **kwargs)

    def create_superuser(self, telephone, username, password, **kwargs):
        kwargs['is_superuser'] = True
        return self._create_user(telephone=telephone, username=username, password=password, **kwargs)


class User(AbstractUser):
    telephone = models.CharField(max_length=11, unique=True)
    school = models.CharField(max_length=100)

    USERNAME_FIELD = 'telephone'
    REQUIRED_FIELDS = []

    objects = UserManager()
AUTH_USER_MODEL = 'front.User'
  • 在 views.py 中创建用户与验证用户
# 使用 create_user 创建用户
def inherit_AbstractUser1(request):
    telephone = '17788889999'
    username = 'tuanzi'
    password = '123456'
    user = User.objects.create_user(telephone=telephone, username=username, password=password)
    print(user.username)
    return HttpResponse('Django 中自定义用户模型:继承 AbstractUser')

# 使用 create_superuser 创建用户
def inherit_AbstractUser2(request):
    telephone = '17799998888'
    username = 'super_tuanzi'
    password = '123456'
    user = User.objects.create_superuser(telephone=telephone, username=username, password=password)
    print(user.username)
    return HttpResponse('Django 中自定义用户模型:继承 AbstractUser')

# 验证用户
def inherit_AbstractUser3(request):
    user = authenticate(request, username='17799998888', password='123456')
    if user:
        print('验证成功')
        print(user.username)
    else:
        print('验证失败')
    return HttpResponse('Django 中自定义用户模型:继承 AbstractUser')

Django 中,构造一个兼容的自定义用户模型的最简方法就是继承 AbstractBaseUser 抽象基类。

我们需要提供一些关键的实现细节

另外,下面的属性和方法在任何 AbstractBaseUser 的子类中都是可用的:

  • get_username()
  • clean()
  • classmethod get_email_field_name()
  • classmethod normalize_username(username)
  • is_authenticated
  • is_anonymous
  • set_password(raw_password)
  • check_password(raw_password)
  • set_unusable_password()
  • has_usable_password()
  • get_session_auth_hash()

继承 AbstractBaseUser 来自定义用户模型示例

  • 在 models.py 中自定义模型管理器自定义用户模型
from django.contrib.auth.models import (AbstractBaseUser, BaseUserManager,
                                        PermissionsMixin)
from django.db import models
from shortuuidfield import ShortUUIDField


class UserManager(BaseUserManager):
    def _create_user(self, telephone, username, password, **kwargs):
        if not telephone:
            raise ValueError('请传入手机号码!')
        if not username:
            raise ValueError('请传入用户名!')
        if not password:
            raise ValueError('请传入密码!')

        user = self.model(telephone=telephone, username=username, **kwargs)
        user.set_password(password)
        user.save()
        return user

    def create_user(self, telephone, username, password, **kwargs):
        kwargs['is_superuser'] = False
        return self._create_user(telephone, username, password, **kwargs)

    def create_superuser(self, telephone, username, password, **kwargs):
        kwargs['is_superuser'] = True
        kwargs['is_staff'] = True
        return self._create_user(telephone, username, password, **kwargs)


class User(AbstractBaseUser, PermissionsMixin):
    uid = ShortUUIDField(primary_key=True)
    telephone = models.CharField(max_length=11, unique=True)
    email = models.EmailField(unique=True, null=True)
    username = models.CharField(max_length=100)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    date_joined = models.DateTimeField(auto_now_add=True)

    USERNAME_FIELD = 'telephone'
    # telephone, username, password
    REQUIRED_FIELDS = ['username']
    EMAIL_FIELD = 'email'

    objects = UserManager()

    def get_full_name(self):
        return self.username

    def get_short_name(self):
        return self.username
  • 在 settings.py 中配置 AUTH_USER_MODEL 选项。注意只需要应用名加上模型名即可,其他东西不要加。
AUTH_USER_MODEL = 'front.User'
  • 第一次生成并运行迁移文件。