程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python入門自學進階-Web框架——20、Django其他相關知識2

編輯:Python

三、緩存

 

緩存是可以在任何地方,如內存、文件、數據庫、其他機器的內存等。

Django提供的緩存機制:

1、開發調試(虛擬緩存)
2、內存  (本地內存)
3、文件
4、數據庫
5、Memcache緩存(python-memcached模塊)    (分布式內存)
6、Memcache緩存(pylibmc模塊)                   (分布式內存)

設置緩存:

緩存系統需要少量的設置。必須知道緩存數據應該放在哪裡 —— 是在數據庫中,還是在文件系統上,或者直接放在內存中。這是一個重要的決定,會影響你的緩存的性能;有些緩存類型比其他類型快。

緩存設置項位於配置文件的緩存配置中。

在settings.py中增加:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎
'TIMEOUT': 300, # 緩存超時時間,默認300,None表示永不過期,0表示立即過期
'OPTIONS': {
'MAX_ENTRIES': 300, # 最大緩存條數,默認300
'CULL_FREQUENCY': 3, # 當達到 MAX_ENTRIES 時,被刪除的條目的比例。實際比例是 1 / CULL_FREQUENCY
},
'KEY_PREFIX': '', # 緩存key的前綴(默認空
'VERSION': 1, # 緩存key的版本,默認1
'KEY_FUNCTION': hanshu_函數名, # 生成key的函數,默認函數會生成:【前綴:版本:key】
}
}

上面是開發調試,即虛擬緩存的配置,其他的緩存,主要是BACKEND的不同:

'django.core.cache.backends.db.DatabaseCache'
'django.core.cache.backends.dummy.DummyCache'
'django.core.cache.backends.filebased.FileBasedCache'
'django.core.cache.backends.locmem.LocMemCache'
'django.core.cache.backends.memcached.PyMemcacheCache'
'django.core.cache.backends.memcached.PyLibMCCache'

另外還有一個重要的配置項是LOCATION,指定緩存的位置。

對於內存緩存,'django.core.cache.backends.locmem.LocMemCache',其LOCATION指定緩存的名字,相當於一個變量名,內存緩存就是內存中的一塊區域,可以看成是一個字典,這裡的LOCATION就是這個字典的名字,‘LOCATION’:‘unique-snowflake’,

對於文件緩存,'django.core.cache.backends.filebased.FileBasedCache',其LOCATION指定緩存的文件夾位置,如'LOCATION': '/var/tmp/django_cache',

對於數據庫緩存,'django.core.cache.backends.db.DatabaseCache',其LOCATION指定緩存的數據庫表名,如‘LOCATION’:‘my_cache_table’,需要執行創建表命令:python manage.py createcachetable

對於Memcache——python-memcached,'django.core.cache.backends.memcached.PyMemcacheCache',其LOCATION指定另外一台機器:

1)‘LOCATION’:‘127.0.0.1:11211’,  以IP和端口方式連接

2)‘LOCATION’:‘unix:/tmp/memcached.sock’,以socket方式連接,一個文件,文件中寫了連接信息,只能連本機。

3)'LOCATION':['172.1.1.1:12211','172.1.1.2:12211',],一個列表指定多台機器,就是集群了,還可以列表中是元組項,指定權重:
'LOCATION':[('172.1.1.1:12211',10),('172.1.1.2:12211',20),],

對於'django.core.cache.backends.memcached.PyLibMCCache'同上面。

應用:主要有全站使用、單獨視圖緩存、局部視圖使用

1、單獨視圖緩存

首先配置settings,然後使用裝飾器cache_page:

# settings中的配置
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': os.path.join(BASE_DIR,'cache'),
}
}

單獨的視圖函數使用裝飾器來使用緩存:

# 後台視圖函數,引入裝飾器,對單獨函數使用緩存
from django.views.decorators.cache import cache_page
@cache_page(20) # 參數代表超時時間,單位是秒
def cache(req):
import time
v = time.time()
print(v)
return HttpResponse(v)

運行後,在文件夾中出現內容了:

 看運行結果:

 第一次請求時,視圖函數運行打印了時間,後來的請求都沒有運行,20秒後,緩存過期,函數又運行了,打印。

2、局部緩存使用,(前端頁面的部分緩存)

使用在模板上,在模板中,先引入模板標簽,即引入TemplateTag:{% load cache %}

然後使用緩存:{% cache 10 緩存key %} 緩存內容 {% endcache %}

視圖函數:

def part(req):
import time
v = time.time()
print(v)
return render(req,'part.html',{'v':v})

前端模板:

{% load cache %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{
{ v }}</h1>
{% cache 20 key-11 %}
<h3>{
{ v }}</h3>
{% endcache %}
</body>
</html>

這裡會緩存<h3>的內容,在緩存中,其鍵的值會是“:1:key-11”。

訪問時:在緩存時間內,H1數據一直變化,H3是不變的,這個數據從緩存中來。

 後台的打印結果:

每次請求都打印,即都執行了函數,說明函數沒有緩存。 

3、全站使用,(要使用中間件)

一般使用兩個中間件,一個放在中間件鏈的開始,一個放在最後,放在最後的中間件,執行process_request,放在第一個的中間件,執行process_response。

這樣放的理由:一個請求的到來,是需要經過所有process_request的,相當於過安檢,安檢過後,才能判斷是否在緩存中,也就是在執行視圖函數前判斷緩存,如果不放在最後一個,有可能安檢不通過也能獲取數據了,這是放在最後中間件的原因,這個中間件是取緩存的功能,還要有一個中間件放在第一位置,主要執行數據的緩存功能,是執行process_response,這是因為對於返回的內容,其他中間件有可能會進行修改,如果不是第一個,就不是最後執行process_response的中間件,所緩存的內容可能不是最終的內容。(一定要與前面中間件的執行順序相結合進行理解)。

這兩個中間件一個是'django.middleware.cache.UpdateCacheMiddleware'——更新緩存內容,實現內容的緩存和'django.middleware.cache.FetchFromCacheMiddleware'——從緩存中獲取內容。

配置如下:

MIDDLEWARE = [
        'django.middleware.cache.UpdateCacheMiddleware',
        # 其他中間件。。。
        'django.middleware.cache.FetchFromCacheMiddleware',
]

這樣配置後,全站緩存就啟用了。

這時再訪問前面的part頁面時,H1和H3的內容都不變了,都進行了緩存。

 四、信號(Django預留的鉤子)

Django有一個“信號調度器(signal dispatcher)”,用來幫助解耦的應用獲知框架內任何其他地方發生了操作。簡單地說,信號允許某些 發送器 去通知一組 接收器 某些操作發生了。當許多代碼段都可能對同一事件感興趣時,信號特別有用。

內置信號集 使用戶代碼能夠獲得 Django 自身某些操作的通知

內置信號:

Model signals
    pre_init                 # django的model執行其構造方法前,自動觸發
    post_init               # django的model執行其構造方法後,自動觸發
    pre_save             # django的model對象保存前,自動觸發
    post_save            # django的model對象保存後,自動觸發
    pre_delete            # django的model對象刪除前,自動觸發
    post_delete          # django的model對象刪除後,自動觸發
    m2m_changed     # django的model中使用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          # 創建數據庫連接時,自動觸發

對於Django內置的信號,僅需注冊指定信號,當程序執行相應操作時,自動觸發注冊函數:

from django.core.signals import request_finished
from django.core.signals import request_started
from django.core.signals import got_request_exception

from django.db.models.signals import class_prepared
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 pre_migrate, post_migrate

from django.test.signals import setting_changed
from django.test.signals import template_rendered

from django.db.backends.signals import connection_created


def callback(sender, **kwargs):
    print("xxoo_callback")
    print(sender,kwargs)

xxoo.connect(callback)
# xxoo指上述導入的內容,即pre_init、post_init等,如pre_init.connect(callback)

注冊的時機,因為是要對所有的一類操作進行信號處理,所有要程序一運行就要注冊上去。所以一般寫在應用的__init__.py中。

啟動項目,會打印:

xxoo_callback
<class 'django.db.backends.sqlite3.base.DatabaseWrapper'> {'signal': <django.dispatch.dispatcher.Signal object at 0x000000000B796160>, 'connection': <django.db.backends.sqlite3.base.DatabaseWrapper object at 0x000000000AD99C50>} 

測試model的信號pre_init和post_init:

創建models類:

from django.db import models
# Create your models here.
from django.db import models
class User(models.Model):
username = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)

注冊信號:

from django.db.backends.signals import connection_created
from django.core.signals import request_finished
from django.core.signals import request_started
from django.core.signals import got_request_exception
from django.db.models.signals import class_prepared
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 pre_migrate, post_migrate
from django.test.signals import setting_changed
from django.test.signals import template_rendered
def callback(sender,**kwargs):
print("xxoo_callback")
print(sender,"-----",kwargs)
def callback2(sender,**kwargs):
print("xxoo_callback2")
print(sender,"-----",kwargs)
connection_created.connect(callback)
pre_init.connect(callback)
post_init.connect(callback2)

視圖函數:

def signal(req):
from midwares import models
oo = models.User(username='root',pwd='123')
return HttpResponse('ok')

urls中增加 : path('signal/',views.signal),

前端訪問signal:打印結果

xxoo_callback
<class 'midwares.models.User'> ----- {'signal': <django.db.models.signals.ModelSignal object at 0x000000000AFF3198>, 'args': (), 'kwargs': {'username': 'root', 'pwd': '123'}}
xxoo_callback2
<class 'midwares.models.User'> ----- {'signal': <django.db.models.signals.ModelSignal object at 0x000000000AFF34A8>, 'instance': <User: User object (None)>}

對於callback,是pre_init信息注冊的,在實例化前執行,sender是<class 'midwares.models.User'>,說明是User類觸發的信號,參數中args是位置參數,這裡沒有傳遞位置參數,kwargs是我們創建User類對象時傳遞的參數,username=root,pwd=123,這些就可以在實例化前進行記錄。

對於callback2,是實例化後執行的,參數instance是實例化後的對象

以上是Django定義的內置信號,下面我們自定義自己的信號:

1)定義信號:
import django.dispatch
pizza_done = django.dispatch.Singnal(providing_args=["toppings","size"])

def mysignal(req):
from midwares import pizza_done # 從應用的__init__.py模塊中引入,只需寫應用的名,不必加__init__
pizza_done.send(sender='調用者',toppings='123',size='456') # 自定義的信號,需要自己主動觸發,觸發就是調用send方法
return HttpResponse('ok')

2)注冊信號:
def callback(sender,**kwargs):
        print("callback")
        print(sender,kwargs)

pizza_done.connect(callback)

3)觸發信號:
from 路徑 import pizza_done
pizza_done.send(sender='seven',toppings=123,size=456)

示例測試:

在__init__.py中定義信號和注冊信號:

# 以下是定義信號
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=['toppings','size'])
# 定義回調函數,注冊信號
def callback3(sender,**kwargs):
print("自定義信號callback3")
print(sender,kwargs)
pizza_done.connect(callback3)

觸發信號:在視圖函數中需要自己觸發

def mysignal(req):
from midwares import pizza_done # 從應用的__init__.py模塊中引入,只需寫應用的名,不必加__init__
pizza_done.send(sender='調用者',toppings='123',size='456') # 自定義的信號,需要自己主動觸發,觸發就是調用send方法
return HttpResponse('ok')

運行結果:

自定義信號callback3
調用者 {'signal': <django.dispatch.dispatcher.Signal object at 0x000000000B786198>, 'toppings': '123', 'size': '456'}

應用場景:預留插拔接口,如某操作後,需要發送提醒,一開始是短信,後來增加郵件,在增加微信、QQ等,這時使用信號,只要增加callback函數,注冊信號就行。

五、BootStrap,集成了css、js一個文件夾  ---   響應式+模板

css:在前端網頁中引入相應的css,在head中:<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css" >

響應式:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bootstrap-5.1.3-dist/css/bootstrap.css">
<style>
.pg-header{
height: 48px;
background-color: black;
}
@media (max-width: 700px) {
.extra{
background-color: yellow;
}
}
</style>
</head>
<body>
<div class="pg-header extra"></div>
</body>
</html>

 

 上面的頁面,隨著浏覽器窗口寬度的變化,在700px以上,div的背景是黑色,縮小的700px以下時,背景變為黃色。這就是響應式。主要是使用@media,bootstrap中的container就是響應式容器

bootstrap中提供了柵格的樣式:col-sm-xx,col-md-xx

js:需要先引入jQuery,然後引入bootstrap.js


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved