日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python自动化开发学习22-Django上

發布時間:2024/4/17 python 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python自动化开发学习22-Django上 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

session

上節已經講了使用Cookie來做用戶認證,但是
Cookie的問題
缺點:敏感信息不適合放在cookie里,敏感信息只能放在服務器端
優勢:把部分用戶數據分散的存放在每個客戶端,減輕服務端的壓力
Cookie是保存在用戶瀏覽器端的鍵值對,Session是保存在服務器端的鍵值對。
Session依賴Cookie,Cookie保存隨機字符串,憑借這個隨機字符串獲取到服務器端Session里的內容。
用Session來優化用戶登錄:用戶登錄后,生成一個隨機字符串,通過Cookie發送給客戶端保存。服務器端維護一個字典,字典的key就是這個隨機生成的字符串,字典的value是另外一個字典,在服務器端保存各種用戶的敏感信息。
Django的sessiong默認是保存在數據庫中的,所以要使用session需要先執行生成數據庫的2條命令:

python manage.py makemigrations python manage.py migrate

即使你沒有寫任何一張表,也會默認生成一些表,其中 django_session 表中就是存放session信息的。

操作

session里存放的就是鍵值對,所以操作起來也跟字典一樣。隨便寫一個登錄的頁面,用下面的處理函數進行操作:

USER_INFO = {'test': {'pass': "test123"},'user': {'pass': "user123"}, }def login(request):if request.method == "GET":return render(request, 'login.html')elif request.method == 'POST':user = request.POST.get('user')pwd = request.POST.get('pwd')user_obj = USER_INFO.get(user)if user_obj and user_obj.get('pass') == pwd:# 1.生成隨機字符串# 2.寫到用戶瀏覽器Cookie# 3.把隨機字符串作為key保存到session中# 4.設置對應的value# 理論上是要完成上面4個步驟# 但是都封裝好了,用的時候只需要1步,就能完成上面的操作,下面是設置session的值request.session['username'] = userrequest.session['is_login'] = Truereturn redirect('/welcome/')else:return render(request, 'login.html')def welcome(request):# 獲取session的值if request.session.get('is_login'):return HttpResponse('Welcome %s' % request.session['username'])else:return HttpResponse('登錄失敗')

登錄頁面:

<form action="/login/" method="POST"><p><input type="text" name="user" placeholder="用戶名"></p><p><input type="password" name="pwd" placeholder="密碼"></p><p><input type="submit" value="登錄"></p> </form>

上面用到了設置數據的操作和獲取數據的操作。其他的操作方法見下面整理的內容。
獲取、設置、刪除Session中數據:

  • request.session['k1'] :獲取值,如果key不存在會報錯
  • request.session.get('k1',None) :獲取值,如果key不存在,在獲取到默認值。默認值默認是None
  • request.session['k1'] = 123 :設置值
  • request.session.setdefault('k1',123) :設置默認值,就是如果這個key有值就不改變,沒有值就設置為第二個參數的值
  • del request.session['k1'] :刪除值

對所有鍵、值、鍵值對的操作:

  • request.session.keys()
  • request.session.values()
  • request.session.items()
  • request.session.iterkeys()
  • request.session.itervalues()
  • request.session.iteritems()
  • iterkeys 和 keys 的區別,iterkeys 返回一個迭代器,而 keys 返回一個列表。
    其他:

    • request.session.session_key :獲取當前用戶的隨機字符串。但是一般這個用不著,不過是可以獲取到的
    • request.session.clear_expired() :將所有Session失效日期小于當前日期的數據刪除。過期的session,數據庫是沒有自動清除的機制的。不過緩存系統是有的
    • request.session.exists("session_key") :檢查作為參數的隨機字符串在數據庫中是否存在。一般也用不著,因為獲取值的時候已經包含這個判斷了,沒有會返回None
    • request.session.delete("session_key") :刪除參數的Session的所有數據
    • request.session.clear() :刪除當前用戶的所有Session數據。和delete方法比較,delete需要提供session_key。而clear方法會先去獲取到當前用戶的key,然后delete

    request.session.set_expiry(value) :設置超時時間

    • 如果value是個整數,session會在些秒數后失效。
    • 如果value是個datatime或timedelta,session就會在這個時間后失效。
    • 如果value是0,用戶關閉瀏覽器session就會失效。
    • 如果value是None,session會依賴全局session失效策略。

    下面的內容在 Lib/site-packages/django/conf/global_settings.py 這個文件里,是默認配置。要修改的話,就在我們的 settings.py 里設置一個值:

    ############ # SESSIONS # ############# Cache to store session data if using the cache session backend. SESSION_CACHE_ALIAS = 'default' # Cookie name. This can be whatever you want. SESSION_COOKIE_NAME = 'sessionid' # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串 # Age of cookie, in seconds (default: 2 weeks). SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Session的cookie失效日期,這里默認的是2周 # A string like "example.com", or None for standard domain cookie. SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名 # Whether the session cookie should be secure (https:// only). SESSION_COOKIE_SECURE = False # 是否Session的cookie只支持http傳輸 # The path of the session cookie. SESSION_COOKIE_PATH = '/' # Session的cookie保存的路徑 # Whether to use the non-RFC standard httpOnly flag (IE, FF3+, others) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸 # Whether to save the session data on every request. SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都保存Session,默認修改之后才保存 # Whether a user's session cookie expires when the Web browser is closed. SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關閉瀏覽器使得Session過期 # The module to store session data SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 默認引擎 # Directory to store session files if using the file session module. If None, # the backend will use a sensible default. SESSION_FILE_PATH = None # 緩存文件路徑,如果為None,則使用tempfile模塊獲取一個臨時地址 # class to serialize session data SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer'

    CSRF(跨站請求偽造)

    客戶端第一次發起GET請求后,不僅返回了頁面,同時還會返回一串加密字符串。之后客戶端再提交數據的時候,需要把之前收到的字符串一并提交,這樣服務器端的CSRF就會對字符串進行驗證,確認收到的數據是之前發起請求的客戶端提交上來的。
    無CSRF的隱患,如果沒有CSRF,正??蛻舳颂峤粩祿翘峤唤o當前訪問的網站。但是也是可以提交到別的網站去的(你可以提交到任何地方)。雖然你可以提交過去,但是這種方式你沒有目標網站給你的加密字符串的,所以開啟CSRF之后,直接就把這部分請求攔截了。

    開啟CSRF

    django為用戶實現防止跨站請求偽造的功能,通過中間件 django.middleware.csrf.CsrfViewMiddleware 來完成。而對于django中設置防跨站請求偽造功能有分為全局和局部。
    全局,settings.py 文件中的MIDDLEWARE(中間件)里,是一個列表,之前都是先把下面的這行注釋掉的:

    'django.middleware.csrf.CsrfViewMiddleware',

    局部
    導入模塊:from django.views.decorators.csrf import csrf_exempt,csrf_protect
    @csrf_protect :為當前函數強制設置防跨站請求偽造功能,即便settings中沒有設置全局中間件。
    @csrf_exempt :取消當前函數防跨站請求偽造功能,即便settings中設置了全局中間件。

    CSRF Token相關裝飾器在CBV只能加到dispatch方法上
    關于dispatch方法,可以看講CBV時記得筆記:https://blog.51cto.com/steed/2091163
    這里要做的就是繼承父類的dispatch方法,然后加上裝飾器:

    from django.views.decorators.csrf import csrf_exempt, csrf_protectclass HomeView(View):@method_decorator(csrf_exempt)def dispatch(self, request, *args, **kwargs):return super(HomeView, self).dispatch(request, *args, **kwargs)def get(self, request):return render(request, "home.html")def post(self, request):print("Home View POST method...")return redirect("/index/")

    應用-Form方式提交

    第一次請求獲取到的字符串在哪里,如何在提交form表單的時候加上獲取的字符串,從而通過CSRF的驗證。做一個簡單的登錄頁面,上節有,然后去 settings.py 文件里開啟之前一直注釋掉的CSRF,按下面的方式提交:

    <form action="/login/" method="POST">{# 加上下面的標簽就可以了 #}{% csrf_token %}<p><input type="text" name="username" placeholder="用戶名"></p><p><input type="password" name="password" placeholder="密碼"></p><p><input type="submit" value="登錄"></p> </form>

    如果form不帶 csrf_token ,那么會返回403錯誤。這里查看客戶端form標簽內的源碼可以發現,系統幫我們生成了一個隱藏的input標簽

    <input name="csrfmiddlewaretoken" type="hidden" value="I9pZVK6UYWgHHPfUQxju79pWu65xOrb793mpWXON1n4HgeTGzheJ78HHQBgu6cB8">

    應用-Ajax方式提交

    使用Ajax方式提交,需要先獲取到csrf的字符串,客戶端收到服務器端的字符串后,是保存在cookie里的,所以可以到cookie里去獲取到。提交的時候也要帶上這個csrf字符串,加一條請求頭: headers: {'X-CSRFtoken': csrftoken}, 。
    注意:下面的例子里專門導入了一個 jquery.cookie.js 的庫,支持 $.cookie 的方法。這是純前端的做法,如果用模板語言,可以用 ‘{{ csrf_token }}' 直接拿到csrf的字符串。
    在原來的頁面里,添加Ajax請求的按鈕,并且綁定事件。驗證不通過重新加載頁面,驗證通過則用 location.href 頁面跳轉:

    <body> <form action="/login/" method="POST">{% csrf_token %}<p><input type="text" name="user" placeholder="用戶名"></p><p><input type="password" name="pwd" placeholder="密碼"></p><p><input type="submit" value="登錄"><input id="btn" type="button" value="Ajax提交"></p> </form> <script src="/static/js/jquery-1.12.4.js"></script> <script src="/static/js/jquery.cookie.js"></script> <script>$(function () {$('#btn').click(function () {var csrftoken = $.cookie('csrftoken'); // cookie里可能沒有把var csrftoken = ‘{{ csrf_token }}'; // 模板語言里也可以直接拿到var user = $("input[name='user']").val();var pwd = $("input[name='pwd']").val();$.ajax({url: '/login/',type: 'POST',data: {'user': user, 'pwd': pwd, 'ajax': true},// data: {'csrfmiddlewaretoken': '{{ csrf_token }}', 'user': user, 'pwd': pwd, 'ajax': true},// 可以放在headers里,也可以放在data里headers: {'X-CSRFtoken': csrftoken},success: function (arg) {if(arg === 'OK'){location.href = '/welcome/'}else{location.reload()}}})})}) </script> </body>

    處理函數也在原來的基礎上添加。通過 is_ajax = request.POST.get('ajax') 判斷是否是ajax提交的請求。最后在return的時候返回不同的結果,其他都不變:

    def login(request):if request.method == "GET":return render(request, 'login.html')elif request.method == 'POST':user = request.POST.get('user')pwd = request.POST.get('pwd')is_ajax = request.POST.get('ajax')user_obj = USER_INFO.get(user)if user_obj and user_obj.get('pass') == pwd:# 1.生成隨機字符串# 2.寫到用戶瀏覽器Cookie# 3.把隨機字符串作為key保存到session中# 4.設置對應的value# 但是只需要一步,就能完成上面的操作,下面是設置session的值request.session['username'] = userrequest.session['is_login'] = Trueprint(request.session)return HttpResponse('OK') if is_ajax else redirect('/welcome/')else:print('error')return HttpResponse('error') if is_ajax else render(request, 'login.html')

    統一設置ajax的csrf,如果頁面里有多個ajax請求,可以統一進行設置。再或者比如之前的練習,已經寫好了不帶csrf的ajax請求,現在也不要去里面改了,用下面的方法統一加上。就是在ajax發送前,設置請求頭加上X-CSRFtoken這個key并且設置值:

    <script>$(function () {$.ajaxSetup({beforeSend: function (xhr, settings) {// xhr 就是 XHLHttpRequest 是一個對象xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken')) // 設置請求頭}});$('#btn').click(function () {// var csrftoken = $.cookie('csrftoken');var user = $("input[name='user']").val();var pwd = $("input[name='pwd']").val();$.ajax({url: '/login/',type: 'POST',data: {'user': user, 'pwd': pwd, 'ajax': true},// headers: {'X-CSRFtoken': csrftoken},success: function (arg) {if(arg === 'OK'){location.href = '/welcome/'}else{location.reload()}}})})}) </script>

    上面的代碼還要再優化一個,只有POST請求需要加csrf,GET請求是不需要加的。但是在上面的代碼里所有的ajax請求的前面都會在請求頭加上csrf,這里要再做個判斷。除了POST和GET還有其他好幾種請求,一起做判斷:

    <script>function csrfSafeMethod(method) {// 下面的這幾類HTTP請求是不需要加CSRF驗證的,這個是官網的一個例子的用法return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));}$(function () {$.ajaxSetup({beforeSend: function (xhr, settings) {// xhr 就是 XHLHttpRequest 是一個對象// settings 里就是下面的$.ajax({})大括號里的內容,這里要獲取type檢查是否需要加csrfif (!csrfSafeMethod(settings.type) && !this.crossDomain){// 滿足上面的條件才需要設置請求頭xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken')) // 設置請求頭}}});$('#btn').click(function () {// var csrftoken = $.cookie('csrftoken');var user = $("input[name='user']").val();var pwd = $("input[name='pwd']").val();$.ajax({url: '/login/',type: 'POST',data: {'user': user, 'pwd': pwd, 'ajax': true},// headers: {'X-CSRFtoken': csrftoken},success: function (arg) {if(arg === 'OK'){location.href = '/welcome/'}else{location.reload()}}})})}) </script>

    中間件

    在settings.py文件里有一個列表,里面列個各種中間件,包括上面將過的csrf。下面是原始的settings.py文件里的中間件的內容:

    MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware', ]

    用戶發起請求,到請求到達Views之前,首先要通過這寫中間件。這些中間件就是一個類,經過就是要調用這些中間件類里的方法,process_request方法。請求的返回也要先通過這些中間件,調用process_response方法,然后再發送給用戶。
    其他名稱在其他的Web框架里,也有中間件,但是名字可能叫做:管道(Pipeline),HttpHandler。

    自定義中間件

    先以csrf的中間件舉例,代碼中引用的字符串是:'django.middleware.csrf.CsrfViewMiddleware' 。這個就是路徑和類名。
    可以到python的模塊中找到這個文件和類。在 \Lib\site-packages\django\middleware\csrf.py 這個文件里有一個類 class CsrfViewMiddleware(MiddlewareMixin): ,這個類里就有process_request方法和process_response方法。并且可以看到這個類是繼承了MiddlewareMixin這個類的,查看這個父類,可以看到這個類里就是調用上面的2個方法。
    要寫自己的中間件,就是要定義一個類,繼承MiddlewareMixin。并且在類里寫上process_request方法和process_response方法。
    在項目下創建Middle文件夾來存放自定義的中間件,創建m1.py文件:

    from django.utils.deprecation import MiddlewareMixinclass Row1(MiddlewareMixin):def process_request(self, request):print('ROW1_reuquest')def process_response(self, request, response):print('ROW1_response')return responseclass Row2(MiddlewareMixin):def process_request(self, request):print('ROW2_reuquest')def process_response(self, request, response):print('ROW2_response')return response

    上面寫了2個類,就是2個中間件了。然后去setting.py里注冊一下你的中間件:

    MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware','Middle.m1.Row1','Middle.m1.Row2', ]

    現在再訪問你之前的頁面,就能看到中間件print的信息了,并且可以看到觸發的順序:

    ROW1_reuquest ROW2_reuquest [11/Apr/2018 11:24:04] "GET /login/ HTTP/1.1" 200 492 ROW2_response ROW1_response

    先觸發request方法,并且是寫在前面的中間件先觸發。然后再是收到GET請求。最后觸發response方法。
    中間件的應用場景:通過中間件可以對所有的請求做一個統一的操作,比如黑名單過濾。
    中間件中可以定義以下方法:

    • process_request(self, request) :處理請求前最先處理
    • process_view(self, request, callback, callback_args, callback_kwargs) :在process_request全部執行之后執行,還是從上到下
    • process_template_response(self, request, response) :如果views返回對象中有render方法,則會執行
    • process_exception(self, request, exception) :當views里出現異常時觸發。exception就是異常的信息
    • process_response(self, request, response) :返回結果后到客戶端收到響應前處理

    常用的就2個,其他了解一下

    緩存

    由于Django是動態網站,所以每次請求均會去數據進行相應的操作,當程序訪問量大時,耗時必然會更加明顯,最簡單解決方式是使用緩存。緩存是將某個views的返回值保存至內存或者memcache中,5分鐘內(默認設置)再有人來訪問時,則不再去執行views中的函數,而是直接從內存或者Redis中之前緩存的內容拿到,并返回。
    Django中提供了6種緩存方式:

    • 開發調試
    • 內存
    • 文件
    • 數據庫
    • Memcache緩存(python-memcached模塊)
    • Memcache緩存(pylibmc模塊)

    配置

    開發調試以及默認配置
    實際內部不做任何操作,就是調試用的。只有第一個引擎是必須要設置的,其他都有默認配置(上面也是照著默認設的),不寫就是使用默認設置,或者寫上你要修改的設置。其它緩存方式的配置也是一樣的,就是把引擎換一下,再加一個 'LOCATION' 就是緩存存放的位置:

    # 此為開始調試用,實際內部不做任何操作。 # 配置: CACHES = {'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎'TIMEOUT': 300, # 緩存超時時間(默認300,None表示永不過期,0表示立即過期)'OPTIONS': {'MAX_ENTRIES': 300, # 最大緩存個數(默認300,就是5分鐘)'CULL_FREQUENCY': 3, # 緩存到達最大個數之后,剔除緩存個數的比例,即:1/CULL_FREQUENCY(默認1/3)},'KEY_PREFIX': '', # 緩存key的前綴(默認空)'VERSION': 1, # 緩存key的版本(默認1)'KEY_FUNCTION': default_key_func # 生成key的函數(默認函數會生成為:【前綴:版本:key】)} }

    默認的 'KEY_FUNCTION' 是在 Lib\site-packages\django\core\cache\backends\base.py 文件里的default_key_func函數,就是生成一個包含 key_prefix, version, key 這3個變量的字符串返回。這里可以用我們自己的寫的函數生成自己想要的樣式:

    def default_key_func(key, key_prefix, version):"""Default function to generate keys.Construct the key used by all other methods. By default, prependthe `key_prefix'. KEY_FUNCTION can be used to specify an alternatefunction with custom key making behavior."""return '%s:%s:%s' % (key_prefix, version, key)

    內存

    # 此緩存將內容保存至內存的變量中 # 配置: CACHES = {'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache','LOCATION': 'unique-snowflake', # 這個必須是全局唯一的變量名,實際就是在內存中維護一個字典,這個是變量名} }

    文件

    # 此緩存將內容保存至文件 # 配置: 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模塊)

    # 此緩存使用python-memcached模塊連接memcache 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',} } # 或者是使用分布式的memcache CACHES = {'default': {'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache','LOCATION': ['172.19.26.240:11211','172.19.26.242:11211',]} } # 或者是使用分布式的memcache,還可以帶權重(權重是memcache做的) CACHES = {'default': {'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache','LOCATION': [('172.19.26.240:11211', 2),('172.19.26.242:11211', 3),]} }

    Memcache緩存(pylibmc模塊)
    和上面差不多,只是用的是不同的python模塊,所以引擎要變一下。

    # 此緩存使用pylibmc模塊連接memcache 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',]} } # 權重也是有的

    應用

    準備測試環境
    使用文件的形式來測試,在項目下創建一個cache文件夾來存放緩存文件,配置如下:

    CACHES = {'default': {'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache','LOCATION': os.path.join(BASE_DIR, 'cache'), # 緩存文件的路徑} }

    然后寫一個顯示當前時間戳的處理函數:

    def cache(request):import timectime = time.time()return render(request, 'cache.html', {'ctime': ctime})

    頁面只要把時間戳顯示出來:

    <body> <h1>{{ ctime }}</h1> <h1>{{ ctime }}</h1> </body>

    現在訪問頁面會看到一個時間戳,并且刷新頁面時間戳也會刷新,說明沒有走緩存。因為上面我們只是把緩存配置上了,還是還沒應用上。

    全站應用緩存
    這個太粗糙了,下面有更加精細的設置。
    要給所有的請求都應用上緩存,這個功能適合放在中間件里。中間件里需要寫2個中間件
    查緩存,收到用戶請求先查找緩存,如果命中則直接返回緩存的內容。這個中間件要放在后面的位置,只有通過了一系列驗證的中間件后才能給用戶返回數據。
    寫緩存,返回給用戶之前沒有緩存的內容的同時,需要把這個內容寫到緩存里去,那么下次就有緩存了。這個中間件要放在靠前的位置,通過了一系列其他中間件加工之后,把最終返回的內容緩存起來。

    MIDDLEWARE = ['django.middleware.cache.UpdateCacheMiddleware',# 其他中間件...'django.middleware.cache.FetchFromCacheMiddleware', ]# 下面是中間件的設置,主要看超時時間 CACHE_MIDDLEWARE_ALIAS = default CACHE_MIDDLEWARE_SECONDS = 600 # 中間件緩存的超時時間,默認600秒。 CACHE_MIDDLEWARE_KEY_PREFIX = ''

    視圖應用緩存1:處理函數前加裝飾器

    from django.views.decorators.cache import cache_page @cache_page(10) # timeout必填,單位秒 def func(request):pass

    視圖應用緩存2:修改urls.py的

    from django.views.decorators.cache import cache_page urlpatterns = [path('admin/', admin.site.urls),path('cache/', cache_page(5)(views.cache)), ]

    局部視圖緩存:
    就是在模板語言里聲明,頁面里的哪些內容是要應用緩存的

    <body> {#要應用緩存,先load一下cache#} {% load cache %} <h1>{{ ctime }}</h1> {#然后在需要應用緩存的內容的前后加上標簽#} {#下面的c1是自定義的key,這里緩存的值的key貌似無法根據配置自動生成#} {% cache 5 c1 %} <h1>{{ ctime }}</h1> {% endcache %} </body>

    首先要load緩存,然后在要應用緩存的內容前后用標簽包起來。這里需要定義timeout時間和key。
    這個局部的應用場景還是很多的,只緩存頁面中不會頻繁發生變化的內容,而經常會變的內容則不緩存

    補充

    在后面的模塊寫項目的時候遇到了,補充進來:
    在后臺調試緩存
    測試臨時存儲的有失效性的 key 和 value。下面的例子中,在緩存里存了一個值,時間是5秒。有效時間內通過key可以獲取到值,超過了之后,返回就是None。

    G:\>python manage.py shell Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> from django.core.cache import cache >>> cache.set('k1', 'v1', 5) >>> cache.get('k1') 'v1' >>> cache.get('k1') >>>

    超時時間的小結

    在CACHES里可以加上TIMEOUT設置超時時間,這個是引擎的超時時間。要使用緩存首先要設置一個引擎。
    設置完引擎后,就是要應用緩存了。上面介紹了不同顆粒度的應用方式:中間件(全局)、url、視圖函數、局部視圖。每次應用的時候是沒有選擇引擎的,所以貌似引擎只能用CACHES設置好的那一個。但是每個方法都有自己的方式來設置超時時間。
    關于超時時間的優先級,最后使用前測試一下。下面是猜測不是結論,url、視圖函數、局部視圖的優先級應該高于引擎的。中間件和引擎的超時設置都在配置文件里,具體是什么情況最好是測試一下。

    信號

    Django中提供了“信號調度”,用于在框架執行操作時解耦。通俗來講,就是一些動作發生的時候,信號允許特定的發送者去提醒一些接受者。

    Django內置信號

    • Model signals
      • pre_init : django的modal執行其構造方法前,自動觸發
      • post_init : django的modal執行其構造方法后,自動觸發
      • pre_save : django的modal對象保存前,自動觸發
      • post_save : django的modal對象保存后,自動觸發
      • pre_delete : django的modal對象刪除前,自動觸發
      • post_delete : django的modal對象刪除后,自動觸發
      • m2m_changed : django的modal中使用m2m字段操作第三張表(add,remove,clear)前后,自動觸發
      • class_prepared : 程序啟動時,檢測已注冊的app中modal類,對于每一個類,自動觸發
    • Management signals
      • pre_migrate : 執行migrate命令前,自動觸發
      • post_migrate : 執行migrate命令后,自動觸發
    • Request/response signals
      • request_started : 請求到來前,自動觸發
      • request_finished : 請求結束后,自動觸發
      • got_request_exception : 請求異常后,自動觸發
    • Test signals
      • setting_changed : 使用test測試修改配置文件時,自動觸發
      • template_rendered : 使用test測試渲染模板時,自動觸發
    • Database Wrappers
      • connection_created : 創建數據庫連接時,自動觸發

    使用之前先要把對應的模塊導入:

    from django.db.models.signals import pre_init, post_init from django.db.models.signals import pre_save, post_save from django.db.models.signals import pre_delete, post_delete from django.db.models.signals import m2m_changed from django.db.models.signals import class_preparedfrom django.db.models.signals import pre_migrate, post_migratefrom django.core.signals import request_started from django.core.signals import request_finished from django.core.signals import got_request_exceptionfrom django.test.signals import setting_changed from django.test.signals import template_renderedfrom django.db.backends.signals import connection_created

    注冊函數1
    將函數名作為參數完成注冊

    # 導入模塊 from django.core.signals import request_started# 準備好要觸發的函數 def callback(sender, **kwargs):print('callback')print(sender, kwargs)request_started.connect(callback) # 注冊你的函數 # pre_init.connect(callback2) # 可以注冊多個,先注冊的先執行

    注冊函數2
    為函數加上裝飾器也能完成注冊:

    # 導入模塊 from django.core.signals import request_started from django.dispatch import receiver# 準備好要觸發的函數,并且加上裝飾器 @receiver(request_started) def callback(sender, **kwargs):print('callback')print(sender, kwargs)

    自定義信號

    要自定義信號需要3步:

  • 定義信號 :這里單獨創建一個文件(名字隨意比如sg.py)來存放自定義的信號
  • 注冊信號 :定義完成好,直接就注冊吧,注冊方法和注冊內置信號一樣
  • 觸發信號 :在你要觸發的位置,執行一個send()方法。比如下面的例子中是在處理函數中加入了這個信號的觸發
  • 內置信號只需要注冊。而自定義的信號,需要在注冊前先定義好這個信號。之后去你需要的位置加上觸發信號的send()方法:

    # sg.py 里的內容 # 第一步:定義信號 import django.dispatch pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"]) # 這里要求2個參數# 第二步:注冊信號 def callback(sender, **kwargs):print('callback')print(sender, kwargs) pizza_done.connect(callback)# views.py 里的內容,當然可以是任何地方 # 第三步:觸發信號 # 導入信號 from sg import pizza_done def my_sig(request):# 發送信號,第一個參數是發送者,后面是你自定義的函數要求的參數pizza_done.send(sender='seven', topping=123, size=456)

    轉載于:https://blog.51cto.com/steed/2104127

    總結

    以上是生活随笔為你收集整理的Python自动化开发学习22-Django上的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。