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和JavaScript间代码转换的4个工具
Feb 22 Python
Python制作刷网页流量工具
Apr 23 Python
分享一个简单的python读写文件脚本
Nov 25 Python
解决pycharm无法调用pip安装的包问题
May 18 Python
详解python单元测试框架unittest
Jul 02 Python
django的ORM操作 删除和编辑实现详解
Jul 24 Python
Python使用itchat 功能分析微信好友性别和位置
Aug 05 Python
python脚本实现音频m4a格式转成MP3格式的实例代码
Oct 09 Python
Python绘制二维曲线的日常应用详解
Dec 04 Python
Python Scrapy框架:通用爬虫之CrawlSpider用法简单示例
Apr 11 Python
scrapy处理python爬虫调度详解
Nov 23 Python
【超详细】八大排序算法的各项比较以及各自特点
Mar 31 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
Breeze 文章管理系统 v1.0.0正式发布
2006/12/14 PHP
PHP mail()函数使用及配置方法
2014/01/14 PHP
表单(FORM)的一些实用效果代码
2007/03/25 Javascript
javascript中关于break,continue的特殊用法与介绍
2012/05/24 Javascript
Javascript模拟加速运动与减速运动代码分享
2014/12/11 Javascript
jQuery中:checked选择器用法实例
2015/01/04 Javascript
nodejs中实现阻塞实例
2015/03/24 NodeJs
vuejs父子组件通信的问题
2017/01/11 Javascript
详解nodejs操作mongodb数据库封装DB类
2017/04/10 NodeJs
如何使用angularJs
2017/05/08 Javascript
详解探索 vuex 2.0 以及使用 vuejs 2.0 + vuex 2.0 构建记事本应用
2017/06/16 Javascript
Kindeditor单独调用单图上传增加预览功能的实例
2017/07/31 Javascript
js中json对象和字符串的理解及相互转化操作实现方法
2017/09/22 Javascript
基于webpack 实用配置方法总结
2017/09/28 Javascript
bootstrap 路径导航 分页 进度条的实例代码
2018/08/06 Javascript
使用js在layui中实现上传图片压缩
2019/06/18 Javascript
vue中用 async/await 来处理异步操作
2020/07/18 Javascript
使用grappelli为django admin后台添加模板
2014/11/18 Python
tensorflow更改变量的值实例
2018/07/30 Python
python 哈希表实现简单python字典代码实例
2019/09/27 Python
详解numpy矩阵的创建与数据类型
2019/10/18 Python
在Keras中CNN联合LSTM进行分类实例
2020/06/29 Python
使用Nibabel库对nii格式图像的读写操作
2020/07/01 Python
CSS3盒子模型详解
2013/04/24 HTML / CSS
HTML5 Canvas如何实现纹理填充与描边(Fill And Stroke)
2013/07/15 HTML / CSS
AmazeUI 图标的示例代码
2020/08/13 HTML / CSS
Armor Lux法国官方网站:水手服装、成衣和内衣
2020/05/26 全球购物
新加坡最早生产电动滑板车的制造商之一:FunsToTheFore
2020/09/08 全球购物
岗位廉洁从政承诺书
2014/03/27 职场文书
计算机专业应届生求职信
2014/04/06 职场文书
建筑工程造价专业自荐信
2014/07/08 职场文书
平安家庭事迹材料
2014/12/20 职场文书
违反纪律检讨书范文
2015/05/07 职场文书
信息技术研修心得体会
2016/01/08 职场文书
go web 预防跨站脚本的实现方式
2021/06/11 Golang
Mysql如何查看是否使用到索引
2022/12/24 MySQL