zoukankan      html  css  js  c++  java
  • Django(十七):静态文件、中间件

    一、静态文件

    参考:https://www.cnblogs.com/jiajiaba/p/10584329.html
    参考:https://docs.djangoproject.com/zh-hans/3.0/ref/settings/#static-files

    1.1 使用

    在 网页使用的css文件,js文件和图片叫做静态文件。
    1)新建静态文件夹 根目录/static/js、css、images
    2) 配置静态文件所在的物理目录。

    Settings.py

    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/1.8/howto/static-files/
    # 【1】设置访问静态文件对应的url地址
    STATIC_URL = '/static/'
    # STATIC_URL = '/abc/'
    # 【2】设置静态文件存放的物理目录(django2.0以后似乎无用)
    STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
    

    说明:

    • STATIC_URL 设置访问静态文件对应的url。
    • STATICFILES_DIRS 设置静态文件所在的物理目录。

    1.2 加载目录过程(了解)

    STATICFILES_FINDERS=('django.contrib.staticfiles.finders.FileSystemFinder', 
    'django.contrib.staticfiles.finders.AppDirectoriesFinder')
    

    1.3 模板中动态生成静态文件路径

    1. {% load static %} django2.0以前可能是 {% load staticfiles %}
    2. <img src="{% static 'images/mm.jpg' %}">
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <!-- 【1】加载静态 -->
        {% load static %}
        <title>首页</title>
    </head>
    <body>
    <h1>首页{{name}}</h1>
    
    <img src="/static/images/mm.jpg"><br/>
    <img src="/abc/images/mm.jpg"><br/>
    【2】动态获取STATIC_URL,拼接静态文件路径:<br/>
    <img src="{% static 'images/mm.jpg' %}">
    
    </body>
    </html>
    

    效果:

    • 1.1 2) 步的配置文件改变成STATIC_URL = '/abc/'动态的路径依旧可以得到正确地址。
      settings.py
    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/1.8/howto/static-files/
    # 【1】设置访问静态文件对应的url地址
    # STATIC_URL = '/static/'
    STATIC_URL = '/abc/'
    # 【2】设置静态文件存放的物理目录(django2.0以后似乎无用)
    #STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
    

    在这里插入图片描述

    二、中间件(函数)

    【参考】https://docs.djangoproject.com/zh-hans/3.0/topics/http/middleware/

    【中间件函数】是django框架给我们预留的函数接口,让我们可以干预请求应答的过程

    在这里插入图片描述

    2.0 实例支持:获取浏览器端的ip地址

    使用request对象的META属性:request.META['REMOTE_ADDR']

    2.1中间件作用——实例说明

    • 目标:过滤指定IP,让它访问不了网站

    2.2常规解决方法——【装饰器过滤IP】

    1)app2/views.py编辑装饰器

    EXCLUDE_IPS = ['192.168.1.123','172.16.179.152'] #第1个ip即要禁用的目标主机IP
    '''装饰器函数:如果IP在exclude_ids里则返回forbidden'''
    def blocked_ips(view_func):
        def wrapper(request, *view_args, **view_kwargs):
            # 获取浏览器端的ip地址
            user_ip = request.META['REMOTE_ADDR']
            if user_ip in EXCLUDE_IPS:
                return HttpResponse('<h1>Forbidden</h1>')
            else:
                return view_func(request, *view_args, **view_kwargs)
        return wrapper
    
    # /index
    @blocked_ips #引用装饰器,此页面会禁用指定ip访问
    def index (request):    
        return render(request,'app2/index.html',{'name':'Tom'})
    
    # /url_reverse
    @blocked_ips #引用装饰器,此页面会禁用指定ip访问
    def url_reverse (request):
        return render(request,'app2/url_reverse.html')
    

    2)urls配置略过#

    3)启动服务

    py manage.py runserver 192.168.1.4:8000
    

    4)在局域网的另一台主机(192.168.1.123电脑)访问 192.168.1.4:8000/index 或 url_reverse

    显示:Forbidden

    5)装饰器方法缺点:虽然也能禁用指定IP,但每个视频函数页面都要调用装饰器@blocked_ips,太过麻烦。

    2.3 中间件过滤IP【重点】

    【参考】https://segmentfault.com/a/1190000019784702

    1)app2/middleware.py 编写中间件

    建立文件,自定义中间件函数,详细代码:

    1. 新建app2/middleware.py文件。
    2. 定义中间件类,写中间件函数
    from django.http import HttpResponse
    from django.utils.deprecation import MiddlewareMixin
    
    #【1】类继承自MiddlewareMixin,类名可随意写,建议加上Middleware  
    #django2.0之前写法:class BlockedIPSMiddleware(object)
    class BlockedIPSMiddleware(MiddlewareMixin): 
        '''中间件类'''
        EXCLUDE_IPS = ['192.168.1.123','172.16.179.152']
        #【2】此处是process_view函数重写,因此写法固定,不能变(包括函数名、参数)
        def process_view(self, request, view_func, *view_args, **view_kwargs):
            '''视图函数调用之前会调用'''
            user_ip = request.META['REMOTE_ADDR']
            if user_ip in BlockedIPSMiddleware.EXCLUDE_IPS:
                return HttpResponse('<h1>Forbidden</h1>')
    

    2)【project2/settings.py】配置中间件

    【1】注册过滤IP的中间件类名(app2文件夹下.middleware.py文件下.BlockedIPSMiddleware类)
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware', #django默认打开csrf防护,它只对post提交有效
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'app2.middleware.BlockedIPSMiddleware' # 【1】注册过滤IP的中间件类名(app2文件夹下.middleware.py文件下.BlockedIPSMiddleware类)
    ]
    

    附)app2/views.py

    from django.shortcuts import render,redirect
    from django.template import loader,RequestContext
    from django.http import HttpResponse,JsonResponse
    from app2.models import BookInfo
    
    EXCLUDE_IPS = ['192.168.1.123','172.16.179.152']
    '''装饰器函数:如果IP在exclude_ids里则返回forbidden'''
    def blocked_ips(view_func):
        def wrapper(request, *view_args, **view_kwargs):
            # 获取浏览器端的ip地址
            user_ip = request.META['REMOTE_ADDR']
            if user_ip in EXCLUDE_IPS:
                return HttpResponse('<h1>Forbidden</h1>')
            else:
                return view_func(request, *view_args, **view_kwargs)
        return wrapper
    
    # /index
    #@blocked_ips
    def index (request):    
        return render(request,'app2/index.html',{'name':'Tom'})
    
    # /url_reverse
    #@blocked_ips
    def url_reverse (request):
        return render(request,'app2/url_reverse.html')
    
    # /temp_tags
    def temp_tags(request):
        '''模板标签'''
        # 1. 查找所有图书的信息
        books = BookInfo.objects.all()
        return render(request,'app2/temp_tags.html', {'books':books})
    

    3)效果:再启动服务器:

    1.打开cmd运行

    py manage.py runserver 192.168.1.4:8000
    

    2.另一台电脑(192.168.1.123)访问任意网址:http://192.168.1.4:8000/temp_tags/
    http://192.168.1.4:8000/index/等等。都会自动提示:
    Forbidden
    3. 这样就不必加装饰器函数、逐个@装饰器函数了

    2.4 django2.0之后MiddlewareMixin中间件类的其它函数及作用

    在这里插入图片描述

    1)process_request:

    这是请求来到 middleware 中时讲入的第一个方法。一般情优下,我们以在这里做一些校验,比如
    户登录或者 HTTP 中是否有认证头之类的验证.这个方法可以有两种返回值 HttpResnonse 或者None,如果返回 HttpResponse,那么接下米的处理方法只会执行 process_response,其他方法将不会被执行。这里需要注意的是,如果你的 middleware 是 settings 配置的 MIDDLEWARE 的第一个,那么剩下的 middleware 也不会被执行;如果返回 None,那么 Diango会继续执行其他方法。

    2)process_view:

    这个方法是在 process_request 方法之后执行的,参数如上面代码所示,其中 func 就是我们将要执行的 view 方法。因此,如果要统计一个view的执行时间,可以在这里做。它的返回值跟 process_request 一样,是HttpResponse 或者 None,其逻辑也一样。如果返回 None,那么 Django 会帮你执行 view 函数,从而得到最终的 response。

    3)Process_template_response:

    执行完上面的方法,并且 Django 帮我们执行完 view,拿到最终的 response 后,如果使用了模板的 response (这是指通过 return render(request,'index.html',context={})方式返回的 response),就会来到这个方法中。 在这个方法中,我们可以对 response 做一下操作,比如 Content-Type 设置,或者其他 header 的修改/增加。

    4)process_response:

    当所有流程都处理完毕后,就来到了这个方法。这个方法的逻辑跟 process_template_response是完全一样的,只是后者是针对带有模板的response的处理。

    5)process_exception:

    上面的处理方法是按顺序介绍的,而这个方法不太一样。只有在发生异常时,才会进入这个方法。哪个阶段发生的异常呢?
    可以简单理解为在将要调用的 View 中出现异常(就是在process_view 的 func 函数中)或者返回的模板 response 在渲染时发生的异常。但是需要注意的是,如果你在process_view 中手动调用了 func,就像我们上面做的那样,就不会触发 process_exception 了。这个方法接收到异常之
    后,可以选择处理异常,然后返回一个含有异常信息的 HttpResponse,或者直接返回 None 不处理,这种情况下 Django会使用自己的异常模板。

    2.5)django2.0之前middleware函数:

    在类中定义中间件预留函数。
    __init__:服务器响应第一个请求的时候调用。
    process_request:是在产生request对象,进行url匹配之前调用。
    process_view:是url匹配之后,调用视图函数之前。
    process_response:视图函数调用之后,内容返回给浏览器之前。
    process_exception:视图函数出现异常,会调用这个函数。
    如果注册的多个中间件类中包含process_exception函数的时候,调用的顺序跟注册的顺序是相反的。

    2.6)中间件各函数调用过程实例演示

    【参考】https://docs.djangoproject.com/zh-hans/3.0/topics/http/middleware/#upgrading-pre-django-1-10-style-middleware

    1)app2/middleware.py 编写中间件

    django2.0后写法
    class TestMiddleware(MiddlewareMixin): 
        '''中间件类'''
        def __init__(self,get_response):#【1】重点一此处必须多加参数,get_response,否则报错: __init__() takes 1 positional argument but 2 were given
            '''服务器重启之后,接收第一个请求时调用'''
            #super().__init__()
            self.get_response = get_response #【2】此处必须得到父类的get_response属性,否则报错 __init__() takes 1 positional argument but 2 were given
            print('----init----')
    
        def process_request(self, request):
            '''产生request对象之后,url匹配之前调用'''
            print('----process_request----')
            # return HttpResponse('process_request')
    
        def process_view(self, request, view_func, *view_args, **view_kwargs):
            '''url匹配之后,视图函数调用之前调用'''
            print('----process_view----')
            return HttpResponse('process_view')
    
        def process_response(self, request, response):
            '''视图函数调用之后,内容返回浏览器之前'''
            print('----process_response----')
            return response
    
    django2.0之前写法
    '''django2.0之前写法'''
    from django.http import HttpResponse
    
    class TestMiddleware(object):
        '''中间件类'''
        def __init__(self):
            '''服务器重启之后,接收第一个请求时调用'''
            print('----init----')
    
        def process_request(self, request):
            '''产生request对象之后,url匹配之前调用'''
            print('----process_request----')
            # return HttpResponse('process_request')
    
        def process_view(self, request, view_func, *view_args, **view_kwargs):
            '''url匹配之后,视图函数调用之前调用'''
            print('----process_view----')
            return HttpResponse('process_view')
    
        def process_response(self, request, response):
            '''视图函数调用之后,内容返回浏览器之前'''
            print('----process_response----')
            return response
    

    2)app2/views.py

    from django.shortcuts import render
    
    # /index
    #@blocked_ips
    def index (request):
    	'''首页'''
        print('----index----')   
        return render(request,'app2/index.html',{'name':'Tom'})
    

    3)配置settings.py

    【1】注册中间件流程测试类名

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware', #django默认打开csrf防护,它只对post提交有效
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'app2.middleware.BlockedIPSMiddleware', # 注册过滤IP的类名
        'app2.middleware.TestMiddleware', #【1】注册中间件流程测试类名
    ]
    

    效果:http://127.0.0.1:8000/index/

    process_view

    1. 正常运行(把首页截断不运行)

    控制台输出(即可看到中间件各函数运行流程):

    1. 第一次会执行init
    2. 再次请求就不再调用它了
    Starting development server at http://127.0.0.1:8000/
    Quit the server with CTRL-BREAK.
    ----init----
    ----process_request----
    ----process_view----
    ----process_response----
    [14/Jan/2020 10:58:16] "GET /index/ HTTP/1.1" 200 12
    ----process_request----
    ----process_view----
    ----process_response----
    [14/Jan/2020 11:01:39] "GET /index/ HTTP/1.1" 200 12
    
    2. 如果把process_request解除注释(后面步骤截断)

    可以看到后面都被截断不再运行了。

    def process_request(self, request):
            '''产生request对象之后,url匹配之前调用'''
            print('----process_request----')
            return HttpResponse('process_request')
    

    控制台输出

    ----process_request----
    ----process_response----
    [14/Jan/2020 11:22:36] "GET /index/ HTTP/1.1" 200 15
    
    3. 如果这两个函数都注释掉:
    def process_request(self, request):
            '''产生request对象之后,url匹配之前调用'''
            print('----process_request----')
            # return HttpResponse('process_request')
    
        def process_view(self, request, view_func, *view_args, **view_kwargs):
            '''url匹配之后,视图函数调用之前调用'''
            print('----process_view----')
            #return HttpResponse('process_view')
    

    则控制台输出:

    • 可以看到首页被加载了
    Quit the server with CTRL-BREAK.
    ----init----
    ----process_request----
    ----process_view----
    ----index----
    ----process_response----
    [14/Jan/2020 11:25:45] "GET /index/ HTTP/1.1" 200 349
    ----process_request----
    ----process_response----
    Not Found: /static/images/mm.jpg
    [14/Jan/2020 11:25:45] "GET /static/images/mm.jpg HTTP/1.1" 404 4316
    [14/Jan/2020 11:25:45] "GET /abc/images/mm.jpg HTTP/1.1" 404 1659
    
    

    2.6)发生异常的中间件

    1)app2/middleware.py 编写异常处理中间件

    from django.http import HttpResponse
    from django.utils.deprecation import MiddlewareMixin
    
    class ExceptionTest1Middleware(MiddlewareMixin):
        def process_exception(self, request, exception):
            '''视图函数发生异常时调用'''
            print('----process_exception1----')
            print(exception)
    
    class ExceptionTest2Middleware(MiddlewareMixin):
        def process_exception(self, request, exception):
            '''视图函数发生异常时调用'''
            print('----process_exception2----')
    

    2)注册中间件settings.py

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware', #django默认打开csrf防护,它只对post提交有效
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        #'app2.middleware.BlockedIPSMiddleware', # 注册过滤IP的类名
        #'app2.middleware.TestMiddleware', #注册中间件流程测试类名
    
        'app2.middleware.ExceptionTest1Middleware', #【1】异常处理中间件
        'app2.middleware.ExceptionTest2Middleware', #【2】异常处理中间件,它们的调用顺序是自下往上的
    ]
    

    3)写一个错误到视图函数app2/views.py

    # /index
    #@blocked_ips
    def index (request):
        '''首页'''
        name='a'+2 #【错误】用字符串和数字相加
        print('----index----')    
        return render(request,'app2/index.html',{'name':'Tom'})
    

    效果:http://127.0.0.1:8000/index/

    报错:

    TypeError at /index/
    can only concatenate str (not "int") to str
    

    控制台输出:
    【1-2】处

    Starting development server at http://127.0.0.1:8000/
    Quit the server with CTRL-BREAK.
    ----process_exception2---- 【1】
    ----process_exception1----【2】
    
    can only concatenate str (not "int") to str
    Internal Server Error: /index/
    Traceback (most recent call last):
      File "C:UsersAdministratorAppDataLocalProgramsPythonPython37libsite-p
    ackagesdjangocorehandlersexception.py", line 34, in inner
        response = get_response(request)
      File "C:UsersAdministratorAppDataLocalProgramsPythonPython37libsite-p
    ackagesdjangocorehandlersase.py", line 115, in _get_response
        response = self.process_exception_by_middleware(e, request)
      File "C:UsersAdministratorAppDataLocalProgramsPythonPython37libsite-p
    ackagesdjangocorehandlersase.py", line 113, in _get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "D:adjango-appproject2app2views.py", line 155, in index
        name='a'+2
    TypeError: can only concatenate str (not "int") to str
    [14/Jan/2020 11:54:35] "GET /index/ HTTP/1.1" 500 69194
    
    
  • 相关阅读:
    luogu P1451 求细胞数量
    P1443 马的遍历
    luogu P1194 买礼物
    codevs 4919 线段树练习4
    printf的实型
    printf的整型
    scanf
    printf
    c++常用函数
    字符类型C++(ascll码表)
  • 原文地址:https://www.cnblogs.com/chenxi188/p/12191313.html
Copyright © 2011-2022 走看看