对Django中内置的User模型实例详解
作者:stu_xujin 发布时间:2022-10-31 05:03:10
User模型
User模型是这个框架的核心部分。他的完整的路径是在django.contrib.auth.models.User。
字段
内置的User模型拥有以下的字段:
1、username: 用户名。150个字符以内。可以包含数字和英文字符,以及_、@、+、.和-字符。不能为空,且必须唯一!
2、first_name:歪果仁的first_name,在30个字符以内。可以为空。
3、last_name:歪果仁的last_name,在150个字符以内。可以为空。
4、email:邮箱。可以为空。
5、password:密码。经过哈希过后的密码。
6、groups:分组。一个用户可以属于多个分组,一个分组可以拥有多个用户。groups这个字段是跟Group的一个多对多的关系。
7、user_permissions:权限。一个用户可以拥有多个权限,一个权限可以被多个用户所有用。和Permission属于一种多对多的关系。
8、is_staff:是否可以进入到admin的站点。代表是否是员工。
9、is_active:是否是可用的。对于一些想要删除账号的数据,我们设置这个值为0就可以了,而不是真正的从数据库中删除。
10、is_superuser:是否是超级管理员。如果是超级管理员,那么拥有整个网站的所有权限。
11、last_login:上次登录的时间。
12、date_joined:账号创建的时间。
User模型的基本用法:
首先我们先执行makegrations和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的密码时经过哈希加密处理的,所以看起来是一窜乱码。
我们还可以对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的一个方法来对密码进行更改。
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模型虽然已经足够强大了。但是有时候还是不能满足我们的需求。比如在验证用户登录的时候,他用的是用户名作为验证,而我们有时候需要通过手机号码或者邮箱来进行验证。还有比如我们想要增加一些新的字段。那么这时候我们就需要扩展用户模型了。扩展用户模型有多种方式。
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()
执行makegrations后的报错信息为:
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()
然后我们需要将我们添加的字段映射到数据库中去,执行makegrations和migrate。
然后在views.py中写入视图:
def oneView(request):
user = User.objects.create_user(username='aaaaaa',email='QQ@qq.com',password='111111')
return HttpResponse('一对一扩展User')
添加映射,执行代码,然后就能在数据库中看到我么添加的信息了。
因为我么定义一个extention的扩展模型,那么我们就不能使用自带的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')
上面的代码中我们定义好了一个我么自己的authenticate方法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
对于authenticate不满意,并且不想要修改原来User对象上的一些字段,但是想要增加一些字段,那么这时候可以直接继承自django.contrib.auth.models.AbstractUser,其实这个类也是django.contrib.auth.models.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模型,我们现在再直接移植肯定是会报错的,那么我们就需要将所有的表进行删除,然后将迁移文件也进行删除了,才可以进行移植。才能执行makegrations和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对应的字段,因为我们在User中将USERNAME_FIELD的值改为了telephone字段,所以我们使用的时候也需要使用telephone字段,相当于username并不是表示username字段,而是我们USERNAME_FIELD属性定义的字段。
注意: USERNAME_FIELD属性值对应的字段必须设置唯一,即需要设置unique=True这个参数。
来源:https://blog.csdn.net/xujin0/article/details/85056419
猜你喜欢
- 从百度查到在django中,使用post方法时,需要先生成随机码,以防止CSRF(Cross-site request forgery)跨站
- 随着互联网产业的飞速发展和电子产业的飞速发展,人们的社交似乎离不开网络,这就应运了SNS的飞速发展。从打开QQ空间关注朋友们的动态,最近心情
- 前言在日常开发编程中,我们有时从用户那里得到一些输入信息,对于特定应用,部分信息不允许包含中文字符,那如何检测信息字符串中是否包含中文字符呢
- 随着网站访问量的加大,每次从数据库读取都是以效率作为代价的,很多用ACCESS作数据库的更会深有体会,静态页加在搜索时,也会被优先考虑。互联
- 打算切换某个网站的主机,没想到遇到Php和Mysql中文乱码的问题。 以前的国外主机用的Mysql是4.x系列的,感觉还比较好,都无论GBK
- vbscript脚本中,fso对象CreateTextFile方法调用时可能会报“无效的过程调用或参数”错误,在使用ASP生成静态页面时,如
- 本文实例讲述了Python实现判断给定列表是否有重复元素的方法。分享给大家供大家参考,具体如下:题目很简单,只是简单温习一个方法,most_
- 症状 在 Service Pack 4 (SP 4) 运行 Microsoft Windows Server 2003、 Microsoft
- 本文实例为大家分享了微信小程序实现星星评价效果的具体代码,供大家参考,具体内容如下代码实现wxml文件<!--pages/evalua
- 前言异常值是指样本中的个别值,也称为离群点,其数值明显偏离其余的观测值。常用检测方法3σ原则和箱型图。其中,3σ原则只适用服从正态分布的数据
- subplot(arg1, arg2, arg3)arg1: 在垂直方向同时画几张图arg2: 在水平方向同时画几张图arg3: 当前命令修
- 本文实例讲述了Python微信推送模板消息功能。分享给大家供大家参考,具体如下:官方文档:https://mp.weixin.qq.com/
- 1.什么是连接查询:在实际开发中大部分都不是从一张表中查询数据,一般都是多张表联合查询取得结果。实际开发中,一般一个业务对应多张表。比如:学
- 最近用vuepress建了个博客,音乐的背景图片需要网络地址。还有博客自动复用的摘要图片也需地址开始用的阿里云的免费对象存储oss,但又是登
- django-pagination这是一个python包,来自github上的一个项目,很容易用。不过这是一个懒人工具,好吧(工具理性)。不
- 本文为大家分享了python tkinter图形界面代码统计工具,供大家参考,具体内容如下#encoding=utf-8import os,
- 1.在搭建网络开始时,会调用到 keras.models的Sequential()方法,返回一个model参数表示模型2.model参数里面
- 函数签名对象,表示调用函数的方式,即定义了函数的输入和输出。在Python中,可以使用标准库inspect的一些方法或类,来操作或创建函数签
- 转用一门新语言通常是一项大决策,尤其是当你的团队成员中只有一个使用过它时。今年 Stream 团队的主要编程语言从 Python 转向了 G
- 摘要:NumPy中包含大量的函数,这些函数的设计初衷是能更方便地使用,掌握解这些函数,可以提升自己的工作效率。这些函数包括数组元素的选取和多