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中的赋值、浅拷贝、深拷贝介绍
Mar 09 Python
Python单元测试框架unittest使用方法讲解
Apr 13 Python
实例Python处理XML文件的方法
Aug 31 Python
Python实现读写sqlite3数据库并将统计数据写入Excel的方法示例
Aug 07 Python
Python中optparser库用法实例详解
Jan 26 Python
Python实现的字典排序操作示例【按键名key与键值value排序】
Dec 21 Python
简单了解python 邮件模块的使用方法
Jul 24 Python
tensorflow的计算图总结
Jan 12 Python
使用Python 自动生成 Word 文档的教程
Feb 13 Python
基于Python实现2种反转链表方法代码实例
Jul 06 Python
matplotlib绘制鼠标的十字光标的实现(内置方式)
Jan 06 Python
写一个Python脚本自动爬取Bilibili小视频
Apr 24 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
phpmyadmin显示utf8_general_ci中文乱码的问题终级篇
2013/04/08 PHP
PHP多线程批量采集下载美女图片的实现代码(续)
2013/06/03 PHP
PHP常见错误提示含义解释(实用!值得收藏)
2016/04/25 PHP
PHP 等比例缩放图片详解及实例代码
2016/09/18 PHP
thinkphp查询,3.X 5.0方法(亲试可行)
2017/06/17 PHP
利用PHP扩展Xhprof分析项目性能实践教程
2018/09/05 PHP
Javascript客户端将指定区域导出到Word、Excel的代码
2008/10/22 Javascript
jquery下操作HTML控件的实现代码
2010/01/12 Javascript
js本身的局限性 别让javascript做太多事
2010/03/23 Javascript
游览器中javascript的执行过程(图文)
2012/05/20 Javascript
jQuery设置与获取HTML,文本和值的简单实例
2014/02/26 Javascript
JS实现鼠标滑过链接改变网页背景颜色的方法
2015/10/20 Javascript
JavaScript数据存储 Cookie篇
2016/07/02 Javascript
如何用js实现鼠标向上滚动时浮动导航
2016/07/18 Javascript
微信小程序 页面跳转和数据传递实例详解
2017/01/19 Javascript
JS触摸与手势事件详解
2017/05/09 Javascript
彻底解决 webpack 打包文件体积过大问题
2017/07/07 Javascript
在 Angular 中使用Chart.js 和 ng2-charts的示例代码
2017/08/17 Javascript
Koa项目搭建过程详细记录
2018/04/12 Javascript
vue 双向数据绑定的实现学习之监听器的实现方法
2018/11/30 Javascript
vue通过数据过滤实现表格合并
2020/11/30 Javascript
react实现antd线上主题动态切换功能
2019/08/12 Javascript
微信小程序手动添加收货地址省市区联动
2020/05/18 Javascript
[01:42]TI4西雅图DOTA2前线报道 第一顿早饭哦
2014/07/08 DOTA
[02:14]2016国际邀请赛中国区预选赛Ehome晋级之路
2016/07/01 DOTA
使用tensorflow实现AlexNet
2017/11/20 Python
查看TensorFlow checkpoint文件中的变量名和对应值方法
2018/06/14 Python
python3调用百度翻译API实现实时翻译
2018/08/16 Python
Django-Model数据库操作(增删改查、连表结构)详解
2019/07/17 Python
世界顶级足球门票网站:Live Football Tickets
2017/10/14 全球购物
Blue Nile蓝色尼罗河香港官网:世界最大在线钻石珠宝销售商
2020/05/07 全球购物
机关会计岗位职责
2014/04/08 职场文书
理发店策划方案
2014/06/05 职场文书
国博复兴之路观后感
2015/06/02 职场文书
2015七夕情人节宣传语
2015/07/14 职场文书
父亲节感言
2015/08/03 职场文书