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

posted @ 2018-08-04 15:24  小a玖拾柒  阅读(275)  评论(0编辑  收藏  举报