Django中间件理解及相关操作

本文深入探讨Django中间件的工作原理,包括中间件方法及其执行顺序。解析了process_request、process_response、process_view、process_exception和process_template_response五个关键方法的作用。并通过自定义中间件示例,展示了如何实现用户登录验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

中间件方法及执行顺序

中间件五个方法:

1)process_request:不能有返回值,若在process_request有返回值,那么下面的中间件将不会执行,后面的URL以及视图函数也不会执行,直接执行当前的中间件的process_response方法。
2)process_response:默认情况下返回response, 即视图函数的返回值,如果在这个方法中自定义了返回值,将返回自定义返回值。
3)process_view:这个方法的调用时机在 Django 执行完 request 预处理函数并确定待执行的 view (即callback参数)之后,但在 view 函数实际执行之前。
4)process_exception:这个方法只有在 request 处理过程中出了问题并且view 函数抛出了一个未捕获的异常时才会被调用。这个钩子可以用来发送错误通知,将现场相关信息输出到日志文件,或者甚至尝试从错误中自动恢复。
5)process_template_response:默认不执行,只有在视图函数的返回结果对象中有render方法才会执行,并把对象的render方法的返回值返回给用户(注意不返回视图函数的return的结果了,而是返回视图函数 return值(对象)中rende方法的结果)

中间件执行顺序

1)在app创建middleware.py文件自定义中间件,在settings中注册

from django.utils.deprecation import MiddlewareMixin

class CustomizeMiddleware1(MiddlewareMixin):
    def process_request(self, request):
        print("中间件1请求")
    def process_response(self, request, response):
        print("中间件1返回")
        return response
    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("中间件1view")

class CustomizeMiddleware2(MiddlewareMixin):
    def process_request(self, request):
        print("中间件2请求")
    def process_response(self, request, response):dd
        print("中间件2返回")
        return response
    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("中间件2view")

如下图,由此可见中间件执行顺序,按照中间件的注册顺序依次往下,然后再反向。
在这里插入图片描述
在这里插入图片描述

自定义中间件验证登录

1)了解中间件之后可以编写中间件验证用户是否有权限或者登录,就没必要在每个视图函数去判断是否有权限。

# 登录
class LoginView(View):
    def get(self, request):
        form = LoginForm()
        if request.user.is_authenticated:
            return HttpResponseRedirect('/')
        return render(request, 'login.html', {'form': form})

    def post(self, request):
        form = LoginForm(request.POST)
        if form.is_valid():
            data = form.cleaned_data
            user = check(data['username'], data['password'])
            request.session['user'] = data['username']  # 在这里存user
            if user is not None:
                if user is not False:
                    login(request, user)
                    return HttpResponseRedirect('/')
                else:
                    return render(request, 'login.html', {'form': form, 'msg': '密码错误'})
            else:
                return render(request, 'login.html', {'form': form, 'msg': '账户不存在'})
        return render(request, 'login.html', {'form': form})

# 中间件
class LoginMiddleware(MiddlewareMixin):
    white_list = ['/login/', '/users/register/']  # 白名单
    black_list = ['/tourial/contact/', ]  # 黑名单 (测试)

    def process_request(self, request):
        print("中间件login验证请求")
        next_url = request.path_info  # 将要请求的url
        # print(request.path_info, request.get_full_path())
        user = request.session.get("user")  # 获取session里的user
        if next_url in self.white_list or user:  # 判断url是否在白名单或者session里是否存在user
            # print(user) 
            return None  # 是的话直接返回None
        elif next_url in self.black_list:  # 如果存在于黑名单 直接返回HttpResponse
            return HttpResponse('This is an illegal URL')
        else:
            return redirect("/login/?next={}".format(next_url))  # 都不是直接跳转到login界面

    def process_response(self, request, response):
        print("中间件login验证返回")
        return response

LoginMiddleware中间件注册后,所有的请求都要走LoginMiddleware的process_request方法;

访问的URL在白名单内或者session中有user用户名,则不做阻拦走正常流程;

如果URL在黑名单中,则返回报错的字符串;

正常的URL但是需要登录后访问,让浏览器跳转到登录页面。

注:中间件中需要session,所以LoginMiddleware注册的位置要在session中间的下方。

也能在中间件中设置限制IP,前面也说了中间件的执行顺序是按照注册的顺序

# X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,
# 只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项。

def get_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]  # 所以这里是真实的ip
    else:
        ip = request.META.get('REMOTE_ADDR')  # 这里获得代理ip
    return ip

class CustomizeMiddleware(MiddlewareMixin):
    def process_request(self, request, response):
        allowed_ip = ['192.168.1.1', '127.0.0.1']
        # 允许/禁止访问的ip地址列表,判断请求ip, 放行/阻拦
        if get_ip(request) not in allowed_ip:
            return HttpResponse('您的IP地址无权访问')
        else:
            return None

那么 request.META 里面还有什么有用的数据呢?动手写一个简单的view函数来显示 request.META 的所有数据,这样你就知道里面有什么了。

def display_meta(request):
    values = request.META.items()
    html = []
    for k, v in values:
        html.append('<tr><td>%s</td><td>%s</td></tr>' % (k, v))
    return HttpResponse('<table>%s</table>' % '\n'.join(html))

在这里插入图片描述
附:Django请求流程图
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值