19 Django之Auth模块

261次阅读
没有评论

共计 7172 个字符,预计需要花费 18 分钟才能阅读完成。

引入

我们在开发一个网页的时候, 无可避免的需要设计实现网站的用户系统; 此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能, 为了节省这个麻烦的过程, Django 自带了强大的用户认证系统 Auth, 它默认使用auth_user 表来存储用户的数据

ps : auth 本质上也是一个 app

一.Auth 模块的使用于字段

1. 先导入 auth 模块

form django.contrib import auth 

2. 进行数据迁移命令来生成 auth_user 表

python3 manage.py makemigrations
python3 manage.py migrate

3.auth_user 表字段

  • auth_user 默认有 11 个字段

19 Django 之 Auth 模块

字段 释义
id ID
password 密码
last_login 最后登录时间
is_superuser 是否是管理员
username 用户名
first_name
last_name
email 邮箱
is_staff 是否是工作人员
is_active 是否激活
date_joined 创建时间

二. 常用方法

1.authenticated : 登入认证

  • 作用 : 提供了用户认证功能,即验证用户名以及密码是否正确
  • 必须传入两个参数 : username & password

  • 校验成功返回 True, 校验失败返回 None

  • request 可以不用传, 默认就是 None
from django.contrib import auth

user_obj = auth.authenticated(request, username=username, password=password)
if user_obj:
    print(user_obj.username)
    print(user_obj.password)
else:
    print('校验失败')

2.login : 保存用户状态

  • 作用 : 该函数接收一个 HttpRequest 对象,以及一个经过认证的 User 对象
  • 实现一个用户登录的功能, 本质上会在后端为该用户生成相关 session 数据存在 session 表中
  • 只要执行了该方法 你就可以在任何地方通过 request.user 获取到当前登陆的用户对象, 否则拿到的是一个匿名用户对象
# 登入成功后调用
auth.login(request, user_obj)   # 内部调用的就是 request.session['key']=user_obj

3.logout : 退出登入

  • 作用 : 该函数接受一个 HttpRequest 对象,无返回值
  • 当调用该函数时, 当前请求的 session 信息会全部清除; 该用户即使没有登录, 使用该函数也不会报错
# 注销当前登录用户:
auth.logout(request)  # 内部使用的就是 request.session.flush()

4.is_authenticated : 判断用户是否登入

  • 用来判断当前请求是否通过了认证
# 视图类中使用
if not request.user.is_authenticated():
    print('未登入, 请先登入')

# 模板中使用
{% if request.user.is_authenticated %}
    {{request.user.username}} 欢迎回家
{% else %}
    <a href="/auth_login/"> 请去登录 </a>
{% endif %}

5.login_required : 登入认证装饰器

  • 作用 : 一个装饰器工具, 用来快捷的给某个视图添加登录校验
# 使用方式一 : 直接在视图函数上添加
@login_required(login_url='/login/')  # 需要指定 url(因为它存在默认 url)
def logout_func(request):
    auth.logout(request)
    return redirect("/login/")

# 使用方式二 : 在配置文件中全局配置
LOGIN_URL = '/login/'

6.create_user : 创建普通用户

  • 作用 : 提供的一个创建新用户的方法, 需要提供必要参数 username & password 等
from django.contrib.auth.models import User

user = User.objects.create_user(username='用户名',password='密码',email='邮箱',...)

7.create_superuser : 创建管理员用户

  • 作用 : 提供的一个创建管理员用户的方法, 需要提供必要参数 username & password & email
from django.contrib.auth.models import User
user = User.objects.create_superuser(username='用户名',password='密码',email='邮箱',...)

8.check_password : 检验密码

  • 作用 : 提供的一个检查密码是否正确的方法, 需要提供当前请求用户的密码
  • 密码正确返回 True, 否则返回 False
if user.check_password('[你的密码]'):
    print('ok')

9.set_password : 修改密码

  • 作用 : 提供的一个修改密码的方法, 接收要设置的新密码作为参数

  • 设置完一定要调用用户对象的 save 方法

user.set_password(password='[新密码]')
user.save()  # 保存

三. 补充 User 对象属性

User.username  # 获取用户名
User.password  # 获取密码   

User.is_staff  # 判断用户是否拥有网站的管理权限, 如果没有, 后台 admin 登录不进去

User.is_active  # 判断是否允许用户登录, 设置为 False, 可以在不删除用户的前提下禁止用户登录

User.is_superuser  # 判断是否是超级管理员

四. auth_user 表扩展字段

auth_user 中的字段有限, 想要在 auth_user 表中添加新的字段, 我们可以对其进行扩展

1. 扩展方式一 : 建立一对一外键关系

  • 新建一个模型类, 比如要添加 Phone 字段, 在该模型内中写入, 并添加 User 的外键字段
from django.contrib.auth.models import User 
class user_detail(models.Model):
    user=models.OneToOneField(to='User')
    phone=models.CharField(max_length=32)

2. 扩展方式二 : 继承 AbstractUser 类来扩写 (步骤)

  • 首先大前提是没有生成 auth_user 表(也就是没进行数据库迁移操作)(有的话需要删干净迁移记录和表)
  • 书写一个类, 并继承 AbstractUser
  • 在类中可以书写你需要扩展的字段, 也可以重写原来的字段
class MyAuthUser(AbstractUser):
    username=models.CharField(max_length=12)  # 重写字段
    phone=models.CharField(max_length=32)     # 书写新字段
  • 到 setting.py 配置文件中设置 AUTH_USER_MODEL 参数, 不然报错
AUTH_USER_MODEL = "[app 名].[类名]"
AUTH_USER_MODEL = "app01.MyAuthUser"  # 示例
  • 最后进行数据库迁移命令
python3 manage.py makemigrations
python3 manage.py migrate

3. 如果 auth_user 表已经存在

  • 先删库
  • 并清空项目中所有的 makemigrations 而来的迁移记录
  • 再清空源码中 admin,auth 俩 app 的 makemigrations 产生的记录

五. 基于 Auth 模块示例

1. 需求

  • 基于 auth 继承 AbstractUser 类,加一个 phone 字段(也可以加多其它)
  • 实现用户的注册登录,登录成功,在 home 页面显示用户名,未登录,则跳转登入界面
  • 超级管理员能够禁用户登录, 实现用户退出功能

2. 代码示例

  • 扩写 auth_user 表
from django.db import models
from django.contrib.auth.models import AbstractUser

class AuthUser(AbstractUser):
    phone = models.CharField(max_length=32)  # 电话
    is_display = models.BooleanField(default=False)  # 自定义的用户是否锁定
  • 路由层 urls.py 文件
from django.contrib import admin
from django.urls import path,re_path
from app01 import views
urlpatterns = [path('admin/', admin.site.urls),
    path('login/', views.login_auth),
    path('register/', views.register),
    path('home/', views.home),
    path('logout/', views.logout_func,name='logout_name'),
    path('admin_user/', views.admin_func,name='admin_name'),
    re_path('^lock/', views.lock,name='lock_name'),
    re_path('^unlock/', views.unlock,name='unlock_name'),
]
  • 视图层 views.py 文件
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from app01.models import AuthUser
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator


# 登入
def login_auth(request):
    if request.method == "GET":
        return render(request, 'login.html')
    if request.method == "POST":
        name = request.POST.get('name')
        passwd = request.POST.get('passwd')
        res = AuthUser.objects.filter(username=name).first()
        if res:
            user_obj = auth.authenticate(request, username=name, password=passwd)
            if user_obj:
                # 判断是否是锁定状态
                if user_obj.is_display:
                    auth.login(request, user_obj)
                    goto_url = request.GET.get('goto')
                    if goto_url:
                        return JsonResponse({'url': goto_url})
                    else:
                        return JsonResponse({'url': '/home/'})
                return JsonResponse({'tag': 100, 'error': '用户被锁定, 请联系管理员'})
            return JsonResponse({'tag': 100, 'error': '密码错误'})
        return JsonResponse({'tag': 100, 'error': '该用户未注册'})

# 注册
def register(request):
    if request.method == 'GET':
        return render(request, 'register.html')
    elif request.method == "POST":
        name = request.POST.get('name')
        passwd = request.POST.get('passwd')
        re_passwd = request.POST.get('re_passwd')
        phone = request.POST.get('phone')
        res = AuthUser.objects.filter(username=name).first()
        # 判断是否存在该用户
        if not res:
            if passwd == re_passwd:
                user = AuthUser.objects.create_user(username=name, password=passwd, phone=phone, is_display=True)
                success = {'tag': 200, 'name': f" 用户名 : {name}"}
                return JsonResponse(success)
            else:
                info = {'tag': 400, 'error': '两次密码不一致'}
                return JsonResponse(info)
        return JsonResponse({'tag': 400, 'error': '用户名已存在'})

# home 页面
@login_required(login_url='/login/')
def home(request):
    if request.method == "GET":
        name = request.user.username
        return render(request, "home.html", locals())

# 注销登入
@login_required(login_url='/login/')
def logout_func(request):
    auth.logout(request)
    return redirect("/login/")

# admin 页面
@login_required(login_url='/login/')
def admin_func(request):
    if request.method == "GET":
        return render(request, 'admin_user.html')

# 分页模板
@login_required(login_url='/login/')
def admin_func(request):
    # 🔰1. 分页后的 paginator 对象
    current_page = int(request.GET.get('page_num', 1))  # 获取用户点击的页码, 没有则默认第一页
    shop_list = AuthUser.objects.all()  # 获取所有的商品对象列表
    paginator = Paginator(shop_list, 5)

    # 🔰2. 页码列表
    if paginator.num_pages > 9:
        if current_page - 4 < 1:
            page_range = range(1, 10)
        elif current_page + 4 > paginator.num_pages:            page_range = range(paginator.num_pages - 8, paginator.num_pages + 1)
        else:
            page_range = range(current_page - 4, current_page + 4)
    else:
        page_range = paginator.page_range

    # 🔰3.page 对象
    try:
        page = paginator.page(current_page)
    except Exception as E:
        page = paginator.page(current_page)

    return render(request, 'admin_user.html', {'page_range': page_range, 'page': page, 'current_page': current_page})

# 加锁
def lock(request):
    if request.method == "POST":
        nid = request.POST.get('nid')
        print(nid)
        # 判断是否是管理员
        if request.user.is_superuser:
            if request.user.username == AuthUser.objects.filter(id=nid).first().username:
                return JsonResponse({'tag': 100, 'info': '不能锁定自己'})
            else:
                AuthUser.objects.filter(id=nid).update(is_display=False)
                return JsonResponse({'tag': 101, 'info': '锁定成功'})
        data = {'tag': 100, 'info': '你不是管理员用户'}
        return JsonResponse(data)

# 解锁
def unlock(request):
    if request.method == "POST":
        nid = request.POST.get('nid')
        print(nid)
        if request.user.is_superuser:
            AuthUser.objects.filter(id=nid).update(is_display=True)
            return JsonResponse({'tag': 101, 'info': '解锁成功'})
        return JsonResponse({'tag': 100, 'info': '你不是管理员用户'})

3. 效果展示

  • 注册密码 失败 & 成功

19 Django 之 Auth 模块

  • 登入 失败 & 成功

19 Django 之 Auth 模块

  • 超级管理员进行锁定以及解锁, 非管理员无法进行操作

19 Django 之 Auth 模块

正文完
 
shawn
版权声明:本站原创文章,由 shawn 2023-06-16发表,共计7172字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)