day63

CBV添加装饰器的三种方式

一.给类方法加装饰器

指名道姓的装--放在方法上面

路由

path('login_view/', views.MyLogin.as_view()),

 需要导入一个模块

from django.utils.decorators import method_decorator

视图

from django.views import View
from django.utils.decorators import method_decorator

'''
CBV中Django不建议你直接给类方法加装饰器
无论该装饰器能否正常工作,都不建议加
'''

class MyLogin(View):
    @method_decorator(login_auth)
    def get(self, request):
        return HttpResponse("get 请求")

    @method_decorator(login_auth)
    def post(self, request):
        return HttpResponse("post 请求")

二.放在类上面

放在类的上面加装饰器,在参数内指向需要装饰的函数,可以指向多个类方法,针对不同的类方法指定不同的装饰器

from django.views import View
from django.utils.decorators import method_decorator

'''
CBV中Django不建议你直接给类方法加装饰器
无论该装饰器能否正常工作,都不建议加
'''
@method_decorator(login_auth,name='get')
@method_decorator(login_auth,name='post')
class MyLogin(View):

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


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

三、重写dispatch方法

在类中自定义dispatch方法,这种方法会个类中所有的方法都加上装饰器

from django.views import View
from django.utils.decorators import method_decorator

'''
CBV中Django不建议你直接给类方法加装饰器
无论该装饰器能否正常工作,都不建议加
'''
class MyLogin(View):
    @method_decorator(login_auth)
    def dispatch(self, request, *args, **kwargs):
        pass

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


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

Django中间件

1、什么是中间件

  • Django中间件是一个轻量级、可重用的组件,用于处理Django请求和响应的过程。

  • 它提供了对请求和响应进行全局处理的机制,可以在请求达到视图之前进行预处理或在响应返回给客户端之前进行后处理。

  • 中间件是按照顺序依次执行的,每个中间件都可以对请求和响应进行修改、补充或处理。

  • 在Django的settings.py配置文件中,通过MIDDLEWARE设置来定义中间件的顺序。

  • 请求发来的时候需要先经过中间件才能到达真正的Django后端
  • 响应返回的时候,最后也需要进过中间件返回发送出去

2、作用

  • 认证和授权:

    • 中间件可以在请求到达视图之前进行用户认证和权限验证,确保只有经过授权的用户才能访问敏感资源。
  • 请求和响应处理:

    • 中间件可以在请求到达视图之前对请求进行预处理

      • 例如添加请求头信息、检查请求参数的合法性等操作。
    • 同时,在视图函数返回响应给客户端之前,中间件还可以对响应进行后处理

      • 例如添加额外的响应头、包装响应数据等操作。
  • 异常处理:

    • 中间件还可以捕获视图函数中可能抛出的异常,并做相应的处理
      • 例如记录异常日志、返回自定义错误信息等。
  • 性能优化:

    • 通过中间件,可以对请求进行性能监测、缓存处理、压缩响应等操作,提升网站的整体性能。

3、示例

class MyMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # 在视图函数调用之前的预处理逻辑
        # ...

        response = self.get_response(request)

        # 在响应返回给客户端之前的后处理逻辑
        # ...

        return response

Django中间件源码分析 

1.SecurityMiddleware

  • django.middleware.security.SecurityMiddleware
    • 安全中间件负责处理与网站安全相关的任务
    • 例如设置HTTP头部,防止跨站脚本攻击(XSS),点击劫持等。
    • 它可以通过配置自定义安全策略来确保网站的安全性。

2. SessionMiddleware

  • django.contrib.sessions.middleware.SessionMiddleware
    • 会话中间件负责处理用户会话的创建之间存储和检索用户数据。
    • 它基于浏览器提供的Cookie或URL传递的会话ID进行会话跟踪,并将会话数据存储在后端数据库或缓存中,以实现用户状态的跨请求保持。

3. CommonMiddleware

  • django.middleware.common.CommonMiddleware
    • 通用中间件提供了一些常见而关键的HTTP请求处理功能
    • 例如,根据请求的HTTP头信息设置语言、时区等。
    • 此外,它还处理静态文件的serving,包括收集静态文件,为其生成URL,并在开发模式下提供静态文件的serving。

4. CsrfViewMiddleware

  • django.middleware.csrf.CsrfViewMiddleware
    • CSRF(Cross-Site Request Forgery)中间件用于防止跨站请求伪造攻击。
    • 它在每个POST请求中验证一个CSRF标记,确保请求是通过合法的表单提交得到的,从而保护用户免受恶意站点的攻击。

5. AuthenticationMiddleware

  • django.contrib.auth.middleware.AuthenticationMiddleware
    • 认证中间件负责处理用户身份认证相关的任务
    • 例如将认证信息关联到请求对象上,为每个请求提供一个user对象,以便在请求处理过程中轻松地获取和使用用户身份信息。

6.MessageMiddleware

  • django.contrib.messages.middleware.MessageMiddleware
    • 消息中间件用于在请求处理过程中存储和传递临时的、一次性的用户消息。
    • 它允许在HTTP重定向之间跨请求传递消息,例如成功或错误提示,以改善用户体验。

 7.XFrameOptionsMiddleware

  • django.middleware.clickjacking.XFrameOptionsMiddleware
    • 点击劫持中间件用于防止页面被嵌入到其他网站中,从而提供一定的点击劫持保护。
    • 它通过设置X-Frame-Options HTTP头部来限制页面的显示方式,从而防止恶意网页通过iframe等方式嵌入当前网页。

 中间件方法

1.process_request

(1)执行顺序

  • 请求来的时候需要经过每一个中间件的 process_request 方法
  • 结果的顺序是按照配置文件中注册的中间件从上往下的顺序执行的

(2)没有定义process_request

  • 如果没有定义这个方法,就跳过这个中间件

(3)定义了返回值

  • 如果在自定义中间件中定义了返回值(三板斧),那么请求将不再继续执行,而是直接原路返回(校验失败不允许访问)

(4)总结

  • process_request 方法就是用来 做全局相关的所有限制功能
  • 该方法在每个请求到达视图之前被调用,可以对请求进行预处理。
    • 例如,进行身份验证、访问控制或请求日志记录等操作。
  • 它接收一个HttpRequest对象作为参数,并且没有返回值
class AuthenticationMiddleware:
    def process_request(self, request):
        # 在这里进行身份验证操作
        if not request.user.is_authenticated:
            # 如果用户未经身份验证,则返回HttpResponse或重定向到登录页面

2.process_response

  • 响应被返回的时候需要结束每一个中间件里面的 process_response 方法

    • 该方法有两个额外的参数
      • request
      • response
  • 该方法必须返回 HttpResponse 对象

    • 默认是response
    • 支持自定义
  • 顺序是按照配置文件中注册过的中间件从下往上依次经过

    • 如果没有定义,则跳过,校验下一个
  • 该方法在每个请求结束并且响应返回到客户端之前被调用。
    • 可以在此处对响应进行处理
    • 例如添加额外的头信息、修改响应内容等。
  • 它接收一个HttpRequest对象和HttpResponse对象作为参数,并且必须返回一个HttpResponse对象。
class CustomResponseMiddleware:
    def process_response(self, request, response):
        # 在这里对响应进行处理
        response['X-Custom-Header'] = 'Custom Value'
        return response

3.process_view

  • 路由匹配成功后执行视图函数之前
  • 会自动执行中间件里面的该方法
  • 顺序是按照配置文件中注册的中间件从上而下的顺序执行
  • 该方法在请求到达视图之前被调用,在视图函数执行前执行。
    • 可以在此处进行一些操作
    • 如修改请求参数或进行记录等。
  • 它接收一个HttpRequest对象和一个视图函数作为参数,并且可以返回一个HttpResponse对象或None。
class LoggingMiddleware:
    def process_view(self, request, view_func, view_args, view_kwargs):
        # 在这里记录日志
        logger.info(f"Request received: {request.path}")
        # 返回None,继续执行原视图函数
        return None

4.process_template_response

  • 返回的 HttpResponse 对象有 render 属性的时候才会触发
  • 顺序是按照配置文件中注册了的中间件从下往上依次经过
  • 该方法在视图函数返回一个TemplateResponse对象时调用。
    • 可以在此处修改模板响应
    • 例如添加全局的上下文数据或进行额外的渲染操作。
  • 它接收一个HttpRequest对象和一个TemplateResponse对象作为参数,并且必须返回一个TemplateResponse对象
class GlobalContextMiddleware:
    def process_template_response(self, request, response):
        # 在这里添加全局的上下文数据
        response.context_data['global_data'] = "Global Value"
        return response

5.process_exception

  • 当视图函数中出现异常的情况下触发
  • 顺序是按照配置文件中注册了的中间件从下往上依次经过
  • 该方法在视图函数抛出异常时被调用。
    • 可以在此处捕获异常并进行处理
    • 例如返回一个定制的错误页面或进行日志记录等。
  • 它接收一个HttpRequest对象和一个异常对象作为参数,可以返回一个HttpResponse对象来替代原始的异常响应。
class ErrorHandlerMiddleware:
    def process_exception(self, request, exception):
        # 在这里处理异常
        if isinstance(exception, CustomException):
            # 如果自定义异常,返回一个定制的错误页面
            return render(request, 'error.html', {'error': str(exception)})
        else:
            # 默认情况,返回一个500服务器错误
            return HttpResponseServerError("Internal Server Error")

自定义中间件

1.process_request

路由层

from app01 import views

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

视图层

def index(request):
    print("这是视图函数index")
    return HttpResponse("index 的返回值")

配置文件

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',
    # 注册自己的中间件(在应用下创建路径会有提示,但是如果在项目下创建就没有提示,需要自己根据路径书写)
    'app01.mymiddle.my_middle.MyMiddle',
    # 谁先注册就先执行谁
    'app01.mymiddle.my_middle.MyMiddle2',
]

自定义中间件

# -*-coding: Utf-8 -*-
# @File : my_middle .py
# author: Chimengmeng
# blog_url : https://www.cnblogs.com/dream-ze/
# Time:2023/7/17

# 引入父类
from django.utils.deprecation import MiddlewareMixin


class MyMiddle(MiddlewareMixin):
    def process_request(self, request):
        print("这是第一个自定义中间件中的 process_request 方法")

class MyMiddle2(MiddlewareMixin):
    def process_request(self, request):
        print("这是第二个自定义中间件中的 process_request 方法")

总结

1、执行顺序
请求来的时候需要经过每一个中间件的process_request方法
结果顺序是按照配置文件中注册的中间件从上往下的顺序执行的

2、没有定义process_request
如果没有定义这个方法,就跳过这个中间件

3、定义了返回值
如果在自定义中间件定义了返回值(三板斧),那么请求将不再继续执行,而是直接原路返回(校验失败不允许访问)

4、总结
process_request方法就是用来做全局相关的所有限制功能

2、process_response 

# 引入父类
from django.utils.deprecation import MiddlewareMixin


class MyMiddle(MiddlewareMixin):
    def process_request(self, request):
        print("这是第一个自定义中间件中的 process_request 方法")

    def process_response(self, request, response):
        '''
        
        :param request: 
        :param response: 就是Django返回给浏览器的内容
        :return: 
        '''
        print("这是第一个自定义中间件中的 process_response 方法")
        # 必须返回 responser
        return response
  • 响应被返回的时候需要结束每一个中间件里面的 process_response 方法

    • 该方法有两个额外的参数
      • request
      • response
  • 该方法必须返回 HttpResponse 对象

    • 默认是response
    • 支持自定义
  • 顺序是按照配置文件中注册过的中间件从下往上依次经过

    • 如果没有定义,则跳过,校验下一个

小结

你可能感兴趣的:(django)