• Python学习---Django拾遗180328


    Django之生命周期

    前台发送URL请求到Django的中间件进行内容校验,完成校验后到达路由映射文件url.py,然后调用视图函数views.py里面的函数进行内容处理【 1.操作数据库进行数据读写  2. 调用前台的模版内容】最后返回字符串给前台进行页面的渲染【这里回去的时候也会经过中间件】。

    Django之中间件

    【更多参考】http://www.cnblogs.com/wupeiqi/articles/5246483.html

    Django中间件类似于Java框架中的拦截器之类的东西,就是在请求到达我们要操作的函数之前添加的一些判断之类的操作。

    应用场景: 适用于全局的操作,对所有的用户请求/用户返回数据都需要处理的情况。process_request适用于请求到达之前已经执行的操作,类似防护的操作[例如,csrf中间件,过滤器,自定义请求头];

    Django中间件即类中的方法执行顺序是Django固定的,不能更改执行顺序,函数名称也不能更改【如果自定义了MiddlewareMixin的话,可以不使用固定的名称】

    注:这里的函数是不需要全部写的,也就是process_request和process_response可有可无

    image

    中间件中可以定义四个方法,分别是:

    process_request(self,request)

    process_view(self, request, callback, callback_args, callback_kwargs)

    process_template_response(self,request,response)

    process_exception(self, request, exception)

    process_response(self, request, response)

    中间件实例

    创建中间件路径【文件夹+文件】

    image

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]
    MIDDLEWARE = [
    ...
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'plugin.handler.Handler',
    'plugin.handler.Handler2',
    'plugin.handler.Handler3',
    ]

    urls.py

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url, include
    from app01 import views
    urlpatterns = [
        url('test/', views.Test),
        url('test/(d+)/', views.Test1),
        # url('test/(?P<nid>d{3})/', views.Test2), # 效果同Test1,只不过nid的名称是固定,kv形式返回
    ]

    views.py

    from django.shortcuts import render, redirect, HttpResponse
    from app01 import models
    # 中间层操作
    class Foo:
        def __init__(self, request, html):
            self.req = request
            self.html = html
    
        def render(self):
            return render(self.req, self.html)
    
    def Test(request):
        print('views')
        return HttpResponse("OK")
    
    def Test1(request,nid):
        print('views1')
        return HttpResponse("OK1")
    
    def Test2(request, nid):
        print('views2')
        return HttpResponse("OK2")
    
    # 测试process_template_response,这里不做细节演示
    def Test4(request, nid):
        print('views2')
        return  Foo(request, 'test.html')

    plugin/handler.py

    # version: python3.2.5
    # 中间件测试
    # 新的中间件【复制的原类,为了规范起见,所有中间件继承于此】
    # 另:继承了自定义的MiddlewareClass就可以自定义函数名了,不一定是process_request
    class MiddlewareClass(object):
        def __init__(self, get_response=None):
            self.get_response = get_response
            super(MiddlewareClass, self).__init__()
    
        def __call__(self, request):
            response = None
            if hasattr(self, 'process_request'):
                # 执行当前中间件的process_request
                response = self.process_request(request)
            if not response:
                # 执行下一个中间件的__call__()方法
                response = self.get_response(request)
            if hasattr(self, 'process_response'):
                # 执行当前中间件的process_response
                response = self.process_response(request, response)
            return response
    
    from  django.utils.deprecation import MiddlewareMixin  # 原始的继承类
    from django.shortcuts import HttpResponse
    class Handler(MiddlewareClass):
        def process_request(self, request):
            print('A  --> process_request')
            # return HttpResponse("Handler的process_response结束了请求...")  #Django2.0.1中此方法会终止后面的中间件请求
    
        # 根据url.py里面的路由映射获取views.py里面的函数,函数参数
        # view_func: 函数名
        # view_args:参数名
        # view_kwargs: 如果参数名指定了列名,则key-value形式显示
        # 执行的时候会按照A->B->C的顺序依次执行中间件内容,完成后去执行process_exception
        def process_view(self, request, view_func, view_args, view_kwargs):
            print('A  --> process_view')
    
        # 这个函数只对views.py里面的报错进行处理,其他异常均不处理
        # 异常处理完成后返回到最后一个中间件process_response进行response处理
        def process_exception(self, request, exception):
            print('A  --> process_exception')
    
        def process_response(self, request, response):
            print('A  --> process_response')
            return response
    
        # views.py函数如果返回的是HttpResponse("OK1"),则这个函数并不做什么操作
        # views.py函数如果返回的是Render(request, 'index.html'),则这个函数也不做什么操作
        # views.py函数如果返回的对象new Obj()有Render方法,则这个函数会去render函数里面做操作
        def process_template_response(self, request, response):
            print('A  --> process_template_response')
            return response
    
    
    class Handler2(MiddlewareClass):
        def process_request(self, request):
            print('B  --> process_request')
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print('B  --> process_view')
            print('view_func:', view_func)
            print('view_args:', view_args)
            print('view_kwargs:', view_kwargs)
    
        def process_exception(self, request, exception):
            print('B  --> process_exception')
    
        def process_response(self, request, response):
            print('B  --> process_response')
            print("Response类型:", response)
            print("Response类型:", type(response))
            return response
        
        def process_template_response(self, request, response):
            print('B  --> process_template_response')
            return response
    
    class Handler3(MiddlewareClass):
        def process_request(self, request):
            print('C  --> process_request')
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print('C  --> process_view')
    
        def process_exception(self, request, exception):
            print('C  --> process_exception')
    
        def process_response(self, request, response):
            print('C  --> process_response')
            return response
    
        def process_template_response(self, request, response):
            print('C  --> process_template_response')
            return response

    templates/XXX.html

        无

    页面显示;

    正常访问执行顺序:

    image

    中间件request请求中返回response效果:

    image

    image

    另外其他的函数执行效果:

    image

    Django之CSRF[跨站请求伪造]

    Django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

    全局:

      中间件 django.middleware.csrf.CsrfViewMiddleware

    局部:

    @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。

    @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

    注: from django.views.decorators.csrf import csrf_exempt,csrf_protect

    settings.py里面如果未注释掉CSRF验证【即需要CSRF验证】

    我们的get请求可以通过,post请求会被拦截

    image

    Django里面使用form的post请求发送数据的时候,一定是return了一个render对象,且HTML的form表单内使用了{% csrf_token %}进行标记,此时前台的HTML里面会多出一行csrf的token同时会缓存一份到Cookie里面。同理,如果我们需要ajax发送post请求的时候,是需要从Cookie里面获取token[从截图可以看到Cookie里面token的key是csrftoken]并添加到请求头[request-header]里让Django进行验证的。

    image

    image

    Ajax请求CSRF实例

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    MIDDLEWARE = [
    ...
    'django.middleware.csrf.CsrfViewMiddleware',
          ...
    ]
    
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]

    urls.py

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url, include
    from app01 import views
    urlpatterns = [
        url('login/', views.Login),
    ]

    views.py

    from django.shortcuts import render, redirect, HttpResponse
    from app01 import models
    # SCRF测试
    def Login(request):
        # 注意这里的settings是Django默认的
        # 我们看到的写入的settings.py文件会读入并覆盖conf里面的setting
        from django.conf import settings
        print('settings.CSRF_HEADER_NAME: ', settings.CSRF_HEADER_NAME)
        print(request.method)
        return render(request, 'login.html')

    templates/login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <form action="/login/" method="post">
            {% csrf_token %}
            姓名:<input type="text" name="username">
            <input type="submit" value="Form提交">
            <input type="button" value="Ajax提交" id="btn">
        </form>
    </body>
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script src="/static/JQuery.Cookies.js"></script>
    <script>
        $(function () {
            {# 这里对请求头做统一的处理,发送请求之前进行批量的配置 #}
             $.ajaxSetup({
                beforeSend: function(xhr) {
                        xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
                }
            });
            $("#btn").click(function () {
                $.ajax({
                    url: '/login/',
                    type:'POST',
                 {# headers: {'X-CSRFTOKEN': 'hhh'},#}
                 {#  headers: {'X-CSRFTOKEN': $.cookie('csrftoken')},  这里是自定义添加token#}
                    data: {username: 'root'},
                    success: function (args) {
                        console.log(args)
                    }
                })
            })
        })
    </script>
    </html>

    PS: 获取request里面的请求信息,可以使用断点打印,我们可以看出我们request里的header经过Django处理后在Meta里面呢,且字段名前添加了HTTP的前缀。

    页面显示;

    image

    image

    其他

    image

    Django之缓存

    【更多参考】http://www.cnblogs.com/wupeiqi/articles/5246483.html

    由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

    缓存适用于固定内容且访问量大,大型文件内容,不具有实时性的内容。

    缓存方式及配置

    Django中提供了6种缓存方式:

    开发调试 -->  什么都不干

    内存

    文件

    数据库

    Memcache缓存(python-memcached模块)   -->在另外一台服务器上

    Memcache缓存(pylibmc模块)

    配置:

    开发调试

    # 此为开始调试用,实际内部不做任何操作
        # 配置:
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.dummy.DummyCache',     # 引擎
                    'TIMEOUT': 300,   # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
                    'OPTIONS':{
                        'MAX_ENTRIES': 300, # 最大缓存个数(默认300)
                        'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
                    },
                    'KEY_PREFIX': '',       # 缓存key的前缀(默认空)
                    'VERSION': 1,           # 缓存key的版本(默认1)
                    'KEY_FUNCTION' 函数名   # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
                }
            }
    注:memache帮我们生成key的时候,会以前缀+版本+key为默认key名称,具体看下面源码
        # 自定义key
        def default_key_func(key, key_prefix, version):
            """
            Default function to generate keys.
            Constructs the key used by all other methods. By default it prepends
            the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
            function with custom key making behavior.
            """
            return '%s:%s:%s' % (key_prefix, version, key)
    
        def get_key_func(key_func):
            """
            Function to decide which key function to use.
            Defaults to ``default_key_func``.
            """
            if key_func is not None:
                if callable(key_func):
                    return key_func
                else:
                    return import_string(key_func)
            return default_key_func

    内存:

    # 此缓存将内容保存至内存的变量中
        # 配置:
            CACHES = {
                'default': {
                   'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                   'LOCATION': 'unique-snowflake',# 此参数就是标志唯一变量名称用于指引value可任意指定
                }
            }
    
        # 注:其他配置同开发调试版本

    文件:

    # 此缓存将内容保存至文件
        # 配置:
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
                    'LOCATION': '/var/tmp/django_cache', # 指定文件路径,文件存放位置
                }
            }
        # 注:其他配置同开发调试版本

    数据库:

    # 此缓存将内容保存至数据库
    # 配置:
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
                    'LOCATION': 'my_cache_table',   # 指定数据库表,一条数据就是一个缓存
                }
            }
        # 注:执行创建表命令 python manage.py createcachetable  -->专门防止缓存的表

    Memcache缓存(python-memcached模块)

    Memcache可以理解为另外一个服务器的内存,是内存级别的缓存;

    内容以Key-Value形式存储,整体的Memcache就是一个大字典

    # 此缓存使用python-memcached模块连接memcache
    # 3种连接方式
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                'LOCATION': '127.0.0.1:11211',  # 根据IP和端口连接指定机器    
       }
        }
    # 此方法只能连接本机信息
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                'LOCATION': 'unix:/tmp/memcached.sock',  # 以文件的形式连接[文件包含连接信息]
            }
        }   
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                'LOCATION': [
                    ('172.19.26.240:11211', 10),              # 连接多个服务器,类似分布式哈~
                    ('172.19.26.242:11211', 15),              # 数据存储再多个服务器上...
              ('172.19.26.241:11211,’ 20),     # 设置了权重的连接,用户输入的key会计算hash值,返回一个int数字,后根据取余求算存储位置,根据权重确定服务器。加了权重后的,此时相当于10+15+20个服务器了,写入第三个服务器[有20个]的概率大
                ]
            }
        }

    Memcache缓存(pylibmc模块)

    # 此缓存使用pylibmc模块连接memcache
    # 共3种连接方式
    # 解释同上
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': '/tmp/memcached.sock',
        }
    }
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        }
    }

    注:memache中如果有服务器故障,因为memacahe里面没有检测机制,只能自己监控该模块,更改模块里面的接口方法处理

    缓存应用

    Django中提供了3种缓存方式:

    全栈使用缓存

    单独视图缓存

    局部视图使用

    A. 全栈使用的配置

    image

    settings.py

    MIDDLEWARE = [
        'django.middleware.cache.UpdateCacheMiddleware',
        # 其他中间件...
        'django.middleware.cache.FetchFromCacheMiddleware',
    ]
    CACHE_MIDDLEWARE_ALIAS = ""
    CACHE_MIDDLEWARE_SECONDS = ""
    CACHE_MIDDLEWARE_KEY_PREFIX = ""

    B.单独视图缓存

    settings.py

    方式一:
            from django.views.decorators.cache import cache_page
            @cache_page(60 * 15)
            def my_view(request):
                ...
    方式二:
            from django.views.decorators.cache import cache_page
            urlpatterns = [
                url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
            ]

    C.局部视图缓存

    Html文件内写

    a. 引入TemplateTag
            {% load cache %}
    b. 使用缓存
            {% cache 5000 缓存key %}
                缓存内容
            {% endcache %}

    单独视图和局部视图实例

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    MIDDLEWARE = [
    ...
    # 'django.middleware.csrf.CsrfViewMiddleware',
          ...
    ]
    
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
            'LOCATION': os.path.join(BASE_DIR, 'cache'),  # 指定文件路径,文件存放位置
        }
    }

    urls.py

    from django.contrib import admin
    from django.urls import path
    from django.conf.urls import url, include
    from app01 import views
    urlpatterns = [
       url('cache/', views.Cache),
     url('part/', views.Cache_part),
    ]

    views.py

    from django.shortcuts import render, redirect, HttpResponse
    from app01 import models
    # 文件缓存之单独视图[views]缓存    -->缓存整个页面及内容
    from django.views.decorators.cache import cache_page
    @cache_page(10)
    def Cache(request):
        import time
        v = time.time()
        return HttpResponse(v)
    
    # 文件缓存之局部视图缓存         -->缓存部分页面内容
    def Cache_part(request):
        import time
        v = time.time()
        return render(request, 'part.html', {'v':v})

    templates/part.html

    {% load cache %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <h1>H1:{{ v }}</h1>
        {% cache 10  time %}
            <h5>H5:  {{ v }}</h5>
        {% endcache %}
    </body>
    </html>

    页面显示;

    文件缓存之单独视图缓存 :

    image

    文件缓存之局部视图缓存

    image

    全栈使用实例

    settings.py

    INSTALLED_APPS = [
       ...
     'app01',   # 注册app
    ]
    MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
    
    ]
    
    STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),)  # 现添加的配置,这里是元组,注意逗号
    TEMPLATES = [
       ...
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
    ]
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
            'LOCATION': os.path.join(BASE_DIR, 'cache'),  # 指定文件路径,文件存放位置
        }
    }

    其余同部分的单独的使用...

    页面显示;

    image

    全栈中间件代码分析:

    from django.middleware.cache import FetchFromCacheMiddleware

    image

    from django.middleware.cache import UpdateCacheMiddleware

    image

     

    Django之bootStrap

    bootStrap 一个集成css,js的文件

    bootStrap参考】  http://v3.bootcss.com/getting-started/

     

    【更多参考】http://www.cnblogs.com/wupeiqi/articles/5237704.html

  • 相关阅读:
    ANDROID笔记:shape的简单使用
    ANDROID笔记:根据长宽实现图片压缩
    ANDROID笔记:PopupMenu的用法
    ANDROID笔记:AdapterContextMenuInfo在ListView中的用法
    ANDROID笔记:利用XML布局文件生成Menu
    ANDROID笔记:ContextMenu的用法
    ANDROID笔记:JSON和Adapter的使用
    ANDROID笔记:Dialog的几种用法
    ANDROID笔记:AdapterViewFlipper和ViewFlipper的简单使用
    #2020征文-开发板# 用鸿蒙开发AI应用(一)硬件篇
  • 原文地址:https://www.cnblogs.com/ftl1012/p/9418739.html
Copyright © 2020-2023  润新知