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调用java的Webservice示例
Mar 10 Python
MySQLdb ImportError: libmysqlclient.so.18解决方法
Aug 21 Python
Python中的自定义函数学习笔记
Sep 23 Python
python判断图片宽度和高度后删除图片的方法
May 22 Python
【Python】Python的urllib模块、urllib2模块批量进行网页下载文件
Nov 19 Python
python+selenium识别验证码并登录的示例代码
Dec 21 Python
python中将一个全部为int的list 转化为str的list方法
Apr 09 Python
sublime python3 输入换行不结束的方法
Apr 19 Python
对Python中type打开文件的方式介绍
Apr 28 Python
python使用opencv驱动摄像头的方法
Aug 03 Python
浅谈Python2之汉字编码为unicode的问题(即类似\xc3\xa4)
Aug 12 Python
python lambda 表达式形式分析
Apr 03 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写杨辉三角实例代码
2011/07/17 PHP
php中session使用示例
2014/03/29 PHP
php通过array_merge()函数合并两个数组的方法
2015/03/18 PHP
分享PHP源码批量抓取远程网页图片并保存到本地的实现方法
2015/12/01 PHP
一文掌握PHP Xdebug 本地与远程调试(小结)
2019/04/23 PHP
jQuery 行级解析读取XML文件(附源码)
2009/10/12 Javascript
JS 实现点击a标签的时候让其背景更换
2013/10/15 Javascript
JS对象转换为Jquery对象实现代码
2013/12/29 Javascript
简单的JavaScript互斥锁分享
2014/02/02 Javascript
js使用for循环查询数组中是否存在某个值
2014/08/12 Javascript
javascript中的this详解
2014/12/08 Javascript
JavaScript里四舍五入函数round用法实例
2015/04/06 Javascript
js兼容pc端浏览器并有多种弹出小提示的手机端浮层控件实例
2015/04/29 Javascript
跟我学习javascript的arguments对象
2015/11/16 Javascript
JavaScript 实现的 zip 压缩和解压缩工具包Zip.js使用详解
2015/12/14 Javascript
jquery分隔Url的param方法(推荐)
2016/05/25 Javascript
JS 通过系统时间限定动态添加 select option的实例代码
2016/06/09 Javascript
wap手机端解决返回上一页的js实例
2016/12/08 Javascript
php中and 和 &&出坑指南
2018/07/13 Javascript
vue+element搭建后台小总结 el-dropdown下拉功能
2020/04/10 Javascript
javascript sort()对数组中的元素进行排序详解
2019/10/13 Javascript
python数据库操作常用功能使用详解(创建表/插入数据/获取数据)
2013/12/06 Python
Python自动化测试Eclipse+Pydev 搭建开发环境
2016/08/15 Python
分析Python读取文件时的路径问题
2018/02/11 Python
利用Python代码实现数据可视化的5种方法详解
2018/03/25 Python
Pandas 数据处理,数据清洗详解
2018/07/10 Python
widows下安装pycurl并利用pycurl请求https地址的方法
2018/10/15 Python
python判断所输入的任意一个正整数是否为素数的两种方法
2019/06/27 Python
如何使用 Flask 做一个评论系统
2020/11/27 Python
利用纯css3实现的文字亮光特效的代码演示
2014/11/27 HTML / CSS
酒店实习个人鉴定
2013/12/07 职场文书
竟聘演讲稿范文
2013/12/31 职场文书
建设幸福中国演讲稿
2014/09/11 职场文书
交通事故和解协议书
2015/01/27 职场文书
试用期辞职信范文
2015/03/02 职场文书
土木工程生产实习心得体会
2016/01/22 职场文书