对Django中内置的User模型实例详解


Posted in Python onAugust 16, 2019

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这个参数。

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

Python 相关文章推荐
python命令行参数解析OptionParser类用法实例
Oct 09 Python
Python中利用sqrt()方法进行平方根计算的教程
May 15 Python
使用Python发送各种形式的邮件的方法汇总
Nov 09 Python
windows系统下Python环境搭建教程
Mar 28 Python
Python实现扣除个人税后的工资计算器示例
Mar 26 Python
TensorFlow实现非线性支持向量机的实现方法
Apr 28 Python
Python 3.x 判断 dict 是否包含某键值的实例讲解
Jul 06 Python
Python定时任务sched模块用法示例
Jul 16 Python
Python字典循环添加一键多值的用法实例
Jan 20 Python
python GUI库图形界面开发之PyQt5打开保存对话框QFileDialog详细使用方法与实例
Feb 27 Python
Elasticsearch py客户端库安装及使用方法解析
Sep 14 Python
如何利用Python实现n*n螺旋矩阵
Jan 18 Python
对Django中的权限和分组管理实例讲解
Aug 16 #Python
django创建最简单HTML页面跳转方法
Aug 16 #Python
在django中实现页面倒数几秒后自动跳转的例子
Aug 16 #Python
解决python3 安装不了PIL的问题
Aug 16 #Python
Python爬虫 批量爬取下载抖音视频代码实例
Aug 16 #Python
django 使用 PIL 压缩图片的例子
Aug 16 #Python
详解PyTorch手写数字识别(MNIST数据集)
Aug 16 #Python
You might like
PHP 删除文件与文件夹操作 unlink()与rmdir()这两个函数的使用
2011/07/17 PHP
YII实现分页的方法
2014/07/09 PHP
thinkphp特殊标签用法概述
2014/11/24 PHP
php简单实现sql防注入的方法
2016/04/22 PHP
Yii2中datetime类的使用
2016/12/17 PHP
父窗口获取弹出子窗口文本框的值
2006/06/27 Javascript
javascript 页面只自动刷新一次
2009/07/10 Javascript
9个JavaScript评级/投票插件
2010/01/18 Javascript
Js 弹出框口并返回值的两种常用方法
2010/12/30 Javascript
jquery文字上下滚动的实现方法
2013/03/22 Javascript
JQuery实现用户名无刷新验证的小例子
2013/03/22 Javascript
JavaScript数据结构和算法之图和图算法
2015/02/11 Javascript
浅谈jQuery构造函数分析
2015/05/11 Javascript
javascript实现简单的省市区三级联动
2015/05/14 Javascript
详细介绍jQuery.outerWidth() 函数具体用法
2015/07/20 Javascript
JavaScript常用正则验证函数实例小结【年龄,数字,Email,手机,URL,日期等】
2017/01/23 Javascript
js实现一个简单的数字时钟效果
2017/03/29 Javascript
BootStrap模态框闪退问题实例代码详解
2018/12/10 Javascript
JS实现的tab切换并显示相应内容模块功能示例
2019/08/03 Javascript
Tensorflow实现卷积神经网络的详细代码
2018/05/24 Python
详谈Pandas中iloc和loc以及ix的区别
2018/06/08 Python
利用Python如何生成便签图片详解
2018/07/09 Python
Windows下PyCharm安装图文教程
2018/08/27 Python
对Xpath 获取子标签下所有文本的方法详解
2019/01/02 Python
Python 画出来六维图
2019/07/26 Python
使用python获取邮箱邮件的设置方法
2019/09/20 Python
关于python pycharm中输出的内容不全的解决办法
2020/01/10 Python
解决python gdal投影坐标系转换的问题
2020/01/17 Python
意大利制造的西装、衬衫和针对男士量身定制的服装:Lanieri
2018/04/08 全球购物
心理健康教育制度
2014/01/27 职场文书
致共产党员倡议书
2014/04/16 职场文书
爱护公共设施演讲稿
2014/09/13 职场文书
2015年施工员工作总结范文
2015/04/20 职场文书
用Python实现一个打字速度测试工具来测试你的手速
2021/05/28 Python
Opencv中cv2.floodFill算法的使用
2021/06/18 Python
Redis实现主从复制方式(Master&Slave)
2022/06/21 Redis