Django User 模块之 AbstractUser 扩展详解


Posted in Python onMarch 11, 2020

最近在写博客,刚好写到用户注册注销模块,觉得这一方面还是挺有趣的。当尝试掀开 Django 的源代码时一切 API 就不会变得那么摸不着。顺着读Django 的各模块源码,我们可以更灵活地更改代码以实现自己想要的功能。

现在,思考一个问题,主需求是实现博客中用户的注册登录登出功能。如果只满足于用户注册时只登记其邮箱或是用户名,Django 自带的 User 模块既可以实现。但实际上,一个普遍的要求是注册用户应该能够修改自己的头像信息,邮箱信息,昵称信息等其他更灵活的需求。

可以先看一下 Django User 模块的源码

class User(AbstractUser):
  """
  Users within the Django authentication system are represented by this
  model.

  Username, password and email are required. Other fields are optional.
  """
  class Meta(AbstractUser.Meta):
    swappable = 'AUTH_USER_MODEL'

注意:如果你的是 Anaconda 管理,可以在路径 C:\Users\User\Anaconda3\Lib\site-packages\django\contrib\auth\models.py 查看

Django 中的 User 模块实际上继承了 AbstractUser 模块,AbstractUser 模块下有 :

username
first_name
last_name
email
date_joined

你可以看出,User 模块继承了 AbstractUser 抽象基类,而仅仅只是继承了,并没有对 AbstractUser 进行任何扩展。所以,对于一个需要更多需求的 User 模块信息来说,我们可以继承 AbstractUser 并根据自己的需求进行扩展。

现在,我们对用户属性添加一些需求,比如支持用户修改头像、支持用户昵称、qq、wechat 以及网站链接等。

class User(AbstractUser):
  nickname = models.CharField(max_length=30, blank=True, null=True, verbose_name='昵称')
  qq = models.CharField(max_length=20, blank=True, null=True, verbose_name='QQ号码')
  url = models.URLField(max_length=100, blank=True, null=True, verbose_name='个人网页地址')
  avatar = ProcessedImageField(upload_to='avatar',
default='avatar/default.png', verbose_name='头像')

  class Meta:
    verbose_name = '用户'
    verbose_name_plural = verbose_name
    ordering = ['-id']

  def __str__(self):
    return self.username

我们给自定义的用户模块增加 nickname(昵称), qq, url(网站链接),avatar(头像)属性。

注意:为了让 Django 能够识别使用自定义的用户模型,必须要在 settings.py 中设置自定义模块位置,如在 settings.py 上添加

AUTH_USER_MODEL = 'blog.user'

其中,blog 为你对应的应用 app 信息,user 为 blog 应用下的 user 模块,在这里 blog 和 user 大小写无关。

如果在你现在执行数据库迁移命令,可能会出现 blog 不存在 user 模块 的提示,而无法重新进行数据迁移。

ValueError: The field account.EmailAddress.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field admin.LogEntry.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field blog.Article.author was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field easy_comment.Comment.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field easy_comment.Like.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field notifications.Notification.recipient was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field online_status.OnlineStatus.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.
The field socialaccount.SocialAccount.user was declared with a lazy reference to 'blog.user', but app 'blog' doesn't provide model 'user'.

所以,如果之前是使用例如 AUTH_USER_MODEL = auth.user 的用户模型,并重新将其自定义为 AUTH_USER_MODEL = blog.user 请删掉 migrations 目录下的所有文件 以及数据库文件。

删除之后,重新进行数据库的迁移

$ python manage.py makemigrations myapp
$ python manage.py migrate

这个时候,所使用的用户即为自定义后的用户了。

File "C:\Users\Micky\Anaconda3\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
  return self.cursor.execute(sql, params)
 File "C:\Users\Micky\Anaconda3\lib\site-packages\django\db\backends\sqlite3\base.py", line 303, in execute
  return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such table: blog_user

这里可以在模板中指定数据库 db_table = 'user'

补充知识:Django学习笔记——内置用户类AbstractUser与内置认证校验系统

内置用户类AbstractUser

我们在之前讲过了model模型的作用和父类的作用,这次介绍的内置用户类AbstractUser就是Django内置的一个关于用户操作的类,它极大地方便了我们对model模型中对User用户类的设计。而所谓内置用户类的本质也就是一个封装好的父类,所以使用起来是相当的方便。

#导入AbstractUser类
from django.contrib.auth.models import AbstractUser

#直接继承就可以了,如果有需要就向寻常model一样写字段就可以
class User(AbstractUser):
  pass

我们通过查看AbstractUser的源码可以知道它设有几个字段

#用户名
username = models.CharField(
    _('username'),
    max_length=150,
    unique=True,
    help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
    validators=[username_validator],
    error_messages={
      'unique': _("A user with that username already exists."),
    },
  )
  
  #名
  first_name = models.CharField(_('first name'), max_length=30, blank=True)
  
  #姓
  last_name = models.CharField(_('last name'), max_length=150, blank=True)
  
  #邮箱
  email = models.EmailField(_('email address'), blank=True)
  
  #权限
  is_staff = models.BooleanField(
    _('staff status'),
    default=False,
    help_text=_('Designates whether the user can log into this admin site.'),
  )
  
  #激活
  is_active = models.BooleanField(
    _('active'),
    default=True,
    help_text=_(
      'Designates whether this user should be treated as active. '
      'Unselect this instead of deleting accounts.'
    ),
  )
  
  #日期
  date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

内置认证校验系统

django自带的用户认证校验系统较为简单,主要就是认证用户名密码的正确与否

首先要在settings里面配置

#使用自带的认证系统
AUTH_USER_MODEL = "user.User"

这是配合自带的用户类AbstractUser一起使用的

通常使用在类视图中的post方法校验用户登录等操作

在view中的具体代码如下

class LoginView(View):

  def get(self,request):
    #逻辑代码
    return render(request,'login.html')

  def post(self,request):
    # 获取前端传递过来的用户名和密码
    username = request.POST.get('username')
    pwd = request.POST.get('pwd')
    record = request.POST.get('record')
    # 进行数据校验
    if not all([username,pwd]):
      return HttpResponse('数据输入不完整')
    # 验证用户名和密码是否正确
    user = authenticate(username=username,password=pwd)
    return render(request,''index.html')

主要就是其中的user = authenticate(username=username,password=pwd)

两个参数都是拿到前端用户输入的信息

以上这篇Django User 模块之 AbstractUser 扩展详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python selenium 三种等待方式详解(必会)
Sep 15 Python
详解python中字典的循环遍历的两种方式
Feb 07 Python
python中数据爬虫requests库使用方法详解
Feb 11 Python
TensorFlow的权值更新方法
Jun 14 Python
python实现下载pop3邮件保存到本地
Jun 19 Python
Python实现序列化及csv文件读取
Jan 19 Python
python实现银行实战系统
Feb 26 Python
Python 格式化打印json数据方法(展开状态)
Feb 27 Python
Python中私有属性的定义方式
Mar 05 Python
jupyter notebook 调用环境中的Keras或者pytorch教程
Apr 14 Python
Python3.9 beta2版本发布了,看看这7个新的PEP都是什么
Jun 10 Python
python plt.plot bar 如何设置绘图尺寸大小
Jun 01 Python
pygame实现飞机大战
Mar 11 #Python
Django框架models使用group by详解
Mar 11 #Python
python检查目录文件权限并修改目录文件权限的操作
Mar 11 #Python
python 链接sqlserver 写接口实例
Mar 11 #Python
浅谈Python中range与Numpy中arange的比较
Mar 11 #Python
python读取当前目录下的CSV文件数据
Mar 11 #Python
python闭包、深浅拷贝、垃圾回收、with语句知识点汇总
Mar 11 #Python
You might like
php正则
2006/07/07 PHP
php获取网页内容方法总结
2008/12/04 PHP
php 保留小数点
2009/04/21 PHP
php常用Output和ptions/Info函数集介绍
2013/06/19 PHP
destoon整合ucenter后注册页面不跳转的解决方法
2014/06/21 PHP
php弹出提示框的是实例写法
2019/09/26 PHP
JQuery模板插件 jquery.tmpl 动态ajax扩展
2011/11/10 Javascript
jQuery计算textarea中文字数(剩余个数)的小程序
2013/11/28 Javascript
关注jquery技巧提高jquery技能(前端开发必学)
2015/11/02 Javascript
jQuery获取访问者IP地址的方法(基于新浪API与QQ查询接口)
2016/05/25 Javascript
jQueryUI DatePicker 添加时分秒
2016/06/04 Javascript
js实现导航吸顶效果
2017/02/24 Javascript
详解vue-cli项目中的proxyTable跨域问题小结
2018/02/09 Javascript
Node.js模块全局安装路径配置方法
2018/05/17 Javascript
vue中使用element ui的弹窗与echarts之间的问题详解
2019/10/25 Javascript
[01:28:24]NAVI vs VG Supermajor 败者组 BO3 第三场 6.5
2018/06/06 DOTA
[08:56]DOTA2-DPC中国联赛2月23日Recap集锦
2021/03/11 DOTA
python实现在目录中查找指定文件的方法
2014/11/11 Python
Python语言描述连续子数组的最大和
2018/01/04 Python
利用python提取wav文件的mfcc方法
2019/01/09 Python
Python datetime和unix时间戳之间相互转换的讲解
2019/04/01 Python
Django REST framework 如何实现内置访问频率控制
2019/07/23 Python
Python3 tkinter 实现文件读取及保存功能
2019/09/12 Python
python图形绘制奥运五环实例讲解
2019/09/14 Python
TensorFlow打印输出tensor的值
2020/04/19 Python
Python实现常见的几种加密算法(MD5,SHA-1,HMAC,DES/AES,RSA和ECC)
2020/05/09 Python
基于html和CSS3制作酷炫的导航栏
2015/09/23 HTML / CSS
美国求婚钻戒网站:Super Jeweler
2016/08/27 全球购物
英国网上超市:Ocado
2020/03/05 全球购物
eDreams德国:南欧领先的在线旅游公司
2020/12/07 全球购物
奉献家乡演讲稿
2014/09/13 职场文书
投资入股合作协议书
2014/10/28 职场文书
违纪学生保证书
2015/02/27 职场文书
2016年6月份红领巾广播稿
2015/12/21 职场文书
SQL Server #{}可以防止SQL注入
2022/05/11 SQL Server
MySQL中JOIN连接的基本用法实例
2022/06/05 MySQL