Django实现一个简单的中间件,不熟悉中间件的爬坑之路
1、在之前,写过一篇文章,自定义一个简单的中间件,文章链接如下:https://blog.csdn.net/u012561176/article/details/84024073
后面,发现还是有问题:
from django.views import View
from django.utils.decorators import method_decorator@method_decorator(LoginMiddleware, name='dispatch')
class AddUser(View):def get(self, request, id):
如上面代码,如果一个View底下的get方法带一个参数或者多个参数的话,将会报错:
__call__() got an unexpected keyword argument 'id'
2、这个__call__()方法是中间件MiddlewareMixin里的方法,自定义中间件的时候可以重写的,在你本地安装路径底下的一个py文件:D:/Python 3.6.3/Lib/site-packages/django/utils/deprecation.py,MiddlewareMixin代码如下:
class MiddlewareMixin:def __init__(self, get_response=None):self.get_response = get_responsesuper().__init__()def __call__(self, request):response = Noneif hasattr(self, 'process_request'):response = self.process_request(request)if not response:response = self.get_response(request)if hasattr(self, 'process_response'):response = self.process_response(request, response)return response
3、为了解决这个问题,报错说__call__()方法缺少参数,因此我给它加多一个参数,在新建一个中间件,接着调用这个代码如下:
class LoginMiddleware2(MiddlewareMixin):"""自定义权限校验中间件,带多个参数时调用"""def __call__(self, request, *args, **kwargs):return super().__call__(request)def process_request(self, request):"""session是否登录校验检查:param request::return:"""
from django.views import View
from django.utils.decorators import method_decorator@method_decorator(LoginMiddleware2, name='dispatch')
class AddUser(View):def get(self, request, id):
结果还是报错了,报错如下:
get() missing 1 required positional argument: 'id'
4、说这个get方法缺少一个参数id,后面就一直断点底层的东西,发现参数有带过去呀,怎么一直到dispatch那里走进去就报错了,发现是不是这个方法修饰器有问题,还是dispatch方法不行,后面试了好多方法,最后决定还是用别的修饰器看能不能成功,于是打开这个目录底下的一个decorators.py文件:D:/Python 3.6.3/Lib/site-packages/django/utils/decorators.py,代码如下:
"Functions that help with dynamically creating decorators for views."# For backwards compatibility in Django 2.0.
from contextlib import ContextDecorator # noqa
from functools import WRAPPER_ASSIGNMENTS, update_wrapper, wrapsclass classonlymethod(classmethod):def __get__(self, instance, cls=None):if instance is not None:raise AttributeError("This method is available only on the class, not on instances.")return super().__get__(instance, cls)def method_decorator(decorator, name=''):"""Convert a function decorator into a method decorator"""# 'obj' can be a class or a function. If 'obj' is a function at the time it# is passed to _dec, it will eventually be a method of the class it is# defined on. If 'obj' is a class, the 'name' is required to be the name# of the method that will be decorated.def _dec(obj):is_class = isinstance(obj, type)if is_class:if name and hasattr(obj, name):func = getattr(obj, name)if not callable(func):raise TypeError("Cannot decorate '{0}' as it isn't a callable ""attribute of {1} ({2})".format(name, obj, func))else:raise ValueError("The keyword argument `name` must be the name of a method ""of the decorated class: {0}. Got '{1}' instead".format(obj, name,))else:func = objdef decorate(function):"""Apply a list/tuple of decorators if decorator is one. Decoratorfunctions are applied so that the call order is the same as theorder in which they appear in the iterable."""if hasattr(decorator, '__iter__'):for dec in decorator[::-1]:function = dec(function)return functionreturn decorator(function)def _wrapper(self, *args, **kwargs):@decoratedef bound_func(*args2, **kwargs2):return func.__get__(self, type(self))(*args2, **kwargs2)# bound_func has the signature that 'decorator' expects i.e. no# 'self' argument, but it is a closure over self so it can call# 'func' correctly.return bound_func(*args, **kwargs)# In case 'decorator' adds attributes to the function it decorates, we# want to copy those. We don't have access to bound_func in this scope,# but we can cheat by using it on a dummy function.@decoratedef dummy(*args, **kwargs):passupdate_wrapper(_wrapper, dummy)# Need to preserve any existing attributes of 'func', including the name.update_wrapper(_wrapper, func)if is_class:setattr(obj, name, _wrapper)return objreturn _wrapper# Don't worry about making _dec look similar to a list/tuple as it's rather# meaningless.if not hasattr(decorator, '__iter__'):update_wrapper(_dec, decorator)# Change the name to aid debugging.if hasattr(decorator, '__name__'):_dec.__name__ = 'method_decorator(%s)' % decorator.__name__else:_dec.__name__ = 'method_decorator(%s)' % decorator.__class__.__name__return _decdef decorator_from_middleware_with_args(middleware_class):"""Like decorator_from_middleware, but return a functionthat accepts the arguments to be passed to the middleware_class.Use like::cache_page = decorator_from_middleware_with_args(CacheMiddleware)# ...@cache_page(3600)def my_view(request):# ..."""return make_middleware_decorator(middleware_class)def decorator_from_middleware(middleware_class):"""Given a middleware class (not an instance), return a view decorator. Thislets you use middleware functionality on a per-view basis. The middlewareis created with no params passed."""return make_middleware_decorator(middleware_class)()# Unused, for backwards compatibility in Django 2.0.
def available_attrs(fn):"""Return the list of functools-wrappable attributes on a callable.This was required as a workaround for http://bugs.python.org/issue3445under Python 2."""return WRAPPER_ASSIGNMENTSdef make_middleware_decorator(middleware_class):def _make_decorator(*m_args, **m_kwargs):middleware = middleware_class(*m_args, **m_kwargs)def _decorator(view_func):@wraps(view_func)def _wrapped_view(request, *args, **kwargs):if hasattr(middleware, 'process_request'):result = middleware.process_request(request)if result is not None:return resultif hasattr(middleware, 'process_view'):result = middleware.process_view(request, view_func, args, kwargs)if result is not None:return resulttry:response = view_func(request, *args, **kwargs)except Exception as e:if hasattr(middleware, 'process_exception'):result = middleware.process_exception(request, e)if result is not None:return resultraiseif hasattr(response, 'render') and callable(response.render):if hasattr(middleware, 'process_template_response'):response = middleware.process_template_response(request, response)# Defer running of process_response until after the template# has been rendered:if hasattr(middleware, 'process_response'):def callback(response):return middleware.process_response(request, response)response.add_post_render_callback(callback)else:if hasattr(middleware, 'process_response'):return middleware.process_response(request, response)return responsereturn _wrapped_viewreturn _decoratorreturn _make_decoratorclass classproperty:def __init__(self, method=None):self.fget = methoddef __get__(self, instance, cls=None):return self.fget(cls)def getter(self, method):self.fget = methodreturn self
5、从以上代码中,可以看到可以使用另外两个装饰器,分别decorator_from_middleware、decorator_from_middleware_with_args,分别使用如下:
from django.views import View
from django.utils.decorators import method_decorator, decorator_from_middleware@decorator_from_middleware(LoginMiddleware2)
class AddUser(View):def get(self, request, id):
from django.views import View
from django.utils.decorators import method_decorator, decorator_from_middleware, decorator_from_middleware_with_args@decorator_from_middleware_with_args(LoginMiddleware2)
class AddUser(View):def get(self, request, id):
接着还是报错,报错如下:AttributeError: 'function' object has no attribute 'as_view',表示这个注解不能用在as_view那里,于是乎我分别使用在底下的get方法前面,修改代码如下:
from django.views import View
from django.utils.decorators import method_decorator, decorator_from_middlewareclass AddUser(View):@decorator_from_middleware(LoginMiddleware2)def get(self, request, id):
接着报错了:AttributeError: 'AddUser' object has no attribute 'session',说这个对象没有属性session,再试下另外一种咯:
from django.views import View
from django.utils.decorators import method_decorator, decorator_from_middleware, decorator_from_middleware_with_argsclass AddUser(View):@decorator_from_middleware_with_args(LoginMiddleware2)def get(self, request, id):
发现还是报错:_decorator() got an unexpected keyword argument 'id',还是底层抛出来的异常。
6、接着,经过调试摸爬滚打后,终于搞出来了,AttributeError: 'AddUser' object has no attribute 'session',说这个对象没有属性session的时候发现了一个问题:
中间件的request底下才有个request,那个request才有session属性,所以,我修改一下中间件如下:
class LoginMiddleware2(MiddlewareMixin):"""自定义权限校验中间件, 带多个参数时"""def process_request(self, request):""":param request::return:"""if login_view.login_check(request.request) is not True:return login_view.login_check(request.request)
要调的时候加多一个request.即可,因为是中间件的request底下还有request,接着再调用即可,
from django.views import View
from django.utils.decorators import method_decorator, decorator_from_middlewareclass AddUser(View):@decorator_from_middleware(LoginMiddleware2)def get(self, request, id):
7、以上内容就是我的中间件爬坑之路,大家可以慢慢看,以上内容仅供大家学习参考,谢谢!
Django实现一个简单的中间件,不熟悉中间件的爬坑之路相关推荐
- 1-3.Win10系统利用Pycharm社区版安装Django搭建一个简单Python Web项目的步骤之三
在1-1.Win10系统利用Pycharm社区版安装Django搭建一个简单Python Web项目的步骤之一 基础上进行如下操作: 所有路由不能全部都在myDjango下的urls.py路由文件中, ...
- Django自定义一个简单的中间件,并使用此中间件
1.在最近做的项目中,需要每个页面访问的时候判断是否登录,没登录的话就跳转到登录页面,因此抽出个公共方法,并自定义个中间件是很有必要的,这样就可以用注解方式去使用这个自定义的中间件,就如Django自 ...
- django写一个简单的登陆注册
要写这个,前提还是需要知道三个知识: 一个是urls.py,它是写我们的路由关系的,之前我写了通过wsgiref写一个简单的服务端,也用到了路由,就是 请求过来的url和视图函数的对应关系. 二是就是 ...
- Django做一个简单的博客系统(11)----搜索文章
前言 实现一个简单的搜索文章的功能. 感谢大神的教程:Django搭建个人博客. 一.搜索文章 1.修改视图函数 article/views.py: def article_list(requ ...
- python爬虫抢火车票_如何用python写一个简单的12306抢票软件|python 爬火车票 教程...
python 如果抓取验证码图片 类似12306的登录验证码图片 这个以前做次.最大的麻烦是码的识别算法的识别率太低.12306那种网站登陆错3次就限制你20分钟.所以除非你有33%以上的识别率否则不 ...
- Vue爬坑之路 二:使用Muse-UI前端框架及axios,实现简单登录页
一:安装UI组件 二:创建基本的vue组件 三:使用axios与后台进行数据交互 1:安装axios 2:axios登录的实现 一:安装UI组件 Muse UI 基于 Vue2.0 开发,Vue2.0 ...
- 1-2.Win10系统利用Pycharm社区版安装Django搭建一个简单Python Web项目的步骤之二
七.在项目下新建 templates 路径 在工程上,右键,添加templates目录 注意*: 此目录下即用来存放我们的html文件: 此目录一般是与app的主目录是平级的.当然也可以建立在app的 ...
- 1-1.Win10系统利用Pycharm社区版安装Django搭建一个简单Python Web项目的步骤之一
首先,安装python3.8和pycharm参考其他教程. 一.安装django 使用下面命令默认安装最新版的django pip install django 使用下面命令可以安装指定版本 pip ...
- MVC和MTV初步认识+django的一个简单应用(萌新交流互动,欢迎大家指出错误)
MVC和MTV本质上是一个模式. MVC:M就是model,V是view,C是controller,这三个会各方面负责一些内容,组成一个整体. controller就是接收用户的的输入调用模型和视图完 ...
最新文章
- PyTorch torchvision.models小结
- 在10分钟内在新Mac中设置Java开发环境(更新)
- mfc嵌入matlab绘图窗口,将matlab的图嵌入MFC
- idea配置jfinal_JFinal 开箱评测,这次我是认真的
- 阿里开源物联网操作系统 AliOS Things 3.0 发布,集成平头哥 AI 芯片架构!
- 龙族幻想最新东京机器人位置_龙族幻想:最强“人形兵器”格斗家降临卡塞尔学院...
- loadrunner脚本中关于httpCode401特殊情况
- Vue学习笔记之01-Vue的特点
- iphone主屏幕动态壁纸_苹果11怎么设置动态壁纸?这个简单!只需这样操作
- uoj #298. 【CTSC2017】网络
- 关于eclipse adt更新的问题
- 用单片机测量流体流速的_一种测量管道内流体流速的传感器的制作方法
- 简易数字时钟 按键可校准
- 微软应用商店microsoft store 打不开
- rk3399 Android9.0 ota升级失败
- 飞天系统和linux,用Linux或Windows系统运行抢茅台脚本在性能上有区别吗?
- discourse 安装_如何使用Discourse在半天之内建立内部团队论坛
- 虚拟偶像主播的大致现状,数字人技术现状
- HP tank 519 设置无边距卡纸
- html字体插件,20款jQuery CSS文字特效插件(有图有真相)