Python學習---Django拾遺180328

Django之生命週期

前臺發送URL請求到Django的中間件進行內容校驗,完成校驗後到達路由映射文件url.py,而後調用視圖函數views.py裏面的函數進行內容處理【 1.操做數據庫進行數據讀寫  2. 調用前臺的模版內容】最後返回字符串給前臺進行頁面的渲染【這裏回去的時候也會通過中間件】。 css

Django之中間件

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

Django中間件相似於Java框架中的攔截器之類的東西,就是在請求到達咱們要操做的函數以前添加的一些判斷之類的操做。 python

應用場景: 適用於全局的操做,對全部的用戶請求/用戶返回數據都須要處理的狀況。process_request適用於請求到達以前已經執行的操做,相似防禦的操做[例如,csrf中間件,過濾器,自定義請求頭]; jquery

Django中間件即類中的方法執行順序是Django固定的,不能更改執行順序,函數名稱也不能更改【若是自定義了MiddlewareMixin的話,能夠不使用固定的名稱】 ajax

注:這裏的函數是不須要所有寫的,也就是process_request和process_response無關緊要 sql

image

中間件中能夠定義四個方法,分別是:數據庫

process_request(self,request)django

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

相關文章
相關標籤/搜索