前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python进阶35-Django Auth组件

Python进阶35-Django Auth组件

作者头像
DriverZeng
发布2022-09-26 13:51:54
5280
发布2022-09-26 13:51:54
举报
文章被收录于专栏:Linux云计算及前后端开发

-曾老湿, 江湖人称曾老大。


-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。


什么是Auth模块


介绍

Auth模块是Django自带的用户认证模块:

我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。

Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统--auth,它默认使用 auth_user 表来存储用户数据。

auth模块用法


创建项目

数据库迁移

代码语言:javascript
复制
MacBook-pro:auth_module driverzeng$ python3 manage.py makemigrations
MacBook-pro:auth_module driverzeng$ python3 manage.py migrate

这个表里的用户,不能直接往里面写,得使用命令,还是运行manage.py

代码语言:javascript
复制
# 创建超级用户
MacBook-pro:auth_module driverzeng$ python3 manage.py createsuperuser


模板层

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <div>
        <lable>用户:<input type="text" name="name"></lable>
    </div>
    <div>
        <lable>密码:<input type="text" name="pwd"></lable>
    </div>
    <input type="submit" value="登录">
</form>
</body>
</html>

视图层

代码语言:javascript
复制
from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
from django.contrib import auth
def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        user = auth.authenticate(request,username=name,password=pwd)
        ## 相当于:user = models.User.objects.filter(name=name,pwd=pwd).first()
        if user:
            return HttpResponse('登录成功')
        else:
            return HttpResponse('用户名或密码错误')

路由层

代码语言:javascript
复制
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
]

Auth模块功能详解


登录

代码语言:javascript
复制
from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
from django.contrib import auth
def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        user = auth.authenticate(request,username=name,password=pwd)
        ## 相当于:user = models.User.objects.filter(name=name,pwd=pwd).first()
        if user:
            # 登录,其实就是把用户的信息放到session中
            auth.login(request,user)
            ## 之前是这样 request.session['name'] = name
            return HttpResponse('登录成功')
        else:
            return HttpResponse('用户名或密码错误')


取出当前登陆用户

只要登录成功,之后在任意视图,都可以取出该用户,这个功能太强大了,省了我们很多事

代码语言:javascript
复制
def test(request):
    user=request.user
    print(user)
    return HttpResponse('当前登录的用户:%s' % user)
代码语言:javascript
复制
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^test/', views.test),
]

如果没有登录就会是一个匿名用户:AnonymousUser


注销

代码语言:javascript
复制
def user_logout(request):
    auth.logout(request)
    user = request.user
    return HttpResponse('注销 [%s] 成功' %user)
代码语言:javascript
复制
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^test/', views.test),
    url(r'^user_logout/', views.user_logout),
]


登录认证装饰器

目前 我有个test页面,不管用户有没有登录都可以访问,因为没有登录的时候,可以用匿名用户访问,Django内置了一个登录认证的装饰器,如果没有登录,或者是匿名用户,可以跳转到指定的页面

模板层

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
    <meta charset="UTF-8">
    <title>个人中心</title>
</head>
<body>
当前登录用户:{{ user }}
<div>
    <a href="/user_logout/">点我注销</a>
</div>
</body>
</html>

视图层

代码语言:javascript
复制
from django.shortcuts import render, HttpResponse, redirect
from django.contrib.auth.decorators import login_required
# Create your views here.
from django.contrib import auth


def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    elif request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        user = auth.authenticate(request, username=name, password=pwd)
        ## 相当于:user = models.User.objects.filter(name=name,pwd=pwd).first()
        if user:
            # 登录,其实就是把用户的信息放到session中
            auth.login(request, user)
            ## 之前是这样 request.session['name'] = name
            return redirect('test')
        else:
            return HttpResponse('用户名或密码错误')


@login_required(redirect_field_name='zls', login_url='/login/')
def test(request):
    user = request.user
    print(user)
    return render(request,'test.html',locals())


def user_logout(request):
    user = request.user
    auth.logout(request)
    return redirect('/login/')

路由层

代码语言:javascript
复制
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^test/', views.test),
    url(r'^user_logout/', views.user_logout),
]

代码语言:javascript
复制
## 导入装饰器:from django.contrib.auth.decorators import login_required
## redirect_field_name 修改url的?后面传递的参数
## login_url 如果没有登录,跳转到页面

但是如果装饰器需要传递参数,如果有一万个视图函数,我就要传递一万次参数?很麻烦,所以Django帮我们做了一件事,settings文件中,修改即可。

代码语言:javascript
复制
LOGIN_URL = '/login/'
代码语言:javascript
复制
from django.shortcuts import render, HttpResponse, redirect
from django.contrib.auth.decorators import login_required
# Create your views here.
from django.contrib import auth


def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    elif request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        user = auth.authenticate(request, username=name, password=pwd)
        ## 相当于:user = models.User.objects.filter(name=name,pwd=pwd).first()
        if user:
            # 登录,其实就是把用户的信息放到session中
            auth.login(request, user)
            ## 之前是这样 request.session['name'] = name
            return redirect('/test/')
        else:
            return HttpResponse('用户名或密码错误')


@login_required()
def test(request):
    user = request.user
    print(user)
    return render(request,'test.html',locals())


def user_logout(request):
    user = request.user
    auth.logout(request)
    return redirect('/login/')

用户注册

代码语言:javascript
复制
from django.shortcuts import render, HttpResponse, redirect
from django.contrib.auth.decorators import login_required
# Create your views here.
from django.contrib import auth

def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    elif request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        user = auth.authenticate(request, username=name, password=pwd)
        ## 相当于:user = models.User.objects.filter(name=name,pwd=pwd).first()
        if user:
            # 登录,其实就是把用户的信息放到session中
            auth.login(request, user)
            ## 之前是这样 request.session['name'] = name
            return redirect('/test/')
        else:
            return HttpResponse('用户名或密码错误')


@login_required()
def test(request):
    user = request.user
    print(user)
    return render(request,'test.html',locals())


def user_logout(request):
    user = request.user
    auth.logout(request)
    return redirect('/login/')

from django.contrib.auth.models import User

def register(request):
    name='cls'
    pwd='123'
    ## 不能这么创建:密码不能是明文的
    ## user = User.objects.create(username=name,password=pwd)

    ## 创建超级用户
    #user = User.objects.create_superuser(username=name,password=pwd)
    ## 创建普通用户
    user = User.objects.create_user(username=name,password=pwd)
    return HttpResponse('用户:%s 注册成功' %user)
代码语言:javascript
复制
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^test/', views.test),
    url(r'^user_logout/', views.user_logout),
    url(r'^register/', views.register),
]


校验密码

因为密码是加密的,所以我们不能直接拿出来,还得用Django给我们写的方法。

代码语言:javascript
复制
def check_pwd(request):
    pwd = '123'
    res = request.user.check_password(pwd)
    print(res)
    if res:
        return HttpResponse('密码校验成功')
    else:
        return HttpResponse('密码校验失败')
代码语言:javascript
复制
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^test/', views.test),
    url(r'^user_logout/', views.user_logout),
    url(r'^register/', views.register),
    url(r'^check_pwd/', views.check_pwd),
]

zls用户的密码是:zls12345

代码语言:javascript
复制
def check_pwd(request):
    pwd = 'zls12345'
    res = request.user.check_password(pwd)
    print(res)
    if res:
        return HttpResponse('密码校验成功')
    else:
        return HttpResponse('密码校验失败')


修改密码

代码语言:javascript
复制
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^test/', views.test),
    url(r'^user_logout/', views.user_logout),
    url(r'^register/', views.register),
    url(r'^check_pwd/', views.check_pwd),
    url(r'^set_pwd/', views.set_pwd),
]
代码语言:javascript
复制
def set_pwd(request):
    pwd = 'zls111'
    user = request.user
    user.set_password(pwd)
    user.save()
    return HttpResponse('OK')

注意:修改密码一定要 调用save方法,否则不保存。


是否认证通过

代码语言:javascript
复制
def auth_1(request):
    res = request.user.is_authenticated
    print(res)
    
    if res:
        return HttpResponse('认证成功')
    else:
        return HttpResponse('认证失败')
代码语言:javascript
复制
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^test/', views.test),
    url(r'^user_logout/', views.user_logout),
    url(r'^register/', views.register),
    url(r'^check_pwd/', views.check_pwd),
    url(r'^set_pwd/', views.set_pwd),
    url(r'^auth_1/', views.auth_1),
]

该方法,主要不是在视图使用,是在模板中使用。


封号和后台管理

is_staff : 用户是否拥有网站的管理权限.

is_active : 是否允许用户登录, 设置为 False,可以在不删除用户的前提下禁止用户登录。

扩展默认的auth_user表

这内置的认证系统这么好用,但是auth_user表字段都是固定的那几个,我在项目中没法拿来直接使用啊!

比如,我想要加一个存储用户手机号的字段,怎么办?

聪明的你可能会想到新建另外一张表然后通过一对一和内置的auth_user表关联,这样虽然能满足要求但是有没有更好的实现方式呢?

答案是当然有了。

我们可以通过继承内置的 AbstractUser 类,来定义一个自己的Model类。

这样既能根据项目需求灵活的设计用户表,又能使用Django强大的认证系统了。

两种方式,复用User表


一对一关联auth_user表

代码语言:javascript
复制
from django.db import models

# Create your models here.
from django.contrib.auth.models import User
class UserDetail(models.Model):
    phone = models.CharField(max_length=32)

    # 如果是从外部引入的表模型是不能加 引号的
    #user = models.OneToOneField(to='User')
    user = models.OneToOneField(to=User)

数据库迁移

代码语言:javascript
复制
MacBook-pro:~ driverzeng$ cd /Users/driverzeng/PycharmProjects/auth_module
MacBook-pro:auth_module driverzeng$ python3 manage.py makemigrations
MacBook-pro:auth_module driverzeng$ python3 manage.py migrate


定义表模型继承

代码语言:javascript
复制
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
    """
    用户信息表
    """
    nid = models.AutoField(primary_key=True)
    phone = models.CharField(max_length=11, null=True, unique=True)
    
    def __str__(self):
        return self.username

注意:

按上面的方式扩展了内置的auth_user表之后,一定要在settings.py中告诉Django,我现在使用我新定义的UserInfo表来做用户认证。写法如下:

代码语言:javascript
复制
# 引用Django自带的User表,继承使用时需要设置
AUTH_USER_MODEL = "app01.UserInfo"

再次注意:

一旦我们指定了新的认证系统所使用的表,我们就需要重新在数据库中创建该表,而不能继续使用原来默认的auth_user表了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-04-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是Auth模块
  • auth模块用法
  • Auth模块功能详解
  • 扩展默认的auth_user表
相关产品与服务
数据传输服务
腾讯云数据传输服务(Data Transfer Service,DTS)可帮助用户在业务不停服的前提下轻松完成数据库迁移上云,利用实时同步通道轻松构建高可用的数据库多活架构,通过数据订阅来满足商业数据挖掘、业务异步解耦等场景需求。同时,DTS 还提供私有化独立输出版本 DTS-DBbridge,支持异构数据库和同构数据库之间迁移和同步,可以帮助企业实现完整数据库迁移(如 Oracle)。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档