zoukankan      html  css  js  c++  java
  • django-中间件,流量统计实例

    Django中间件(Middleware)

    • 中间件,顾名思义,就是处在中间的一些软件。比如匹配到了URL,但是还没有执行view函数的时候,这个时候可以执行一些代码,这个代码就是中间件。
    • HttpRequest  一(中间件)一> View 一(中间件)一> HttpResponse
    对Django自带的中间件进行详细解释:
    django.middleware.security.SecurityMiddleware:
    一些安全设置,比如XSS脚本过滤。 django.contrib.sessions.middleware.SessionMiddleware:session
    支持中间件,加入这个中间件,会在数据库中生成一个django_session的表。 django.middleware.common.CommonMiddleware:
    通用中间件,会处理一些URL,比如baidu.com会自动的处理成www.baidu.com。比如
    /blog/111会处理成/blog/111/自动加上反斜杠。 django.middleware.csrf.CsrfViewMiddleware:
    跨域请求伪造中间件。加入这个中间件,在提交表单的时候会必须加入csrf_token,cookie中也会生成一个名叫csrftoken的值,也会在header中加入一个HTTP_X_CSRFTOKEN的值来放置CSRF攻击。 django.contrib.auth.middleware.AuthenticationMiddleware:
    用户授权中间件。他会在每个HttpRequest对象到达view之前添加当前登录用户的user属性,也就是你可以在view中通过request访问user。 django.contrib.messages.middleware.MessageMiddleware:
    消息中间件。展示一些后台信息给前端页面。如果需要用到消息,还需要在INSTALLED_APPS中添加django.contrib.message才能有效。如果不需要,可以把这两个都删除。 django.middleware.clickjacking.XFrameOptionsMiddleware:
    防止通过浏览器页面跨Frame出现clickjacking(欺骗点击)攻击出现。 中间件的执行顺序 在调用视图前,settings中配置的MIDDLEWARE数组顺序执行 在调用视图后,中间件会按相反的顺序

    自定义中间件格式

    名字必须是 XxxxMiddleware

    在settings配置路径MIDDLEWARE=[]

    class TestMiddleware(object):
        ''' 自定义中间件 '''
        def __init__(self, get_response):
            self.get_response = get_response # 是View的function
    
        def __call__(self, request):
            # 请求之前的处理代码
    
            response = self.get_response(request) # 执行View请求
    
            # 请求之后的处理代码
    
            return response # 需要返回response对象

    另一种写法:

    class Test1Middleware(MiddlewareMixin): # 继承Middleware相当于上面的标准写法
        ''' 自定义中间件 '''
       pass
    • 在调用视图前,他有以下函数
      • process_view(request, view_func, view_args, view_kwargs): return None or HttpResponse
        • 在函数为你执行view视图前调用的方法
    •    def process_veiw(self, request, view_func, view_args, view_kwargs):
              """
                  @request, 当前请求对象
                  @view_func, 就是我们需要执行的view_func方法,
                  @view_args, 就是我们的view_func所带的位置参数
                  @view_kwargs, 就是我们的view_func所带的键值参数
              """
              print u'process_veiw方法,在执行View之前执行'
      
              # 这个方法如果返回的是一个response, 它就提前结束请求
              response = view_func(request, *view_args, **view_kwargs)
              return request
    • 调用视图之后
      • process_template_response(request, response) return 的结果实现了render方法的HttpResponse
        • 如果需要调用这个函数,view视图返回的response对象必须包含render方法(SimpleTemplateResponse, TemplateResponse
          )包含了render方法。而不是view直接render,一般该函数做模版内容处理
      •     def process_template_response(self, request, response):
                # 这个方法必须返回的response对象拥有render函数才会调用
                # from django.template.response import SimpleTemplateResponse, TemplateResponse
                # 这个中间件会在render方法之前调用中间件(view调用后且并没有直接渲染页面才会被调用,如果view返回render方法,则它是已经渲染完毕,该中间件则不能被调用。
        view可以用TemplateResponse, SimpleTemplateResponse代替render)
        # 也就是渲染html之前调用 print u"执行process_template_response" return response
      • process_exception(request, exception): return None or HttpResponse
        • 该请求在报出异常时,执行该方法
      •     def process_exception(self, request, exception):
                # 这个异常必须是在执行view get中出现的异常,它才能进入
                # 这里的异常是指代码出现错误,403,500错误不代表代码出现异常
                print u"---- exception ----"

    中间件开发准则

      • 中间件的类不能是任何类的子类。
      • 中间件可以存在于你Python 路径中的任何位置。 Django所关心的只是被包含在MIDDLEWARE中的配置。
      • 将Django 中可用的中间件作为例子随便看看。https://docs.djangoproject.com/en/1.11/ref/middleware/
      • 如果你认为你写的中间件组建可能会对其他人有用,那就把它共享到社区! 让我们知道它,我们会考虑把它添加到Django中
      • 中间件一般是实现一个系统级别的应用或者面向整个工程应用,所以一般情况下,中间件不能有业务代码

    流量统计

    中简件:

    class StatFlowMiddleware(object):
        """ 流量统计 """
        def __init__(self, get_response):
            self.get_response = get_response
            self.count = {}
    
        def __call__(self, request):
            if request.META.has_key("HTTP_X_FORWARDED_FOR"):
                ip = request.META["HTTP_X_FORWARDED_FOR"]
            else:
                ip = request.META["REMOTE_ADDR"]
    
            response = self.get_response(request)
    
            stats = cache.get_or_set("stats", {})
            count = 0
            count += 1  # 次数没统计 只统计了一次 怎么解决?
            if not stats.get(ip):
                stats[ip] = [time.time(), count] # 设置时间戳,计算某段时间的流量
                cache.set("stats",stats,60)
    
            return response

    view

    class StatFlowMiddleware(View):
        """
        显示一分钟的流量
        from django.core.cache import cache
        """
        def get(self, request):
            stats = cache.get('stats')
            if stats:
                current_time = time.time()
                curr_ips = [k for k, v in stats.items() if int(v[0])-current_time < 60]
                count = []
                for ip in curr_ips:
                    count.append(stats[ip][1])
            else:
                curr_ips=[]
                count=[]
            return render(request, "stats_flow.html", locals())

    html

    <body>
        访问IP:{{ curr_ips }}
        访问次数:{{ count }}
    </body>
  • 相关阅读:
    c# 并行运算二
    c# 并行运算
    Task+http请求
    Task多线程
    SSO系统认证
    web系统权限设计
    AutoMapper的使用
    中间件
    express-middleware
    中间件概念
  • 原文地址:https://www.cnblogs.com/tangpg/p/9041542.html
Copyright © 2011-2022 走看看