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. 1-3.Win10系统利用Pycharm社区版安装Django搭建一个简单Python Web项目的步骤之三

    在1-1.Win10系统利用Pycharm社区版安装Django搭建一个简单Python Web项目的步骤之一 基础上进行如下操作: 所有路由不能全部都在myDjango下的urls.py路由文件中, ...

  2. Django自定义一个简单的中间件,并使用此中间件

    1.在最近做的项目中,需要每个页面访问的时候判断是否登录,没登录的话就跳转到登录页面,因此抽出个公共方法,并自定义个中间件是很有必要的,这样就可以用注解方式去使用这个自定义的中间件,就如Django自 ...

  3. django写一个简单的登陆注册

    要写这个,前提还是需要知道三个知识: 一个是urls.py,它是写我们的路由关系的,之前我写了通过wsgiref写一个简单的服务端,也用到了路由,就是 请求过来的url和视图函数的对应关系. 二是就是 ...

  4. Django做一个简单的博客系统(11)----搜索文章

    前言 实现一个简单的搜索文章的功能.     感谢大神的教程:Django搭建个人博客. 一.搜索文章 1.修改视图函数 article/views.py: def article_list(requ ...

  5. python爬虫抢火车票_如何用python写一个简单的12306抢票软件|python 爬火车票 教程...

    python 如果抓取验证码图片 类似12306的登录验证码图片 这个以前做次.最大的麻烦是码的识别算法的识别率太低.12306那种网站登陆错3次就限制你20分钟.所以除非你有33%以上的识别率否则不 ...

  6. Vue爬坑之路 二:使用Muse-UI前端框架及axios,实现简单登录页

    一:安装UI组件 二:创建基本的vue组件 三:使用axios与后台进行数据交互 1:安装axios 2:axios登录的实现 一:安装UI组件 Muse UI 基于 Vue2.0 开发,Vue2.0 ...

  7. 1-2.Win10系统利用Pycharm社区版安装Django搭建一个简单Python Web项目的步骤之二

    七.在项目下新建 templates 路径 在工程上,右键,添加templates目录 注意*: 此目录下即用来存放我们的html文件: 此目录一般是与app的主目录是平级的.当然也可以建立在app的 ...

  8. 1-1.Win10系统利用Pycharm社区版安装Django搭建一个简单Python Web项目的步骤之一

    首先,安装python3.8和pycharm参考其他教程. 一.安装django 使用下面命令默认安装最新版的django pip install django 使用下面命令可以安装指定版本 pip ...

  9. MVC和MTV初步认识+django的一个简单应用(萌新交流互动,欢迎大家指出错误)

    MVC和MTV本质上是一个模式. MVC:M就是model,V是view,C是controller,这三个会各方面负责一些内容,组成一个整体. controller就是接收用户的的输入调用模型和视图完 ...

最新文章

  1. PyTorch torchvision.models小结
  2. 在10分钟内在新Mac中设置Java开发环境(更新)
  3. mfc嵌入matlab绘图窗口,将matlab的图嵌入MFC
  4. idea配置jfinal_JFinal 开箱评测,这次我是认真的
  5. 阿里开源物联网操作系统 AliOS Things 3.0 发布,集成平头哥 AI 芯片架构!
  6. 龙族幻想最新东京机器人位置_龙族幻想:最强“人形兵器”格斗家降临卡塞尔学院...
  7. loadrunner脚本中关于httpCode401特殊情况
  8. Vue学习笔记之01-Vue的特点
  9. iphone主屏幕动态壁纸_苹果11怎么设置动态壁纸?这个简单!只需这样操作
  10. uoj #298. 【CTSC2017】网络
  11. 关于eclipse adt更新的问题
  12. 用单片机测量流体流速的_一种测量管道内流体流速的传感器的制作方法
  13. 简易数字时钟 按键可校准
  14. 微软应用商店microsoft store 打不开
  15. rk3399 Android9.0 ota升级失败
  16. 飞天系统和linux,用Linux或Windows系统运行抢茅台脚本在性能上有区别吗?
  17. discourse 安装_如何使用Discourse在半天之内建立内部团队论坛
  18. 虚拟偶像主播的大致现状,数字人技术现状
  19. HP tank 519 设置无边距卡纸
  20. html字体插件,20款jQuery CSS文字特效插件(有图有真相)

热门文章

  1. 《学习javascript数据结构与算法》——第六章:集合
  2. 【转】Visual Studio 2005/2008中的快捷键与小技巧整理
  3. vue中使用FullCalendar日历组件
  4. 【JS】call,apply,bind
  5. 一个简易的数字输入框组件
  6. LeetCode--91. 解码方法(动态规划)
  7. MFC多线程的创建,包括工作线程和用户界面线程
  8. 7-46 最长对称子串 (25 分)
  9. 北林oj-算法设计与分析-Don‘t touch my cake(题意+代码)
  10. 排序算法之选择排序(简单选择排序、堆排序)