Django基础七之CBV装饰器和中间件


ttxdong
ttxdong 2022-09-21 09:15:50 53963
分类专栏: 资讯

Python微信订餐小程序课程视频

https://edu.csdn.net/course/detail/36074

Python实战量化交易理财系统

https://edu.csdn.net/course/detail/35475

Django基础七之CBV装饰器和中间件

目录* Django基础七之CBV装饰器和中间件
+ 1. CBV加装饰器
+ 2. Django中间件
- 2.1 Django中间件介绍
- 2.2 自定义中间件
- 2.2.1 自定义中间件
- 2.2.2 自定义中间件总结
- 2.2.3 其他中间件函数
- 2.3 新版本中间件写法
+ 3.Csrf中间件

1. CBV加装饰器

CBV加装饰器有三种方法,

案例:要求登录(不管get请求还是post请求)后才可以访问

HTML代码

index.html

html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>

head>
<body>

<div>
    <p>Hello Indexp>
div>

body>
html>

index.html")


    def post(self, request):
        print("post 请求")
        return HttpResponse("post")


def login(request):
    if request.method == "POST":
        name = request.POST.get("username")
        password = request.POST.get("password")
        if name == "hans" and password == "123":
            request.session['is\_login'] = True
            print("登录成功")

    return render(request, "login.html")


 CBV加装饰器方法三:

from django.shortcuts import render, HttpResponse, redirect

from django.views import View

from django.utils.decorators import method_decorator


 Create your views here.
 装饰器
def login\_auth(func):
    def inner(request, *args, **kwargs):
        if request.session.get("is\_login"):
            res = func(*args, **kwargs)
            return res
        else:
            return redirect('/login/')

    return inner

class Index(View):
    方法三 使用dispatch给所有的方法添加装饰器
 @method\_decorator(login\_auth)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get(self, request):
        print("get 请求")
        return render(request, "index.html")


    def post(self, request):
        print("post 请求")
        return HttpResponse("post")


def login(request):
    if request.method == "POST":
        name = request.POST.get("username")
        password = request.POST.get("password")
        if name == "hans" and password == "123":
            request.session['is\_login'] = True
            print("登录成功")

    return render(request, "login.html")


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140

urls.py

from django.contrib import admin
from django.urls import path

from wrapperMidd  import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.Index.as_view()),
    path('login/', views.login),
]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

访问地址:http://127.0.0.1:8000/index

get的请求使用POSTMAN工具

2. Django中间件

2.1 Django中间件介绍

中间件是 Django 请求/响应处理的钩子框架。它是一个轻量级的、低级的“插件”系统,用于全局改变 Django 的输入或输出。

每个中间件组件负责做一些特定的功能,Django中自带了七个中间件

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',    安全中间件,为请求/响应周期提供了若干安全增强功能。每一项都可以通过设置独立地启用或禁用。
    'django.contrib.sessions.middleware.SessionMiddleware',  启用会话支持
    'django.middleware.common.CommonMiddleware',  “通用”中间件
    'django.middleware.csrf.CsrfViewMiddleware',  CSRF 保护中间件,通过在 POST 表单中添加隐藏的表单字段,并检查请求的正确值,增加对跨站点伪造请求的保护。
    'django.contrib.auth.middleware.AuthenticationMiddleware',  验证中间件,将代表当前登录的用户的 user 属性添加到每个传入的 HttpRequest 对象中
    'django.contrib.messages.middleware.MessageMiddleware',  消息中间件,启用基于 cookie 和会话的消息支持
    'django.middleware.clickjacking.XFrameOptionsMiddleware',  X-Frame-Options 中间件,简单的 通过 X-Frame-Options 头的点击劫持保护。
]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

中间件(Middleware)在整个Djangorequest/response处理机制中的角色如下所示:

HttpRequest -> Middleware(request) -> View -> Middleware(response) -> HttpResponse

中间件常用于权限校验、限制用户请求、打印日志、改变输出内容等多种应用场景.而且中间件对Django的输入或输出的改变是全局的。

Django 中间件作用:

  • 修改请求,即传送到 view 中的 HttpRequest 对象。
  • 修改响应,即 view 返回的 HttpResponse 对象。

中间件执行顺序:

image

2.2 自定义中间件

中间件可以定义四个方法:

  • process_request(self,request)
  • process_view(self, request, view_func, view_args, view_kwargs)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

主要为process_requestprocess_response

2.2.1 自定义中间件

在应用目录下新建一个 py 文件,名字自定义。

在应用目录下创建myMiddle.py
myMiddle.py:

from django.utils.deprecation import MiddlewareMixin

class myMinddle(MiddlewareMixin):
    def process\_request(self, request):   在视图之前执行
        print("这是自定义中间件 请求1")

    def process\_response(self,request, response):  在视图之后执行
        print("这是自定义中间件 响应1")
        return response


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

把自定义的中间件注册到setting.pyMIDDLEWARE里面:

setting.py:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'wrapperMidd.myMinddle.myMinddle',   自定义中间件
]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

测试:

views.py:
    
from django.shortcuts import render, HttpResponse, redirect
def testMinddle(request):
    print("testMinddle")
    return HttpResponse("TEST")

urls.py:
    
from django.contrib import admin
from django.urls import path

from appName  import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('testMinddle/', views.testMinddle),
]

 访问:http://127.0.0.1:8000/testMinddle/
 结果:
"""
这是自定义中间件 请求1
testMinddle
这是自定义中间件 响应1
"""

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

增加两个自定义中间件,执行过程:

myMiddle.py:

from django.utils.deprecation import MiddlewareMixin

class myMinddle(MiddlewareMixin):
    def process\_request(self, request):
        print("这是自定义中间件 请求1")

    def process\_response(self,request, response):
        print("这是自定义中间件 响应1")
        return response


class myMinddle2(MiddlewareMixin):
    def process\_request(self, request):
        print("这是自定义中间件 请求2")

    def process\_response(self,request, response):
        print("这是自定义中间件 响应2")
        return response


setting.py:
MIDDLEWARE = [
    ......
    'wrapperMidd.myMinddle.myMinddle',
    'wrapperMidd.myMinddle.myMinddle2',
]

 访问:http://127.0.0.1:8000/testMinddle/
 结果
"""
这是自定义中间件 请求1
这是自定义中间件 请求2
testMinddle
这是自定义中间件 响应2
这是自定义中间件 响应1
"""

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

如果在第一个中间件直接返回,执行顺序如果:

myMiddle.py:

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class myMinddle(MiddlewareMixin):
    def process\_request(self, request):
        print("这是自定义中间件 请求1")
        return HttpResponse("request")   """在这里直接返回"""
    def process\_response(self,request, response):
        print("这是自定义中间件 响应1")
        return response


class myMinddle2(MiddlewareMixin):
    def process\_request(self, request):
        print("这是自定义中间件 请求2")

    def process\_response(self,request, response):
        print("这是自定义中间件 响应2")
        return response

 访问:http://127.0.0.1:8000/testMinddle/
 结果:
网页上显示:request
后台显示:
"""
这是自定义中间件 请求1
这是自定义中间件 响应1
"""


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

2.2.2 自定义中间件总结

  1. 自定义中间件先执行process_request再执行views.py里的视图函数,最后再执行process_response,而且process_response函数必须要返回 return response
  2. 如果有多个自定义中间件,则执行顺序按settings.py里自上而下执行,写在上面的先执行。执行顺序
自定义中间件1 process_request--->自定义中间件2 process_request-->视图函数-->自定义中间件2 process_response -->自定义中间件1 process_response

  • 1
  • 2
  1. 如果自定义中间件的process_request里有return返回,而这个中间件还是在上面,则它会执行自己定义的process_requestprocess_response,则视图函数和其他的中间件都不执行
  2. 如果自定义中间件的process_request里有return返回,而这个中间件上面还有其他的中间件,则会自上而下执行,执行到自定义中间件的process_request后就会执行process_response,则视图函数和它下面的中间件都不执行
MIDDLEWARE = [
    ...其他中间件...
    '自定义中间件1',
    '自定义中间件2',   自定义中间件2里使用return直接返回 
    '自定义中间件3',
]

执行顺序:
"""
其他中间件 process\_request --> 自定义中间件1 process\_request --> 自定义中间件2 process\_request --> 自定义中间件2 process\_response --> 自定义中间件1 process\_response -->其他中间件 process\_response
"""
视图函数和自定义中间件3是不执行的

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.2.3 其他中间件函数

process_view

process_view在process_request之后,路由转发到视图,执行视图之前执行。

process_view() 只在 Django 调用视图前被调用。它应该返回 None 或 HttpResponse 对象。如果它返回 None ,Django 将继续处理这个请求,执行任何其他的 process_view() ,然后执行相应的视图。如果它返回 HttpResponse 对象,Django 不会去影响调用相应的视图;它会将响应中间件应用到 HttpResponse 并返回结果。


函数定义:
process_view(request, view_func, view_args, view_kwargs)
request 是一个 HttpRequest 对象。
view_func 是一个 Django 将要使用的 Python 函数。(这是一个真实的函数对象,不是函数的名称);view_args 是一个用来传递给视图的位置参数列表,;
view_kwargs 是一个用来传递给视图的关键字参数字典。
view_args 和 view_kwargs 都不包含第一个视图参数 ( request )。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

process_exception

视图执行中发生异常时执行。

当视图引发异常时,Django 会调用 process_exception()。process_exception() 应该返回 None 或 HttpResponse 对象。如果它返回一个 HttpResponse 对象,模板响应和响应中间件将被应用且会将结果响应返回浏览器。否则,就会开始默认异常处理( default exception handling )。

再次,中间件在响应阶段会按照相反的顺序运行,其中包括 process_exception 。如果异常中间件返回一个响应,那么中间件之上的中间件类的 process_exception 方法根本不会被调用。

函数定义:
process_exception(request, exception)
request 是一个 HttpRequest 对象。 exception 是一个由视图函数引发的 Exception 对象。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

process_template_response

视图函数刚执行完毕,process_response之前执行。


process_template_response() 在视图被完全执行后调用,如果响应实例有 render() 方法,表明它是一个 TemplateResponse 或等效对象。

它必须返回一个实现了 render 方法的响应对象。它可以通过改变``response.template_name`` 和 response.context_data 来改变给定的 response ,或者它可以创建和返回全新的 TemplateResponse 或等效对象。

不需要显式地渲染响应——一旦所有模板中间件被调用,响应会被自动渲染。

中间件会在响应阶段按照相反的顺序运行,其中包括 process_template_response() 。


函数定义:
process_template_response(request, response)

request 是一个 HttpRequest 对象。
response 是 TemplateResponse 对象(或者等效对象),它通过 Django 视图或中间件返回。


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class myMinddle(MiddlewareMixin):
    def process\_request(self, request):
        print("这是自定义中间件 请求1")

    def process\_response(self,request, response):
        print("这是自定义中间件 响应1")
        return response

    def process\_view(self,request, view\_func, view\_args, view\_kwargs):
        print("视图函数之前执行")

    def process\_exception(self,request,exception):
        print("处理视图函数")
        
访问http://127.0.0.1:8000/testMinddle/
结果:
这是自定义中间件 请求1
视图函数之前执行
testMinddle
这是自定义中间件 响应1


 视图函数出错示例:
这是自定义中间件 请求1
视图函数之前执行
testMinddle
处理视图函数错误
这是自定义中间件 响应1

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

2.3 新版本中间件写法

官网上给的示例:

class SimpleMiddleware:
    def \_\_init\_\_(self, get\_response):
        self.get_response = get_response
         配置和初始化

    def \_\_call\_\_(self, request):
         在这里编写视图和后面的中间件被调用之前需要执行的代码,即process\_request()
        response = self.get_response(request)

         在这里编写视图调用后需要执行的代码,即process\_response()

        return response

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

案例:

使用官网上的写法不用继承 MiddlewareMixin

class SimpleMiddleware:
    def \_\_init\_\_(self, get\_response):
        self.get_response = get_response
         One-time configuration and initialization.

    def \_\_call\_\_(self, request):
         Code to be executed for each request before
         the view (and later middleware) are called.
        print("这是自定义中间件 SimpleMiddleware的请求")
        response = self.get_response(request)

         Code to be executed for each request/response after
         the view is called.
        print("这是自定义中间件 SimpleMiddleware的响应")

        return response

 执行结果:
这是自定义中间件 SimpleMiddleware的请求
testMinddle
这是自定义中间件 SimpleMiddleware的响应


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

注意

__init__(get_response)

中间件必须接受 get_response 参数。还可以初始化中间件的一些全局状态。记住两个注意事项:

  • Django仅用 get_response 参数初始化您的中间件,因此不能定义 __init__() ,因为需要其他参数。
  • 与每次请求都会调用 __call__() 方法不同,当 Web 服务器启动后,__init__() 只被调用一次

上面只定义了process_requestprocess_response 其中process_viewprocess_exception还是要写。

class SimpleMiddleware:
    def \_\_init\_\_(self, get\_response):
        self.get_response = get_response
       
    def \_\_call\_\_(self, request):

        print("这是自定义中间件 SimpleMiddleware的请求")
        response = self.get_response(request)
        
        print("这是自定义中间件 SimpleMiddleware的响应")

        return response

    def process\_view(self,request, view\_func, view\_args, view\_kwargs):
        print("视图函数之前执行")

    def process\_exception(self,request,exception):
        print("处理视图函数错误")

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

3.Csrf中间件

使用Django框架使用django.middleware.csrf.CsrfViewMiddleware中间件,在前端页面提交操作的时候,会报错:

Forbidden (403)
CSRF verification failed. Request aborted.

  • 1
  • 2
  • 3

解决方法:

如果使用form提交,则在前端页面里加入:
    {% csrf_token %}
如:

 
 {% csrf\_token %}
 username: 
 password:
 
 



如果是Ajax提交:
"""一定要导入jquery"""


 username: 
 password:
 



 $('btn').click(function (){
 $.ajax({
 url: "",
 method: "post",
 data: {username: $('user').val(), password: $('pwd').val(), csrfmiddlewaretoken: '{{csrf\_token}}'},

 success: function (data) {
 console.log(data)

 }
 })

 })




 使用cookie:
使用cookie 则要导入"""jquery.cookie.min.js"""


const csrftoken = $.cookie('csrftoken');

使用:


 username: 
 password:
 



 $('btn').click(function (){
 const csrftoken = $.cookie('csrftoken');
 $.ajax({
 url: "",
 headers:{'X-CSRFToken': csrftoken}, // 加请求头。
 method: "post",
 data: {username: $('user').val(), password: $('pwd').val()},
 success: function (data) {
 console.log(data)

 }
 })

 })





  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

全局使用csrf局部函数使用,或全局不使用,局部函数使用csrf

from django.views.decorators.csrf import csrf_exempt,csrf_protect
 全局使用,局部不使用
@csrf\_exempt
def xxx()

 全局不使用(禁用掉),局部使用
@csrf\_protect
def yyy()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
文章知识点与官方知识档案匹配,可进一步学习相关知识
Python入门技能树高级教程函数127519 人正在系统学习中

网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。

本文链接:https://www.xckfsq.com/news/show.html?id=8726
赞同 0
评论 0 条
ttxdongL2
粉丝 0 发表 7 + 关注 私信
上周热门
如何使用 StarRocks 管理和优化数据湖中的数据?  2959
【软件正版化】软件正版化工作要点  2878
统信UOS试玩黑神话:悟空  2843
信刻光盘安全隔离与信息交换系统  2737
镜舟科技与中启乘数科技达成战略合作,共筑数据服务新生态  1271
grub引导程序无法找到指定设备和分区  1235
华为全联接大会2024丨软通动力分论坛精彩议程抢先看!  165
点击报名 | 京东2025校招进校行程预告  164
2024海洋能源产业融合发展论坛暨博览会同期活动-海洋能源与数字化智能化论坛成功举办  163
华为纯血鸿蒙正式版9月底见!但Mate 70的内情还得接着挖...  159
本周热议
我的信创开放社区兼职赚钱历程 40
今天你签到了吗? 27
信创开放社区邀请他人注册的具体步骤如下 15
如何玩转信创开放社区—从小白进阶到专家 15
方德桌面操作系统 14
我有15积分有什么用? 13
用抖音玩法闯信创开放社区——用平台宣传企业产品服务 13
如何让你先人一步获得悬赏问题信息?(创作者必看) 12
2024中国信创产业发展大会暨中国信息科技创新与应用博览会 9
中央国家机关政府采购中心:应当将CPU、操作系统符合安全可靠测评要求纳入采购需求 8

加入交流群

请使用微信扫一扫!