Django内置User模型详解:字段、创建、扩展与认证实战
本文深入解析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模型实例详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













