Django内置User模型详解:字段、创建、扩展与认证实战

凌晨两点半
凌晨两点半
发布时间:2026-10-13| 4人浏览过
原创

本文深入解析Django内置User模型,详细列举username、password等12个核心字段及其约束。通过代码示例演示create_user与create_superuser的创建流程,以及authenticate的登录验证机制。重点探讨三种用户模型扩展方案:代理模型、一对一外键及AbstractUser继承,涵盖AUTH_USER_MODEL配置、USERNAME_FIELD重写及数据库迁移注意事项,帮助开发者灵活构建符合业务需求的用户系统。

Django User模型概述

User模型

User模型是Django框架的核心组成部分,其完整路径为django.contrib.auth.models.User。

User模型核心字段详解

字段

内置的User模型包含以下字段:

1、username:用户名,长度限制在150个字符以内。允许包含数字、英文字符以及_、@、+、.和-符号。该字段不能为空且必须唯一。

2、first_name:名,长度限制在30个字符以内,允许为空。

3、last_name:姓,长度限制在150个字符以内,允许为空。

4、email:邮箱地址,允许为空。

5、password:密码,数据库中存储的是经过哈希处理后的密文。

6、groups:分组字段,表示用户与Group模型的多对多关系。一个用户可以属于多个分组,一个分组也可包含多个用户。

7、user_permissions:权限字段,表示用户与Permission模型的多对多关系。一个用户可拥有多个权限,一个权限也可被多个用户共享。

8、is_staff:布尔值,标识用户是否拥有访问Django Admin站点的权限(即是否为员工)。

9、is_active:布尔值,标识用户账户是否可用。对于需要停用而非物理删除的账号,可将此值设为False(0),而无需从数据库中删除记录。

10、is_superuser:布尔值,标识是否为超级管理员。若为True,则该用户拥有网站的所有权限。

11、last_login:记录用户上次登录的时间。

12、date_joined:记录账号创建的时间。

User模型基本用法:创建与验证

User模型的基本用法:

首先执行makemigrations和migrate命令,将模型映射到数据库。

创建用户:

使用create_user方法可快速创建普通用户。该方法必须传递username、email和password参数。


from django.http import HttpResponse
from django.contrib.auth.models import User

def index(request):
  user = User.objects.create_user(username='xujin',email='qq@qq.com',password='111111')
  return HttpResponse('success')

执行上述视图后,进入数据库查看auth_user表,即可看到刚创建的用户信息。

上述三个参数为必填项,其余为可选参数。在数据库中看到的密码看似乱码,实则是经过哈希加密处理的结果,并非明文存储。

我们还可以对User对象进行数据修改。


def index(request):
  # user = User.objects.create_user(username='xujin',email='qq@qq.com',password='111111')
  user = User.objects.get(username='xujin')
  user.last_name = 'aaa'
  user.save() #更改完数据之后一定要记得保存
  return HttpResponse('success')

但密码字段不能直接赋值修改,因为直接赋值会导致密码以明文形式存入数据库,无法进行哈希加密。需使用User对象提供的set_password方法进行修改。


def index(request):
  # user = User.objects.create_user(username='xujin',email='qq@qq.com',password='111111')
  user = User.objects.get(username='xujin')
  # user.last_name = 'aaa'
  # user.save() #更改完数据之后一定要记得保存
  # user.password = '222222' # 这样修改是错误的,在数据库中会明文显示,不会被加密处理
  user.set_password('222222') # 这个方法设置的密码才会经过加密处理然后存放到数据库中去
  user.save()
  return HttpResponse('success')

创建超级用户:

创建超级用户有两种方式。

第一种是使用代码方式。创建超级用户的代码与普通用户类似,但需调用create_superuser方法。示例代码如下:


def index(request):
  user = User.objects.create_superuser(username='xujin1',email='QQ@qq.com',password='111111')
  return HttpResponse('success')

成功创建超级用户后,可在数据库auth_user表的is_superuser字段中查看到值为1(表示超级用户),而普通用户的该值为0。

第二种创建超级用户的方式是使用命令行。

在终端输入:


python manage.py createsuperuser

执行该命令可创建超级用户,但系统对密码强度有较高要求,禁止设置过于简单的密码。

注意:由于Django内置User模型规定username为唯一字段,因此创建用户时username不能重复。

登录验证

Django的认证系统已实现登录验证功能。通过django.contrib.auth.authenticate方法即可实现,该方法仅支持通过username和password进行验证。示例代码如下:


from django.contrib.auth import authenticate

def index(request):
  username = 'xujin'
  password = '222222'
  user = authenticate(request,username=username,password=password) # 验证成功之后就会返回这个user对象
  if user:
    print('登录成功:%s' % user.username)
  else:
    print('用户名或密码错误!')
  return HttpResponse('success')

扩展用户模型的三种方案

扩展用户模型

Django内置的User模型功能强大,但有时无法满足特定需求。例如,登录验证默认使用用户名,而业务可能需要通过手机号或邮箱验证;或者需要增加额外字段。此时需扩展用户模型,主要有以下几种方式。

方案一:代理模型(Proxy Model)

1. 设置Proxy(代理)模型:

若对Django提供的字段及验证方法满意,仅需在原有基础上增加操作方法,建议使用此方式。示例代码如下:

在models.py中创建一个代理模型:


from django.contrib.auth.models import User

class Person(User):
  class Meta:
    proxy = True # 表明这是一个代理模型

  @classmethod
  def get_user_number(cls):
    # 获取user的个数
    return cls.objects.all().count()

然后在views.py导入并使用:


from .models import Person

def proxyView(request):
  user_number = Person.get_user_number()
  print(user_number)
    
  # 因为我们使用了代理模型,那么以下两种写法是等价的  # User.objects.all()
  # Person.objects.all() 
  
  return HttpResponse('success')

这是代理模型的基本用法,可定义自定义方法而不改变原User模型的方法。

由于是代理模型,不能在其中添加新字段。例如,若尝试在Person模型中添加新字段,将报错,提示代理模型不能包含模型字段。


class Person(User):
  telephone = models.CharField(max_length=11)

  class Meta:
    proxy = True # 表明这是一个代理模型

  @classmethod
  def get_user_number(cls):
    # 获取user的个数
    return cls.objects.all().count()

执行makemigrations后的报错信息为:


ERRORS:
?: (models.E017) Proxy model 'Person' contains model fields.

虽然代理模型不能拥有新字段,但可以拥有自己的属性。

若需给User模型增加新字段,可采用一对一外键的方式扩展。

方案二:一对一外键扩展

一对一外键

若对authenticate验证方法无特殊要求(仅使用username和password),但需在原模型基础上添加新字段,可使用一对一外键方式。

首先在models.py中新建一个模型,并使用一对一外键与User连接:


class UserExtension(models.Model):
  # 定义一个一对一的外键
  user = models.OneToOneField(User,on_delete=models.CASCADE,related_name='extension')
  telephone = models.CharField(max_length=11)
  school = models.CharField(max_length=100)

from django.dispatch import receiver
from django.db.models.signals import post_save
# 这是一个信号函数,即每创建一个User对象时,就会新建一个userextionsion进行绑定,使用了receiver这个装饰器
@receiver(post_save,sender=User)
def handler_user_extension(sender,instance,created,**kwargs):
  if created: # 如果是第一次创建user对象,就创建一个userextension对象进行绑定
    UserExtension.objects.create(user=instance)
  else: # 如果是修改user对象,那么也要将extension进行保存
    instance.extension.save()

随后需将新增字段映射到数据库,执行makemigrations和migrate命令。

然后在views.py中写入视图:


def oneView(request):
  user = User.objects.create_user(username='aaaaaa',email='QQ@qq.com',password='111111')
  return HttpResponse('一对一扩展User')

添加映射并执行代码后,即可在数据库中看到添加的信息。

由于定义了extension扩展模型,无法直接使用自带的authenticate验证登录,需自定义authenticate方法。


def my_authenticate(telephone,password):
  user = User.objects.filter(extension__telephone=telephone).first()
  if user:
    is_correct = user.check_password(password)
    if is_correct:
      return user
    else:
      print('密码错误!')
      return None
  else:
    print('没有找到此用户')
    return None

def oneView(request):
  # 创建一条测试数据
  user = User.objects.create_user(username='bbb',email='QQ@qq.com',password='111111')
  user.extension.telephone = '18888888888'
  user.save()
  return HttpResponse('一对一扩展User')

上述代码中定义了自定义的my_authenticate方法用于验证登录。在视图oneView中创建测试数据,此时尚未使用自定义方法,需先新建测试数据才能调用。

运行上述代码后,即可使用自定义方法验证登录。

修改视图:


def oneView(request):
  # 创建一条测试数据
  # user = User.objects.create_user(username='bbb',email='QQ@qq.com',password='111111')
  # user.extension.telephone = '18888888888'
  # user.save()
  telephone = '18888888888'
  password = '111111'
  user = my_authenticate(telephone,password)
  if user:
    print('登录成功')
  else:
    print('登录失败')
  return HttpResponse('一对一扩展User')

以上即为使用一对一方式扩展User模型的过程。

方案三:继承AbstractUser

继承自AbstractUser

若对authenticate不满意,且不想修改原User对象字段,但需增加新字段,可直接继承django.contrib.auth.models.AbstractUser。该类是User的父类。例如,需在原User模型基础上添加telephone和school字段,示例代码如下。

首先注释掉以前所有代码,在models.py中写入代码:


from django.contrib.auth.models import AbstractUser,BaseUserManager

# 自定义管理工具
class UserManage(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)

  # 我们在使用authenticate的时候,默认传入的就好似username和password字段
  # 现在我们设置了这个属性的值,那么再使用authenticate的时候,就会使用我们设定的字段
  USERNAME_FIELD = 'telephone'
  objects = UserManage()

随后需在settings中添加变量,告知Django修改了内置User模型,使用自定义的User模型:


AUTH_USER_MODEL = 'front.User'

该变量名必须固定,不能随意命名。

变量值为自定义User模型的位置:app名.模型名。

要使用自定义模型,需先映射到数据库。由于改变了内置User结构且数据库中已存在未修改的User模型,直接迁移会报错。因此需删除所有表及迁移文件,重新执行makemigrations和migrate命令方可成功。

随后在views.py中添加视图:


from .models import User

def inherit_view(request):
  telephone = '18888888888'
  password = '111111'
  username = 'xujin'
  user = User.objects.create_user(telephone=telephone,password=password,username=username)
  print(user.username)
  return HttpResponse('success')

执行上述代码,即可成功创建用户,并使用自定义的User模型。

若需使用authenticate验证输入信息,应验证哪个字段?


def inherit_view(request):
  telephone = '18888888888'
  password = '111111'
  username = 'xujin'
  # user = User.objects.create_user(telephone=telephone,password=password,username=username)
  # print(user.username)

  user = authenticate(request,username=telephone,password=password)
  if user:
    print('登录成功')
    print(user.username)
  else:
    print('验证失败')
  return HttpResponse('success')

在authenticate中,username参数传入的是telephone字段。这是因为在User模型中重写了USERNAME_FIELD属性,该属性接收的值即为authenticate中username对应的字段。由于将USERNAME_FIELD值改为telephone,使用时也需使用telephone字段,此时username参数不再表示username字段,而是代表USERNAME_FIELD属性定义的字段。

注意:USERNAME_FIELD属性对应的字段必须设置唯一,即需设置unique=True参数。

以上这篇对Django中内置的User模型实例详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。