The Django Book

Chapter 13: Caching

绗崄涓夌珷 缂撳瓨鏈哄埗

Static Web sites, in which simple files are served directly to the Web, scale like crazy. But a fundamental tradeoff in dynamic Web sites is, well, theyre dynamic. Each time a user requests a page, the Web server makes all sorts of calculationsfrom database queries, to template rendering, to business logic to create the page that your sites visitor sees. From a processing-overhead perspective, this is quite expensive.

闈欐佺殑缃戠珯鐨勫唴瀹归兘鏄簺绠鍗曠殑闈欐佺綉椤电洿鎺ュ瓨鍌ㄥ湪鏈嶅姟鍣ㄤ笂锛屽彲浠ラ潪甯稿鏄撳湴杈惧埌闈炲父鎯婁汉鐨勮闂噺銆備絾鏄姩鎬佺綉绔欏洜涓烘槸鍔ㄦ佺殑锛屼篃灏辨槸璇存瘡娆$敤鎴疯闂竴涓〉闈紝鏈嶅姟鍣ㄨ鎵ц鏁版嵁搴撴煡璇紝鍚姩妯℃澘锛屾墽琛屼笟鍔¢昏緫鍒版渶缁堢敓鎴愪竴涓綘鎵鐪嬪埌鐨勭綉椤碉紝杩欎竴鍒囬兘鏄姩鎬佸嵆鏃剁敓鎴愮殑銆備粠澶勭悊鍣ㄨ祫婧愮殑瑙掑害鏉ョ湅锛岃繖鏄瘮杈冩槀璐电殑銆

For most Web applications, this overhead isnt a big deal. Most Web applications arent washingtonpost.com or Slashdot; theyre simply small- to medium-sized sites with so-so traffic. But for medium- to high-traffic sites, its essential to cut as much overhead as possible. Thats where caching comes in.

瀵逛簬澶у鏁扮綉缁滃簲鐢ㄦ潵璇达紝杩囪浇骞朵笉鏄ぇ闂銆傚洜涓哄ぇ澶氭暟缃戠粶搴旂敤骞朵笉鏄痺ashingtonpost.com鎴朣lashdot锛涘畠浠氬父鏄緢灏忓緢绠鍗曪紝鎴栬呮槸涓瓑瑙勬ā鐨勭珯鐐癸紝鍙湁寰堝皯鐨勬祦閲忋備絾鏄浜庝腑绛夎嚦澶ц妯℃祦閲忕殑绔欑偣鏉ヨ锛屽敖鍙兘鍦拌В鍐宠繃杞介棶棰樻槸闈炲父蹇呰鐨勩傝繖灏遍渶瑕佺敤鍒扮紦瀛樹簡銆

To cache something is to save the result of an expensive calculation so that you dont have to perform the calculation next time. Heres some pseudocode explaining how this would work for a dynamically generated Web page:

缂撳瓨鐨勭洰鐨勬槸涓轰簡閬垮厤閲嶅璁$畻锛岀壒鍒槸瀵逛竴浜涙瘮杈冭楁椂闂淬佽祫婧愮殑璁$畻銆備笅闈㈢殑浼唬鐮佹紨绀轰簡濡備綍瀵瑰姩鎬侀〉闈㈢殑缁撴灉杩涜缂撳瓨銆

given a URL, try finding that page in the cache
if the page is in the cache:
    return the cached page
else:
    generate the page
    save the generated page in the cache (for next time)
    return the generated page

Django comes with a robust cache system that lets you save dynamic pages so they dont have to be calculated for each request. For convenience, Django offers different levels of cache granularity. You can cache the response of specific views, you can cache only the pieces that are difficult to produce, or you can cache your entire site.

涓烘锛孌jango鎻愪緵浜嗕竴涓ǔ瀹氱殑缂撳瓨绯荤粺璁╀綘缂撳瓨鍔ㄦ侀〉闈㈢殑缁撴灉锛岃繖鏍峰湪鎺ヤ笅鏉ユ湁鐩稿悓鐨勮姹傚氨鍙互鐩存帴浣跨敤缂撳瓨涓殑鏁版嵁锛岄伩鍏嶄笉蹇呰鐨勯噸澶嶈绠椼傚彟澶朌jango杩樻彁渚涗簡涓嶅悓绮掑害鏁版嵁鐨勭紦瀛橈紝渚嬪锛氫綘鍙互缂撳瓨鏁翠釜椤甸潰锛屼篃鍙互缂撳瓨鏌愪釜閮ㄥ垎锛岀敋鑷崇紦瀛樻暣涓綉绔欍

Django also works well with upstream caches, such as Squid (http://www.squid-cache.org/) and browser-based caches. These are the types of caches that you dont directly control but to which you can provide hints (via HTTP headers) about which parts of your site should be cached, and how.

Django涔熷拰”涓婃父”缂撳瓨宸ヤ綔鐨勫緢濂斤紝渚嬪Squid(http://www.squid-cache.org)鍜屽熀浜庢祻瑙堝櫒鐨勭紦瀛橈紝杩欎簺绫诲瀷鐨勭紦瀛樹綘涓嶇洿鎺ユ帶鍒讹紝浣嗘槸浣犲彲浠ユ彁渚涘叧浜庝綘鐨勭珯鐐瑰摢閮ㄥ垎搴旇琚紦瀛樺拰鎬庢牱缂撳瓨鐨勭嚎绱(閫氳繃HTTP澶撮儴)缁欏畠浠

Read on to discover how to use Djangos caching system. When your site gets Slashdotted youll be happy you understand this material.

缁х画闃呰鏉ョ爺绌跺浣曚娇鐢―jango鐨勭紦瀛樼郴缁熴傚綋浣犵殑缃戠珯鍙樻垚璞lashdot鐨勬椂鍊欙紝浣犱細寰堝緢楂樺叴鐞嗚В浜嗚繖閮ㄥ垎鏉愭枡

Setting Up the Cache

璁惧畾缂撳瓨

The cache system requires a small amount of setup. Namely, you have to tell it where your cached data should live, whether in a database, on the filesystem, or directly in memory. This is an important decision that affects your caches performance (yes, some cache types are faster than others). In-memory caching will generally be much faster than filesystem or database caching, because it lacks the overhead of hitting the filesystem or database.

缂撳瓨绯荤粺闇瑕佷竴浜涘皯閲忕殑璁惧畾宸ヤ綔锛屽嵆浣犲繀闇鍛婅瘔瀹冧綘鐨勭紦瀛樻暟鎹湪鍝噷—鍦ㄦ暟鎹簱锛屾枃浠剁郴缁熸垨鑰呯洿鎺ュ湪鍐呭瓨涓紝杩欐槸褰卞搷浣犵殑缂撳瓨鎬ц兘鐨勯噸瑕佸喅瀹氾紝鏄殑锛屼竴浜涚紦瀛樼被鍨嬭姣斿叾瀹冪殑蹇紝鍐呭瓨缂撳瓨閫氬父姣旀枃浠剁郴缁熸垨鏁版嵁搴撶紦瀛樺揩锛屽洜涓哄墠鑰呮病鏈夎闂枃浠剁郴缁熸垨鏁版嵁搴撶殑杩囧害杩炴帴

Your cache preference goes in the CACHE_BACKEND setting in your settings file. If you use caching and do not specify CACHE_BACKEND , Django will use simple:/// by default. The following sections explain all available values for CACHE_BACKEND .

浣犵殑缂撳瓨閫夋嫨鍦ㄤ綘鐨剆ettings鏂囦欢鐨 CACHE_BACKEND 璁剧疆涓紝濡傛灉浣犱娇鐢ㄧ紦瀛樹絾娌℃湁鎸囧畾 CACHE_BACKEND 锛孌jango灏嗛粯璁や娇鐢 simple:/// 锛屼笅闈㈠皢瑙i噴 CACHE_BACKEND 鐨勬墍鏈夊彲寰楀埌鐨勫

Memcached

鍐呭瓨缂撳啿

By far the fastest, most efficient type of cache available to Django, Memcached is an entirely memory-based cache framework originally developed to handle high loads at LiveJournal (http://www.livejournal.com/) and subsequently open-sourced by Danga Interactive (http://danga.com/). Its used by sites such as Slashdot and Wikipedia to reduce database access and dramatically increase site performance.

鐩墠涓烘Django鍙緱鍒扮殑鏈蹇殑鏈楂樻晥鐨勭紦瀛樼被鍨嬫槸鍩轰簬鍐呭瓨鐨勭紦瀛樻鏋禡emcached锛屽畠璧峰垵寮鍙戞潵涓篖iveJournal.com澶勭悊楂樿礋鑽峰苟闅忓悗琚獶anga Interactive(http://www.danga.com)寮婧愶紝瀹冭Slashdot鍜學ikipedia绛夌珯鐐归噰鐢ㄤ互鍑忓皯鏁版嵁搴撹闂苟鏋佸ぇ鐨勬彁鍗囦簡绔欑偣鎬ц兘

Memcached is available for free at http://danga.com/memcached/. It runs as a daemon and is allotted a specified amount of RAM. Its primary feature is to provide an interfacea super-lightning-fast interfacefor adding, retrieving, and deleting arbitrary data in the cache. All data is stored directly in memory, so theres no overhead of database or filesystem usage.

Memcached鍙互鍦╤ttp://danga.com/memcached/鍏嶈垂寰楀埌锛屽畠浣滀负鍚庡彴杩涚▼杩愯骞跺垎閰嶄竴涓寚瀹氭暟閲忕殑RAM.瀹冭兘涓轰綘鎻愪緵鍦ㄧ紦瀛樹腑*濡傞棯鐢佃埇蹇熺殑*娣诲姞锛岃幏鍙栧拰鍒犻櫎浠绘剰鏁版嵁锛屾墍鏈夌殑鏁版嵁鐩存帴瀛樺偍鍦ㄥ唴瀛樹腑锛屾墍浠ユ病鏈夋暟鎹簱鍜屾枃浠剁郴缁熶娇鐢ㄧ殑杩囧害浣跨敤

After installing Memcached itself, youll need to install the Memcached Python bindings, which are not bundled with Django directly. These bindings are in a single Python module, memcache.py , which is available at http://www.tummy.com/Community/software/python-memcached/.

鍦ㄥ畨瑁呬簡Memcached鏈韩涔嬪悗锛屼綘灏嗛渶瑕佸畨瑁匨emcached Python缁戝畾锛屽畠娌℃湁鐩存帴鍜孌jango缁戝畾锛岃繖浜涚粦瀹氬湪涓涓崟鐙殑Python妯″潡涓紝’memcache.py’锛屽彲浠ュ湪http://www.djangoproject.com/thirdparty/python-memcached寰楀埌

To use Memcached with Django, set CACHE_BACKEND to memcached://ip:port/ , where ip is the IP address of the Memcached daemon and port is the port on which Memcached is running.

璁剧疆 CACHE_BACKENDmemcached://ip:port/ 鏉ヨDjango浣跨敤Memcached锛岃繖閲岀殑 ip 鏄疢emcached鍚庡彴杩涚▼鐨処P鍦板潃锛 port 鍒欐槸Memcached杩愯鎵鍦ㄧ殑绔彛

In this example, Memcached is running on localhost (127.0.0.1) port 11211:

鍦ㄨ繖涓緥瀛愪腑锛孧emcached杩愯鍦ㄦ湰鍦颁富鏈 (127.0.0.1)涓,绔彛涓11211锛

CACHE_BACKEND = 'memcached://127.0.0.1:11211/'

One excellent feature of Memcached is its ability to share cache over multiple servers. This means you can run Memcached daemons on multiple machines, and the program will treat the group of machines as a single cache, without the need to duplicate cache values on each machine. To take advantage of this feature with Django, include all server addresses in CACHE_BACKEND , separated by semicolons.

Memcached鐨勪竴涓瀬濂界殑鐗规ф槸瀹冨湪澶氫釜鏈嶅姟鍣ㄥ垎浜紦瀛樼殑鑳藉姏锛岃繖鎰忓懗鐫浣犲彲浠ュ湪澶氬彴鏈哄櫒涓婅繍琛孧emcached杩涚▼锛岀▼搴忓皢浼氭妸杩欑粍鏈哄櫒褰撲綔涓涓*鍗曠嫭鐨*缂撳瓨锛岃屼笉闇瑕佸湪姣忓彴鏈哄櫒涓婂鍒剁紦瀛樺硷紝涓轰簡璁〥jango鍒╃敤姝ょ壒鎬э紝闇瑕佸湪CACHE_BACKEND閲屽寘鍚墍鏈夌殑鏈嶅姟鍣ㄥ湴鍧骞剁敤鍒嗗彿鍒嗛殧

In this example, the cache is shared over Memcached instances running on the IP addresses 172.19.26.240 and 172.19.26.242, both of which are on port 11211:

杩欎釜渚嬪瓙涓紝缂撳瓨鍦ㄨ繍琛屽湪172.19.26.240鍜172.19.26.242鐨処P鍦板潃鍜11211绔彛鐨凪emcached瀹炰緥闂村垎浜:

CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/'

In the following example, the cache is shared over Memcached instances running on the IP addresses 172.19.26.240 (port 11211), 172.19.26.242 (port 11212), and 172.19.26.244 (port 11213):

杩欎釜渚嬪瓙涓紝缂撳瓨鍦ㄨ繍琛屽湪172.19.26.240(绔彛11211)锛172.19.26.242(绔彛11212)锛172.19.26.244(绔彛11213)鐨凪emcached瀹炰緥闂村垎浜:

CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11212;172.19.26.244:11213/'

A final point about Memcached is that memory-based caching has one important disadvantage. Because the cached data is stored only in memory, the data will be lost if your server crashes. Clearly, memory isnt intended for permanent data storage, so dont rely on memory-based caching as your only data storage. Without a doubt, none of the Django caching back-ends should be used for permanent storagetheyre all intended to be solutions for caching, not storagebut we point this out here because memory-based caching is particularly temporary.

鏈鍚庡叧浜嶮emcached鐨勬槸鍩轰簬鍐呭瓨鐨勭紦瀛樻湁涓涓噸澶х殑缂虹偣锛屽洜涓虹紦瀛樻暟鎹彧瀛樺偍鍦ㄥ唴瀛樹腑锛屽垯濡傛灉鏈嶅姟鍣ㄦ鏈虹殑璇濇暟鎹細涓㈠け锛屾樉鐒跺唴瀛樹笉鏄负鎸佷箙鏁版嵁瀛樺偍鍑嗗鐨勶紝Django娌℃湁涓涓紦瀛樺悗绔槸鐢ㄦ潵鍋氭寔涔呭瓨鍌ㄧ殑锛屽畠浠兘鏄紦瀛樻柟妗堬紝鑰屼笉鏄瓨鍌.浣嗘槸鎴戜滑鍦ㄨ繖閲屾寚鍑烘槸鍥犱负鍩轰簬鍐呭瓨鐨勭紦瀛樼壒鍒殑鐭殏 .

Database Caching

鏁版嵁搴撶紦瀛

To use a database table as your cache back-end, create a cache table in your database and point Djangos cache system at that table.

涓轰簡灏嗘暟鎹簱琛ㄤ綔涓虹紦瀛樺悗绔紝闇瑕佸湪鏁版嵁搴撲腑鍒涘缓涓涓紦瀛樿〃骞跺皢Django鐨勭紦瀛樼郴缁熸寚鍚戣琛

First, create a cache table by running this command:

棣栧厛,浣跨敤濡備笅璇彞鍒涘缓涓涓紦瀛樼敤鏁版嵁琛:

python manage.py createcachetable [cache_table_name]

where [cache_table_name] is the name of the database table to create. This name can be whatever you want, as long as its a valid table name thats not already being used in your database. This command creates a single table in your database that is in the proper format Djangos database-cache system expects.

杩欓噷鐨刐cache_table_name]鏄鍒涘缓鐨勬暟鎹簱琛ㄥ悕锛屽悕瀛楀彲浠ユ槸浠讳綍浣犳兂瑕佺殑锛屽彧瑕佸畠鏄悎娉曠殑鍦ㄤ綘鐨勬暟鎹簱涓病鏈夎浣跨敤锛岃繖涓懡浠ゅ湪浣犵殑鏁版嵁搴撳垱寤轰竴涓伒寰狣jango鐨勬暟鎹簱缂撳瓨绯荤粺鏈熸湜褰㈠紡鐨勫崟鐙殑琛.

Once youve created that database table, set your CACHE_BACKEND setting to "db://tablename" , where tablename is the name of the database table. In this example, the cache tables name is my_cache_table :

涓鏃︿綘鍒涘缓浜嗘暟鎹簱琛紝璁剧疆浣犵殑CACHE_BACKEND璁剧疆涓”db://tablename”锛岃繖閲岀殑tablename鏄暟鎹簱琛ㄧ殑鍚嶅瓧锛屽湪杩欎釜渚嬪瓙涓紝缂撳瓨琛ㄥ悕涓簃y_cache_table:

CACHE_BACKEND = 'db://my_cache_table'

The database caching back-end uses the same database as specified in your settings file. You cant use a different database back-end for your cache table.

鏁版嵁搴撶紦瀛樺悗绔娇鐢ㄤ綘鐨剆ettings鏂囦欢鎸囧畾鐨勫悓涓鏁版嵁搴擄紝浣犱笉鑳戒负浣犵殑缂撳瓨琛ㄤ娇鐢ㄤ笉鍚岀殑鏁版嵁搴撳悗绔.

Filesystem Caching

鏂囦欢绯荤粺缂撳瓨

To store cached items on a filesystem, use the "file://" cache type for CACHE_BACKEND , specifying the directory on your filesystem that should store the cached data.

浣跨敤”file://“缂撳瓨绫诲瀷浣滀负CACHE_BACKEND骞舵寚瀹氬瓨鍌ㄧ紦瀛樻暟鎹殑鏂囦欢绯荤粺鐩綍鏉ュ湪鏂囦欢绯荤粺瀛樺偍缂撳瓨鏁版嵁.

For example, to store cached data in /var/tmp/django_cache , use this setting:

渚嬪锛屼娇鐢ㄤ笅闈㈢殑璁剧疆鏉ュ湪/var/tmp/django_cache瀛樺偍缂撳瓨鏁版嵁:

CACHE_BACKEND = 'file:///var/tmp/django_cache'

Note that there are three forward slashes toward the beginning of the preceding example. The first two are for file:// , and the third is the first character of the directory path, /var/tmp/django_cache . If youre on Windows, put the drive letter after the file:// , like so:: file://c:/foo/bar .

娉ㄦ剰渚嬪瓙涓紑澶存湁涓変釜鍓嶆枩绾匡紝鍓嶄袱涓槸file://锛岀涓変釜鏄洰褰曡矾寰勭殑绗竴涓瓧绗︼紝/var/tmp/django_cache锛屽鏋滀綘浣跨敤Windows绯荤粺锛屾妸鐩樼瀛楁瘝鏀惧湪file://鍚庨潰锛屽儚杩欐牱:’file://c:/foo/bar‘.

The directory path should be absolute that is, it should start at the root of your filesystem. It doesnt matter whether you put a slash at the end of the setting.

鐩綍璺緞搴旇鏄*缁濆*璺緞锛屽嵆搴旇浠ヤ綘鐨勬枃浠剁郴缁熺殑鏍瑰紑濮嬶紝浣犲湪璁剧疆鐨勭粨灏炬斁缃枩绾夸笌鍚︽棤鍏崇揣瑕.

Make sure the directory pointed to by this setting exists and is readable and writable by the system user under which your Web server runs. Continuing the preceding example, if your server runs as the user apache , make sure the directory /var/tmp/django_cache exists and is readable and writable by the user apache .

纭璇ヨ缃寚鍚戠殑鐩綍瀛樺湪骞朵笖浣犵殑Web鏈嶅姟鍣ㄨ繍琛岀殑绯荤粺鐨勭敤鎴峰彲浠ヨ鍐欒鐩綍锛岀户缁笂闈㈢殑渚嬪瓙锛屽鏋滀綘鐨勬湇鍔″櫒浠ョ敤鎴穉pache杩愯锛岀‘璁/var/tmp/django_cache瀛樺湪骞朵笖鐢ㄦ埛apache鍙互璇诲啓/var/tmp/django_cache鐩綍

Each cache value will be stored as a separate file whose contents are the cache data saved in a serialized (pickled) format, using Pythons pickle module. Each files name is the cache key, escaped for safe filesystem use.

姣忎釜缂撳瓨鍊煎皢琚瓨鍌ㄤ负鍗曠嫭鐨勬枃浠讹紝鍏跺唴瀹规槸Python鐨刾ickle妯″潡浠ュ簭鍒楀寲(“pickled”)褰㈠紡淇濆瓨鐨勭紦瀛樻暟鎹紝姣忎釜鏂囦欢鐨 鏂囦欢鍚嶆槸缂撳瓨閿紝浠ヨ閬垮紑瀹夊叏鏂囦欢绯荤粺鐨勪娇鐢

Local-Memory Caching

鏈湴鍐呭瓨缂撳瓨

If you want the speed advantages of in-memory caching but dont have the capability of running Memcached, consider the local-memory cache back-end. This cache is per-process and thread-safe, but it isnt as efficient as Memcached due to its simplistic locking and memory allocation strategies.

濡傛灉浣犳兂瑕佸唴瀛樼紦瀛樼殑閫熷害浼樺娍浣嗘病鏈夎兘鍔涜繍琛孧emcached锛屽彲浠ヨ冭檻浣跨敤鏈湴瀛樺偍鍣ㄧ紦瀛樺悗绔紝璇ョ紦瀛樻槸澶氱嚎绋嬪拰绾跨▼瀹夊叏 鐨勶紝浣嗘槸鐢变簬鍏剁畝鍗曠殑閿佸拰鍐呭瓨鍒嗛厤绛栫暐瀹冩病鏈塎emcached楂樻晥

To use it, set CACHE_BACKEND to 'locmem:///' , for example:

璁剧疆 CACHE_BACKENDlocmem:/// 鏉ヤ娇鐢ㄥ畠锛屼緥濡:

CACHE_BACKEND = 'locmem:///'

Simple Caching (for Development)

绠鏄撶紦瀛橈紙鐢ㄤ簬寮鍙戦樁娈碉級

A simple, single-process memory cache is available as 'simple:///' , for example:

鍙互閫氳繃閰嶇疆 'simple:///' 鏉ヤ娇鐢ㄤ竴涓畝鍗曠殑鍗曡繘绋嬪唴瀛樼紦瀛橈紝渚嬪锛

CACHE_BACKEND = 'simple:///'

This cache merely saves cached data in process, which means it should be used only in development or testing environments.

杩欎釜缂撳瓨浠呬粎鏄皢鏁版嵁淇濆瓨鍦ㄨ繘绋嬪唴锛屽洜姝ゅ畠搴旇鍙湪寮鍙戠幆澧冩垨娴嬭瘯鐜涓娇鐢.

Dummy Caching (for Development)

浠跨紦瀛橈紙渚涘紑鍙戞椂浣跨敤锛

Finally, Django comes with a dummy cache that doesnt actually cache; it just implements the cache interface without doing anything.

鏈鍚庯紝Django鎻愪緵涓涓亣缂撳瓨鐨勮缃細瀹冧粎浠呭疄鐜颁簡缂撳瓨鐨勬帴鍙h屼笉鍋氫换浣曞疄闄呯殑浜嬫儏

This is useful if you have a production site that uses heavy-duty caching in various places and a development/test environment on which you dont want to cache. In that case, set CACHE_BACKEND to 'dummy:///' in the settings file for your development environment, for example:

杩欐槸涓湁鐢ㄧ殑鐗规э紝濡傛灉浣犵殑绾夸笂绔欑偣浣跨敤浜嗗緢澶氭瘮杈冮噸鐨勭紦瀛橈紝鑰屽湪寮鍙戠幆澧冧腑鍗翠笉鎯充娇鐢ㄧ紦瀛橈紝閭d箞浣犲彧瑕佷慨鏀归厤缃枃浠讹紝灏 CACHE_BACKEND 璁剧疆涓 'dummy:///' 灏卞彲浠ヤ簡锛屼緥濡傦細

CACHE_BACKEND = 'dummy:///'

As a result, your development environment wont use caching, but your production environment still will.

杩欐牱鐨勭粨鏋滃氨鏄綘鐨勫紑鍙戠幆澧冩病鏈変娇鐢ㄧ紦瀛橈紝鑰岀嚎涓婄幆澧冧緷鐒跺湪浣跨敤缂撳瓨.

CACHE_BACKEND Arguments

CACHE_BACKEND鍙傛暟

Each cache back-end may take arguments. Theyre given in query-string style on the CACHE_BACKEND setting. Valid arguments are as follows:

姣忎釜缂撳瓨鍚庣閮藉彲鑳戒娇鐢ㄥ弬鏁帮紝瀹冧滑鍦–ACHE_BACKEND璁剧疆涓互鏌ヨ瀛楃涓插舰寮忕粰鍑猴紝鍚堟硶鐨勫弬鏁颁负:

timeout : The default timeout, in seconds, to use for the cache. This argument defaults to 300 seconds (5 minutes).

timeout:鐢ㄤ簬缂撳瓨鐨勮繃鏈熸椂闂达紝浠ョ涓哄崟浣嶃傝繖涓弬鏁伴粯璁よ璁剧疆涓300绉掞紙浜斿垎閽燂級

max_entries : For the simple, local-memory, and database back-ends, the maximum number of entries allowed in the cache before old values are deleted. This argument defaults to 300.

max_entries : 瀵逛簬simple, local-memory涓巇atabase绫诲瀷鐨勭紦瀛,杩欎釜鍙傛暟鏄寚瀹氱紦瀛樹腑瀛樻斁鐨勬渶澶ф潯鐩暟锛屽ぇ浜庤繖涓暟鏃讹紝鏃х殑鏉$洰灏嗕細琚垹闄ゃ傝繖涓弬鏁伴粯璁ゆ槸300.

cull_frequency : The ratio of entries that are culled when max_entries is reached. The actual ratio is 1/cull_frequency , so set cull_frequency=2 to cull half of the entries when max_entries is reached.

cull_frequency :褰撹揪鍒 max_entries 鐨勬椂鍊,琚帴鍙楃殑璁块棶鐨勬瘮鐜囥傚疄闄呯殑姣旂巼鏄 1/cull_frequency ,鎵浠ヨ缃甤ull_frequency=2灏辨槸鍦ㄨ揪鍒 max_entries 鐨勬椂鍊欏幓闄や竴鍗婃暟閲忕殑缂撳瓨

A value of 0 for cull_frequency means that the entire cache will be dumped when max_entries is reached. This makes culling much faster at the expense of more cache misses. This argument defaults to 3.

cull_frequency 鐨勫艰缃负 0 鎰忓懗鐫褰撹揪鍒 max_entries 鏃,缂撳瓨灏嗚娓呯┖銆傝繖灏嗕互寰堝缂撳瓨涓㈠け涓轰唬浠,澶уぇ鎻愰珮鎺ュ彈璁块棶鐨勯熷害銆傝繖涓奸粯璁ゆ槸3

In this example, timeout is set to 60 :

鍦ㄨ繖涓緥瀛愪腑锛 timeout 琚鎴 60

CACHE_BACKEND = "locmem:///?timeout=60"

In this example, timeout is 30 and max_entries is 400 :

鑰屽湪杩欎釜渚嬪瓙涓紝 timeout 璁句负 30max_entries400 :

CACHE_BACKEND = "locmem:///?timeout=30&max_entries=400"

Invalid arguments are silently ignored, as are invalid values of known arguments.

鍏朵腑锛岄潪娉曠殑鍙傛暟涓庨潪娉曠殑鍙傛暟鍊奸兘灏嗚蹇界暐銆

The Per-Site Cache

绔欑偣绾 Cache

Once youve specified CACHE_BACKEND , the simplest way to use caching is to cache your entire site. This means each page that doesnt have GET or POST parameters will be cached for a specified amount of time the first time its requested.

涓鏃︿綘鎸囧畾浜”CACHE_BACKEND”锛屼娇鐢ㄧ紦瀛樼殑鏈绠鍗曠殑鏂规硶灏辨槸缂撳瓨浣犵殑鏁翠釜缃戠珯銆傝繖鎰忓懗鐫鎵鏈変笉鍖呭惈GET鎴朠OST鍙傛暟鐨勯〉闈㈠湪绗竴娆¤璇锋眰涔嬪悗灏嗚缂撳瓨鎸囧畾濂界殑涓娈垫椂闂达紙灏辨槸璁剧疆鐨則imeout鍙傛暟锛夈

To activate the per-site cache, just add 'django.middleware.cache.CacheMiddleware' to your MIDDLEWARE_CLASSES setting, as in this example:

瑕佹縺娲绘瘡涓珯鐐圭殑cache锛屽彧瑕佸皢``’django.middleware.cache.CacheMiddleware’`` 娣诲姞鍒 MIDDLEWARE_CLASSES 鐨勮缃噷锛屽氨鍍忎笅闈㈣繖鏍凤細

MIDDLEWARE_CLASSES = (
    'django.middleware.cache.CacheMiddleware',
    'django.middleware.common.CommonMiddleware',
)

Note

娉ㄦ剰

The order of MIDDLEWARE_CLASSES matters. See the section Order of MIDDLEWARE_CLASSES later in this chapter.

鍏充簬 MIDDLEWARE_CLASSES 椤哄簭鐨勪竴浜涗簨鎯呫傝鐪嬫湰绔犺妭鍚庨潰鐨凪IDDLEWARE_CLASSES椤哄簭閮ㄥ垎銆

Then, add the following required settings to your Django settings file:

鐒跺悗锛屽湪浣犵殑Django settings鏂囦欢閲屽姞鍏ヤ笅闈㈡墍闇鐨勮缃細

  • CACHE_MIDDLEWARE_SECONDS : The number of seconds each page should be cached.

CACHE_MIDDLEWARE_SECONDS :姣忎釜椤甸潰搴旇琚紦瀛樼殑绉掓暟

  • CACHE_MIDDLEWARE_KEY_PREFIX : If the cache is shared across multiple sites using the same Django installation, set this to the name of the site, or some other string that is unique to this Django instance, to prevent key collisions. Use an empty string if you dont care.

  • CACHE_MIDDLEWARE_KEY_PREFIX 锛氬鏋滅紦瀛樿澶氫釜浣跨敤鐩稿悓Django瀹夎鐨勭綉绔欐墍鍏变韩锛岄偅涔堟妸杩欎釜鍊艰鎴愬綋鍓嶇綉绔欏悕锛屾垨鍏朵粬鑳戒唬琛ㄨ繖涓狣jango瀹炰緥鐨勫敮涓瀛楃涓诧紝浠ラ伩鍏峩ey鍙戠敓鍐茬獊銆傚鏋滀綘涓嶅湪鎰忕殑璇濆彲浠ヨ鎴愮┖瀛楃涓层

The cache middleware caches every page that doesnt have GET or POST parameters. That is, if a user requests a page and passes GET parameters in a query string, or passes POST parameters, the middleware will not attempt to retrieve a cached version of the page. If you intend to use the per-site cache, keep this in mind as you design your application; dont use URLs with query strings, for example, unless it is acceptable for your application not to cache those pages.

缂撳瓨涓棿浠剁紦瀛樻瘡涓病鏈塆ET鎴栬匬OST鍙傛暟鐨勯〉闈紝鍗冲鏋滅敤鎴疯姹傞〉闈㈠苟鍦ㄦ煡璇㈠瓧绗︿覆閲屼紶閫扜ET鍙傛暟鎴栬匬OST鍙傛暟锛屼腑闂翠欢灏嗕笉浼氬皾璇曞緱鍒扮紦瀛樼増鏈殑椤甸潰锛屽鏋滀綘鎵撶畻浣跨敤鏁寸珯缂撳瓨锛岃璁′綘鐨勭▼搴忔椂鐗㈣杩欑偣锛屼緥濡傦紝涓嶈浣跨敤鎷ユ湁鏌ヨ瀛楃涓茬殑URLs锛岄櫎闈為偅浜涢〉闈㈠彲浠ヤ笉缂撳瓨

The cache middleware supports another setting, CACHE_MIDDLEWARE_ANONYMOUS_ONLY . If youve defined this setting, and its set to True , then the cache middleware will only cache anonymous requests (i.e., those requests made by a non-logged-in user). This is a simple and effective way of disabling caching for any user-specific pages, such as Djangos admin interface. Note that if you use CACHE_MIDDLEWARE_ANONYMOUS_ONLY , you should make sure youve activated AuthenticationMiddleware and that AuthenticationMiddleware appears before CacheMiddleware in your MIDDLEWARE_CLASSES .

缂撳瓨涓棿浠讹紙 cache middleware锛夋敮鎸佸彟澶栦竴绉嶈缃夐」, CACHE_MIDDLEWARE_ANONYMOUS_ONLY 銆傚鏋滀綘鎶婂畠璁剧疆涓衡淭rue鈥,閭d箞缂撳瓨涓棿浠跺氨鍙細瀵瑰尶鍚嶈姹傝繘琛岀紦瀛橈紝 鍖垮悕璇锋眰鏄寚閭d簺 娌℃湁鐧诲綍鐨勭敤鎴峰彂璧风殑璇锋眰銆傚鏋滄兂鍙栨秷鐢ㄦ埛鐩稿叧椤甸潰锛坲ser-specific pages锛夌殑缂撳瓨锛屼緥濡侱jangos 鐨勭鐞嗙晫闈紝杩欐槸涓绉嶆棦绠鍗曞張鏈夋晥鐨勬柟娉曘傚彟澶栵紝濡傛灉浣犺浣跨敤 CACHE_MIDDLEWARE_ANONYMOUS_ONLY 閫夐」锛屼綘蹇呴』鍏堟縺娲 AuthenticationMiddleware 鎵嶈锛屼篃灏辨槸鍦ㄤ綘鐨勯厤缃枃浠 MIDDLEWARE_CLASSES 鐨勫湴鏂癸紝 AuthenticationMiddleware 蹇呴』鍑虹幇鍦 CacheMiddleware 鍓嶉潰銆

Finally, note that CacheMiddleware automatically sets a few headers in each HttpResponse :

鏈鍚庯紝鍐嶆彁閱掍竴涓嬶細 CacheMiddleware 鍦ㄦ瘡涓 HttpResponse 涓兘浼氳嚜鍔ㄨ缃竴浜涘ご閮ㄤ俊鎭紙headers锛

  • It sets the Last-Modified header to the current date/time when a fresh (uncached) version of the page is requested.

  • 褰撲竴涓柊(娌$紦瀛樼殑)鐗堟湰鐨勯〉闈㈣璇锋眰鏃惰缃甃ast-Modified澶撮儴涓哄綋鍓嶆棩鏈/鏃堕棿

  • It sets the Expires header to the current date/time plus the defined CACHE_MIDDLEWARE_SECONDS .

  • 璁剧疆Expires澶撮儴涓哄綋鍓嶆棩鏈/鏃堕棿鍔犱笂瀹氫箟鐨凜ACHE_MIDDLEWARE_SECONDS

  • It sets the Cache-Control header to give a maximum age for the page, again from the CACHE_MIDDLEWARE_SECONDS setting.

  • 璁剧疆Cache-Control澶撮儴鏉ョ粰椤甸潰涓涓渶澶х殑鏃堕棿—鍐嶄竴娆★紝鏍规嵁CACHE_MIDDLEWARE_SECONDS璁剧疆

The Per-View Cache

瑙嗗浘绾х紦瀛

A more granular way to use the caching framework is by caching the output of individual views. This has the same effects as the per-site cache (including the omission of caching on requests with GET and POST parameters). It applies to whichever views you specify, rather than the whole site.

鏇村姞棰楃矑绾х殑缂撳瓨妗嗘灦浣跨敤鏂规硶鏄鍗曚釜瑙嗗浘鐨勮緭鍑鸿繘琛岀紦瀛樸傝繖鍜屾暣绔欑骇缂撳瓨鏈変竴鏍风殑鏁堟灉锛堝寘鎷拷鐣ュ鏈 GET 鍜 POST 鍙傛暟鐨勮姹傜殑缂撳瓨锛夈傚畠搴旂敤浜庝綘鎵鎸囧畾鐨勮鍥撅紝鑰屼笉鏄暣涓珯鐐广

Do this by using a decorator , which is a wrapper around your view function that alters its behavior to use caching. The per-view cache decorator is called cache_page and is located in the django.views.decorators.cache module, for example:

瀹屾垚杩欓」宸ヤ綔鐨勬柟寮忔槸浣跨敤 淇グ鍣 锛屽叾浣滅敤鏄寘瑁硅鍥惧嚱鏁帮紝灏嗗叾琛屼负杞崲涓轰娇鐢ㄧ紦瀛樸傝鍥剧紦瀛樹慨楗板櫒绉颁负 cache_page 锛屼綅浜 django.views.decorators.cache 妯″潡涓紝渚嬪锛

from django.views.decorators.cache import cache_page

def my_view(request, param):
    # ...
my_view = cache_page(my_view, 60 * 15)

Alternatively, if youre using Python 2.4 or greater, you can use decorator syntax. This example is equivalent to the preceding one:

濡傛灉浣跨敤 Python 2.4 鎴栨洿楂樼増鏈, 浣犱篃鍙互浣跨敤 decorator 璇硶銆傝繖涓緥瀛愬拰鍓嶉潰鐨勯偅涓槸绛夊悓鐨:

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
def my_view(request, param):
    # ...

cache_page takes a single argument: the cache timeout, in seconds. In the preceding example, the result of the my_view() view will be cached for 15 minutes. (Note that weve written it as 60 * 15 for the purpose of readability. 60 * 15 will be evaluated to 900 that is, 15 minutes multiplied by 60 seconds per minute.)

cache_page 鍙帴鍙椾竴涓弬鏁帮細浠ョ璁$殑缂撳瓨瓒呮椂銆傚湪鍓嶄緥涓紝 “my_view()” 瑙嗗浘鐨勭粨鏋滃皢琚紦瀛 15 鍒嗛挓銆傦紙娉ㄦ剰锛氫负浜嗘彁楂樺彲璇绘э紝璇ュ弬鏁拌涔﹀啓涓 60 * 1560 * 15 灏嗚璁$畻涓 900 锛屼篃灏辨槸璇15 鍒嗛挓涔樹互姣忓垎閽 60 绉掋傦級

The per-view cache, like the per-site cache, is keyed off of the URL. If multiple URLs point at the same view, each URL will be cached separately. Continuing the my_view example, if your URLconf looks like this:

鍜岀珯鐐圭紦瀛樹竴鏍凤紝瑙嗗浘缂撳瓨涓 URL 鏃犲叧銆傚鏋滃涓 URL 鎸囧悜鍚屼竴瑙嗗浘锛屾瘡涓鍥惧皢浼氬垎鍒紦瀛樸傜户缁 my_view 鑼冧緥锛屽鏋 URLconf 濡備笅鎵绀猴細

urlpatterns = ('',
    (r'^foo/(\d{1,2})/$', my_view),
)

then requests to /foo/1/ and /foo/23/ will be cached separately, as you may expect. But once a particular URL (e.g., /foo/23/ ) has been requested, subsequent requests to that URL will use the cache.

閭d箞姝e浣犳墍鏈熷緟鐨勯偅鏍凤紝鍙戦佸埌 /foo/1//foo/23/ 鐨勮姹傚皢浼氬垎鍒紦瀛樸備絾涓鏃﹀彂鍑轰簡鐗瑰畾鐨勮姹傦紙濡傦細 /foo/23/ 锛夛紝涔嬪悗鍐嶅害鍙戝嚭鐨勬寚鍚戣 URL 鐨勮姹傚皢浣跨敤缂撳瓨銆

Specifying Per-View Cache in the URLconf

鍦 URLconf 涓寚瀹氳鍥剧紦瀛

The examples in the previous section have hard-coded the fact that the view is cached, because cache_page alters the my_view function in place. This approach couples your view to the cache system, which is not ideal for several reasons. For instance, you might want to reuse the view functions on another, cacheless site, or you might want to distribute the views to people who might want to use them without being cached. The solution to these problems is to specify the per-view cache in the URLconf rather than next to the view functions themselves.

鍓嶄竴鑺備腑鐨勮寖渚嬪皢瑙嗗浘纭紪鐮佷负浣跨敤缂撳瓨锛屽洜涓 cache_page 鍦ㄩ傚綋鐨勪綅缃 my_view 鍑芥暟杩涜浜嗚浆鎹€傝鏂规硶灏嗚鍥句笌缂撳瓨绯荤粺杩涜浜嗚﹀悎锛屼粠鍑犱釜鏂归潰鏉ヨ骞朵笉鐞嗘兂銆備緥濡傦紝浣犲彲鑳芥兂鍦ㄦ煇涓棤缂撳瓨鐨勭珯鐐逛腑閲嶇敤璇ヨ鍥惧嚱鏁帮紝鎴栬呬綘鍙兘鎯冲皢璇ヨ鍥惧彂甯冪粰閭d簺涓嶆兂閫氳繃缂撳瓨浣跨敤瀹冧滑鐨勪汉銆傝В鍐宠繖浜涢棶棰樼殑鏂规硶鏄湪 URLconf 涓寚瀹氳鍥剧紦瀛橈紝鑰屼笉鏄揣鎸ㄧ潃杩欎簺瑙嗗浘鍑芥暟鏈韩鏉ユ寚瀹氥

Doing so is easy: simply wrap the view function with cache_page when you refer to it in the URLconf. Heres the old URLconf from earlier:

瀹屾垚杩欓」宸ヤ綔闈炲父绠鍗曪細鍦 URLconf 涓敤鍒拌繖浜涜鍥惧嚱鏁扮殑鏃跺欑畝鍗曞湴鍖呰9涓涓 cache_page 銆備互涓嬫槸鍒氭墠鐢ㄥ埌杩囩殑 URLconf :

urlpatterns = ('',
    (r'^foo/(\d{1,2})/$', my_view),
)

Heres the same thing, with my_view wrapped in cache_page :

浠ヤ笅鏄悓涓涓 URLconf 锛屼笉杩囩敤 cache_page 鍖呰9浜 my_view

from django.views.decorators.cache import cache_page

urlpatterns = ('',
    (r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)),
)

If you take this approach, dont forget to import cache_page within your URLconf.

濡傛灉閲囧彇杩欑鏂规硶, 涓嶈蹇樿鍦 URLconf 涓鍏 cache_page .

The Low-Level Cache API

浣庡眰娆$紦瀛楢PI

Sometimes, caching an entire rendered page doesnt gain you very much and is, in fact, inconvenient overkill.

鏈変簺鏃跺欙紝瀵规暣涓粡瑙f瀽鐨勯〉闈㈣繘琛岀紦瀛樺苟涓嶄細缁欎綘甯︽潵澶锛屼簨瀹炰笂鍙兘浼氳繃鐘逛笉鍙娿

Perhaps, for instance, your site includes a view whose results depend on several expensive queries, the results of which change at different intervals. In this case, it would not be ideal to use the full-page caching that the per-site or per-view cache strategies offer, because you wouldnt want to cache the entire result (since some of the data changes often), but youd still want to cache the results that rarely change.

姣斿璇达紝涔熻浣犵殑绔欑偣鎵鍖呭惈鐨勪竴涓鍥句緷璧栧嚑涓垂鏃剁殑鏌ヨ锛屾瘡闅斾竴娈垫椂闂寸粨鏋滃氨浼氬彂鐢熷彉鍖栥傚湪杩欑鎯呭喌涓嬶紝浣跨敤绔欑偣绾х紦瀛樻垨鑰呰鍥剧骇缂撳瓨绛栫暐鎵鎻愪緵鐨勬暣椤电紦瀛樺苟涓嶆槸鏈鐞嗘兂鐨勶紝鍥犱负浣犲彲鑳戒笉浼氭兂瀵规暣涓粨鏋滆繘琛岀紦瀛橈紙鍥犱负涓浜涙暟鎹粡甯稿彉鍖栵級锛屼絾浣犱粛鐒朵細鎯冲寰堝皯鍙樺寲鐨勯儴鍒嗚繘琛岀紦瀛樸

For cases like this, Django exposes a simple, low-level cache API, which lives in the module django.core.cache . You can use the low-level cache API to store objects in the cache with any level of granularity you like. You can cache any Python object that can be pickled safely: strings, dictionaries, lists of model objects, and so forth. (Most common Python objects can be pickled; refer to the Python documentation for more information about pickling.)

鍦ㄥ儚杩欐牱鐨勬儏褰笅锛 Django 灞曠ず浜嗕竴绉嶄綅浜 django.core.cache 妯″潡涓殑绠鍗曘佷綆灞傛鐨勭紦瀛 API 銆備綘鍙互浣跨敤杩欑浣庡眰娆$殑缂撳瓨 API 鍦ㄧ紦瀛樹腑浠ヤ换浣曠骇鍒矑搴﹁繘琛屽璞″偍瀛樸備綘鍙互瀵规墍鏈夎兘澶熷畨鍏ㄨ繘琛 pickle 澶勭悊鐨 Python 瀵硅薄杩涜缂撳瓨锛氬瓧绗︿覆銆佸瓧鍏稿拰妯″瀷瀵硅薄鍒楄〃绛夌瓑锛涙煡闃 Python 鏂囨。鍙互浜嗚В鍒版洿澶氬叧浜 pickling 鐨勪俊鎭傦級

Heres how to import the API:

涓嬮潰鏄浣曞鍏ヨ繖涓 API :

>>> from django.core.cache import cache

The basic interface is set(key, value, timeout_seconds) and get(key) :

鍩烘湰鐨勬帴鍙f槸 set(key, value, timeout_seconds)get(key) :

>>> cache.set('my_key', 'hello, world!', 30)
>>> cache.get('my_key')
'hello, world!'

The timeout_seconds argument is optional and defaults to the timeout argument in the CACHE_BACKEND setting explained earlier.

timeout_seconds 鍙傛暟鏄彲閫夌殑, 骞朵笖榛樿涓哄墠闈㈣杩囩殑 CACHE_BACKEND 璁剧疆涓殑 timeout 鍙傛暟.

If the object doesnt exist in the cache, or the cache back-end is unreachable, cache.get() returns None :

濡傛灉瀵硅薄鍦ㄧ紦瀛樹腑涓嶅瓨鍦, 鎴栬呯紦瀛樺悗绔槸涓嶅彲杈剧殑, cache.get() 杩斿洖 None :

# Wait 30 seconds for 'my_key' to expire...

>>> cache.get('my_key')
None

>>> cache.get('some_unset_key')
None

We advise against storing the literal value None in the cache, because you wont be able to distinguish between your stored None value and a cache miss signified by a return value of None .

鎴戜滑涓嶅缓璁湪缂撳瓨涓繚瀛 None 甯搁噺锛屽洜涓轰綘灏嗘棤娉曞尯鍒嗘墍淇濆瓨鐨 None 鍙橀噺鍙婄敱杩斿洖鍊 None 鎵鏍囪瘑鐨勭紦瀛樻湭涓

cache.get() can take a default argument. This specifies which value to return if the object doesnt exist in the cache:

cache.get() 鎺ュ彈涓涓 缂虹渷 鍙傛暟銆傚叾鎸囧畾浜嗗綋缂撳瓨涓笉瀛樺湪璇ュ璞℃椂鎵杩斿洖鐨勫硷細

>>> cache.get('my_key', 'has expired')
'has expired'

To retrieve multiple cache values in a single shot, use cache.get_many() . If possible for the given cache back-end, get_many() will hit the cache only once, as opposed to hitting it once per cache key. get_many() returns a dictionary with all of the keys you asked for that exist in the cache and havent expired:

瑕佹兂涓娆¤幏鍙栧涓紦瀛樺硷紝鍙互浣跨敤 cache.get_many() 銆傚鏋滃彲鑳界殑璇濓紝瀵逛簬缁欏畾鐨勭紦瀛樺悗绔紝 get_many() 灏嗗彧璁块棶缂撳瓨涓娆★紝鑰屼笉鏄姣忎釜缂撳瓨閿奸兘杩涜涓娆¤闂 get_many() 鎵杩斿洖鐨勫瓧鍏稿寘鎷簡浣犳墍璇锋眰鐨勫瓨鍦ㄤ簬缂撳瓨涓笖鏈秴鏃剁殑鎵鏈夐敭鍊笺

>>> cache.set('a', 1)
>>> cache.set('b', 2)
>>> cache.set('c', 3)
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}

If a cache key doesnt exist or is expired, it wont be included in the dictionary. The following is a continuation of the example:

濡傛灉鏌愪釜缂撳瓨鍏抽敭瀛椾笉瀛樺湪鎴栬呭凡瓒呮椂, 瀹冨皢涓嶄細琚寘鍚湪瀛楀吀涓 涓嬮潰鏄寖渚嬬殑寤剁画:

>>> cache.get_many(['a', 'b', 'c', 'd'])
{'a': 1, 'b': 2, 'c': 3}

Finally, you can delete keys explicitly with cache.delete() . This is an easy way of clearing the cache for a particular object:

鏈鍚,浣犲彲浠ョ敤 cache.delete() 鏄惧紡鍦板垹闄ゅ叧閿瓧銆傝繖鏄湪缂撳瓨涓竻闄ょ壒瀹氬璞$殑绠鍗曢斿緞銆

>>> cache.delete('a')

cache.delete() has no return value, and it works the same way whether or not a value with the given cache key exists.

cache.delete() 娌℃湁杩斿洖鍊, 涓嶇缁欏畾鐨勭紦瀛樺叧閿瓧瀵瑰簲鐨勫煎瓨鍦ㄤ笌鍚, 瀹冮兘灏嗕互鍚屾牱鏂瑰紡宸ヤ綔銆

Upstream Caches

涓婃父缂撳瓨

So far, this chapter has focused on caching your own data. But another type of caching is relevant to Web development, too: caching performed by upstream caches. These are systems that cache pages for users even before the request reaches your Web site.

鐩墠涓烘锛屾湰绔犵殑鐒︾偣涓鐩存槸瀵逛綘 鑷繁鐨 鏁版嵁杩涜缂撳瓨銆備絾杩樻湁涓绉嶄笌 Web 寮鍙戠浉鍏崇殑缂撳瓨锛氱敱 涓婃父 楂橀熺紦瀛樻墽琛岀殑缂撳啿銆傛湁涓浜涚郴缁熺敋鑷冲湪璇锋眰鍒拌揪绔欑偣涔嬪墠灏变负鐢ㄦ埛杩涜椤甸潰缂撳瓨銆

Here are a few examples of upstream caches:

涓嬮潰鏄笂娓哥紦瀛樼殑鍑犱釜渚嬪瓙锛

  • Your ISP may cache certain pages, so if you requested a page from http://example.com/, your ISP would send you the page without having to access example.com directly. The maintainers of example.com have no knowledge of this caching; the ISP sits between example.com and your Web browser, handling all of the caching transparently.

  • 浣犵殑 ISP (浜掕仈缃戞湇鍔″晢)鍙兘浼氬鐗瑰畾鐨勯〉闈㈣繘琛岀紦瀛橈紝鍥犳濡傛灉浣犲悜 http://example.com/ 璇锋眰涓涓〉闈紝浣犵殑 ISP 鍙兘鏃犻渶鐩存帴璁块棶 example.com 灏辫兘灏嗛〉闈㈠彂閫佺粰浣犮傝 example.com 鐨勭淮鎶よ呬滑鍗存棤浠庡緱鐭ヨ繖绉嶇紦瀛橈紝ISP 浣嶄簬 example.com 鍜屼綘鐨勭綉椤垫祻瑙堝櫒涔嬮棿锛岄忔槑鍦板鐞嗘墍鏈夌殑缂撳瓨銆

  • Your Django Web site may sit behind a proxy cache , such as Squid Web Proxy Cache (http://www.squid-cache.org/), that caches pages for performance. In this case, each request first would be handled by the proxy, and it would be passed to your application only if needed.

  • 浣犵殑 Django 缃戠珯鍙兘浣嶄簬鏌愪釜 浠g悊缂撳瓨 涔嬪悗锛屼緥濡 Squid 缃戦〉浠g悊缂撳瓨 (http://www.squid-cache.org/)锛岃缂撳瓨涓烘彁楂樻ц兘鑰屽椤甸潰杩涜缂撳瓨銆傚湪姝ゆ儏鍐典笅 锛屾瘡涓姹傚皢棣栧厛鐢变唬鐞嗘湇鍔″櫒杩涜澶勭悊锛岀劧鍚庝粎鍦ㄩ渶瑕佺殑鎯呭喌涓嬫墠琚紶閫掕嚦浣犵殑搴旂敤绋嬪簭銆

  • Your Web browser caches pages, too. If a Web page sends out the appropriate headers, your browser will use the local cached copy for subsequent requests to that page, without even contacting the Web page again to see whether it has changed.

  • 浣犵殑缃戦〉娴忚鍣ㄤ篃瀵归〉闈㈣繘琛岀紦瀛樸傚鏋滄煇缃戦〉閫佸嚭浜嗙浉搴旂殑澶撮儴锛屼綘鐨勬祻瑙堝櫒灏嗗湪涓哄璇ョ綉椤电殑鍚庣画鐨勮闂姹備娇鐢ㄦ湰鍦扮紦瀛樼殑鎷疯礉锛岀敋鑷充笉浼氬啀娆¤仈绯昏缃戦〉鏌ョ湅鏄惁鍙戠敓浜嗗彉鍖栥

Upstream caching is a nice efficiency boost, but theres a danger to it. The content of many Web pages differs based on authentication and a host of other variables, and cache systems that blindly save pages based purely on URLs could expose incorrect or sensitive data to subsequent visitors to those pages.

涓婃父缂撳瓨灏嗕細浜х敓闈炲父鏄庢樉鐨勬晥鐜囨彁鍗囷紝浣嗕篃瀛樺湪涓瀹氶闄┿傝澶氱綉椤电殑鍐呭渚濇嵁韬唤楠岃瘉浠ュ強璁稿鍏朵粬鍙橀噺鐨勬儏鍐靛彂鐢熷彉鍖栵紝缂撳瓨绯荤粺浠呯洸鐩湴鏍规嵁 URL 淇濆瓨椤甸潰锛屽彲鑳戒細鍚戣繖浜涢〉闈㈢殑鍚庣画璁块棶鑰呮毚闇蹭笉姝g‘鎴栬呮晱鎰熺殑鏁版嵁銆

For example, say you operate a Web e-mail system, and the contents of the inbox page obviously depend on which user is logged in. If an ISP blindly cached your site, then the first user who logged in through that ISP would have his or her user-specific inbox page cached for subsequent visitors to the site. Thats not cool.

涓句釜渚嬪瓙锛屽亣瀹氫綘鍦ㄤ娇鐢ㄧ綉椤电數閭郴缁燂紝鏄剧劧鏀朵欢绠遍〉闈㈢殑鍐呭鍙栧喅浜庣櫥褰曠殑鏄摢涓敤鎴枫傚鏋 ISP 鐩茬洰鍦扮紦瀛樹簡璇ョ珯鐐癸紝閭d箞绗竴涓敤鎴烽氳繃璇 ISP 鐧诲綍涔嬪悗锛屼粬锛堟垨濂癸級鐨勭敤鎴锋敹浠剁椤甸潰灏嗕細缂撳瓨缁欏悗缁殑璁块棶鑰呫傝繖涓鐐逛篃涓嶅ソ鐜┿

Fortunately, HTTP provides a solution to this problem. A number of HTTP headers exist to instruct upstream caches to differ their cache contents depending on designated variables, and to tell caching mechanisms not to cache particular pages. Well look at some of these headers in the sections that follow.

骞歌繍鐨勬槸锛 HTTP 鎻愪緵浜嗚В鍐宠闂鐨勬柟妗堛傚凡鏈変竴浜 HTTP 澶存爣鐢ㄤ簬鎸囧紩涓婃父缂撳瓨鏍规嵁鎸囧畾鍙橀噺鏉ュ尯鍒嗙紦瀛樺唴瀹癸紝骞堕氱煡缂撳瓨鏈哄埗涓嶅鐗瑰畾椤甸潰杩涜缂撳瓨銆傛垜浠皢鍦ㄦ湰鑺傚悗缁儴鍒嗗皢瀵硅繖浜涘ご鏍囪繘琛岄槓杩般

Using Vary Headers

浣跨敤 Vary 澶存爣

The Vary header defines which request headers a cache mechanism should take into account when building its cache key. For example, if the contents of a Web page depend on a users language preference, the page is said to vary on language.

Vary 澶存爣瀹氫箟浜嗙紦瀛樻満鍒跺湪鏋勫缓鍏剁紦瀛橀敭鍊兼椂搴斿綋灏嗗摢涓姹傚ご鏍囪冭檻鍦ㄥ唴銆備緥濡傦紝濡傛灉缃戦〉鐨勫唴瀹瑰彇鍐充簬鐢ㄦ埛鐨勮瑷鍋忓ソ锛岃椤甸潰琚О涓烘牴鎹瑷鑰屼笉鍚屻

By default, Djangos cache system creates its cache keys using the requested path (e.g., "/stories/2005/jun/23/bank_robbed/" ). This means every request to that URL will use the same cached version, regardless of user-agent differences such as cookies or language preferences. However, if this page produces different content based on some difference in request headerssuch as a cookie, or a language, or a user-agentyoull need to use the Vary header to tell caching mechanisms that the page output depends on those things.

缂虹渷鎯呭喌涓嬶紝Django 鐨勭紦瀛樼郴缁熶娇鐢ㄦ墍璇锋眰鐨勮矾寰勶紙姣斿锛 "/stories/2005/jun/23/bank_robbed/" 锛夋潵鍒涘缓鍏剁紦瀛橀敭銆傝繖鎰忓懗鐫瀵硅 URL 鐨勬瘡涓姹傞兘灏嗕娇鐢ㄥ悓涓涓凡缂撳瓨鐗堟湰锛岃屼笉鑰冭檻 cookies 鎴栬瑷鍋忓ソ涔嬬被鐨 user-agent 宸埆銆傜劧鑰岋紝濡傛灉璇ラ〉闈㈠熀浜庤姹傚ご鏍囩殑鍖哄埆锛堜緥濡 cookies銆佽瑷鎴栬 user-agent)浜х敓涓嶅悓鍐呭锛屼綘灏变笉寰椾笉浣跨敤

Vary 澶存爣鏉ラ氱煡缂撳瓨鏈哄埗锛氳椤甸潰鐨勮緭鍑哄彇鍐充簬杩欎簺涓滆タ銆

To do this in Django, use the convenient vary_on_headers view decorator, like so:

瑕佸湪 Django 瀹屾垚杩欓」宸ヤ綔锛屽彲浣跨敤渚垮埄鐨 vary_on_headers 瑙嗗浘淇グ鍣紝濡備笅鎵绀猴細

from django.views.decorators.vary import vary_on_headers

# Python 2.3 syntax.
def my_view(request):
    # ...
my_view = vary_on_headers(my_view, 'User-Agent')

# Python 2.4+ decorator syntax.
@vary_on_headers('User-Agent')
def my_view(request):
    # ...

In this case, a caching mechanism (such as Djangos own cache middleware) will cache a separate version of the page for each unique user-agent.

鍦ㄨ繖绉嶆儏鍐典笅锛岀紦瀛樿缃紙濡 Django 鑷繁鐨勭紦瀛樹腑闂翠欢锛夊皢浼氫负姣忎竴涓崟鐙殑鐢ㄦ埛娴忚鍣ㄧ紦瀛樹竴涓嫭绔嬬殑椤甸潰鐗堟湰銆

The advantage to using the vary_on_headers decorator rather than manually setting the Vary header (using something like response['Vary'] = 'user-agent' ) is that the decorator adds to the Vary header (which may already exist), rather than setting it from scratch and potentially overriding anything that was already in there.

浣跨敤 vary_on_headers 淇グ鍣ㄨ屼笉鏄墜鍔ㄨ缃 Vary 澶存爣锛堜娇鐢ㄥ儚 response['Vary'] = 'user-agent' 涔嬬被鐨勪唬鐮侊級鐨勫ソ澶勬槸淇グ鍣ㄥ湪锛堝彲鑳藉凡缁忓瓨鍦ㄧ殑锛 Vary 涔嬩笂杩涜 娣诲姞 锛岃屼笉鏄粠闆跺紑濮嬭缃紝涓斿彲鑳借鐩栬澶勫凡缁忓瓨鍦ㄧ殑璁剧疆銆

You can pass multiple headers to vary_on_headers() :

浣犲彲浠ュ悜 vary_on_headers() 浼犲叆澶氫釜澶存爣锛

@vary_on_headers('User-Agent', 'Cookie')
def my_view(request):
    # ...

This tells upstream caches to vary on both , which means each combination of user-agent and cookie will get its own cache value. For example, a request with the user-agent Mozilla and the cookie value foo=bar will be considered different from a request with the user-agent Mozilla and the cookie value foo=ham .

璇ユ浠g爜閫氱煡涓婃父缂撳瓨瀵 涓よ 閮借繘琛屼笉鍚屾搷浣滐紝涔熷氨鏄 user-agent 鍜 cookie 鐨勬瘡绉嶇粍鍚堥兘搴旇幏鍙栬嚜宸辩殑缂撳瓨鍊笺備妇渚嬫潵璇达紝浣跨敤 Mozilla 浣滀负 user-agent 鑰 foo=bar 浣滀负 cookie 鍊肩殑璇锋眰搴旇鍜屼娇鐢 Mozilla 浣滀负 user-agent 鑰 foo=ham 鐨勮姹傚簲璇ヨ瑙嗕负涓嶅悓璇锋眰銆

Because varying on cookie is so common, theres a vary_on_cookie decorator. These two views are equivalent:

鐢变簬鏍规嵁 cookie 鑰屽尯鍒嗗寰呮槸寰堝父瑙佺殑鎯呭喌锛屽洜姝ゆ湁 vary_on_cookie 淇グ鍣ㄣ備互涓嬩袱涓鍥炬槸绛夋晥鐨勶細

@vary_on_cookie
def my_view(request):
    # ...

@vary_on_headers('Cookie')
def my_view(request):
    # ...

The headers you pass to vary_on_headers are not case sensitive; "User-Agent" is the same thing as "user-agent" .

浼犲叆 vary_on_headers 澶存爣鏄ぇ灏忓啓涓嶆晱鎰熺殑锛 "User-Agent""user-agent" 瀹屽叏鐩稿悓銆

You can also use a helper function, django.utils.cache.patch_vary_headers , directly. This function sets, or adds to, the Vary header , for example:

浣犱篃鍙互鐩存帴浣跨敤甯姪鍑芥暟锛 django.utils.cache.patch_vary_headers 銆傝鍑芥暟璁剧疆鎴栧鍔 Vary header 锛屼緥濡傦細

from django.utils.cache import patch_vary_headers

def my_view(request):
    # ...
    response = render_to_response('template_name', context)
    patch_vary_headers(response, ['Cookie'])
    return response

patch_vary_headers takes an HttpResponse instance as its first argument and a list/tuple of case-insensitive header names as its second argument.

patch_vary_headers 浠ヤ竴涓 HttpResponse 瀹炰緥涓虹涓涓弬鏁帮紝浠ヤ竴涓ぇ灏忓啓涓嶆晱鎰熺殑澶存爣鍚嶇О鍒楄〃鎴栧厓缁勪负绗簩涓弬鏁般

Other Cache Headers

鍏跺畠缂撳瓨澶存爣

Other problems with caching are the privacy of data and the question of where data should be stored in a cascade of caches.

鍏充簬缂撳瓨鍓╀笅鐨勯棶棰樻槸鏁版嵁鐨勭闅愭т互鍙婂叧浜庡湪绾ц仈缂撳瓨涓暟鎹簲璇ュ湪浣曞鍌ㄥ瓨鐨勯棶棰樸

A user usually faces two kinds of caches: his or her own browser cache (a private cache) and his or her providers cache (a public cache). A public cache is used by multiple users and controlled by someone else. This poses problems with sensitive datayou dont want, say, your bank account number stored in a public cache. So Web applications need a way to tell caches which data is private and which is public.

閫氬父鐢ㄦ埛灏嗕細闈㈠涓ょ缂撳瓨锛氫粬鎴栧ス鑷繁鐨勬祻瑙堝櫒缂撳瓨锛堢鏈夌紦瀛橈級浠ュ強浠栨垨濂圭殑鎻愪緵鑰呯紦瀛橈紙鍏叡缂撳瓨锛夈傚叕鍏辩紦瀛樼敱澶氫釜鐢ㄦ埛浣跨敤锛岃屽彈鍏朵粬鏌愪汉鐨勬帶鍒躲傝繖灏变骇鐢熶簡浣犱笉鎯抽亣鍒扮殑鏁忔劅鏁版嵁鐨勯棶棰橈紝姣斿璇翠綘鐨勯摱琛岃处鍙疯瀛樺偍鍦ㄥ叕浼楃紦瀛樹腑銆傚洜姝わ紝Web 搴旂敤绋嬪簭闇瑕佷互鏌愮鏂瑰紡鍛婅瘔缂撳瓨閭d簺鏁版嵁鏄鏈夌殑锛屽摢浜涙槸鍏叡鐨勩

The solution is to indicate a pages cache should be private. To do this in Django, use the cache_control view decorator:

瑙e喅鏂规鏄爣绀哄嚭鏌愪釜椤甸潰缂撳瓨搴斿綋鏄鏈夌殑銆傝鍦 Django 涓畬鎴愭椤瑰伐浣滐紝鍙娇鐢 cache_control 瑙嗗浘淇グ鍣細

from django.views.decorators.cache import cache_control

@cache_control(private=True)
def my_view(request):
    # ...

This decorator takes care of sending out the appropriate HTTP header behind the scenes.

璇ヤ慨楗板櫒璐熻矗鍦ㄥ悗鍙板彂閫佺浉搴旂殑 HTTP 澶存爣銆

There are a few other ways to control cache parameters. For example, HTTP allows applications to do the following:

杩樻湁涓浜涘叾浠栨柟娉曞彲浠ユ帶鍒剁紦瀛樺弬鏁般備緥濡, HTTP 鍏佽搴旂敤绋嬪簭鎵ц濡備笅鎿嶄綔:

  • Define the maximum time a page should be cached.

  • 瀹氫箟椤甸潰鍙互琚紦瀛樼殑鏈澶ф鏁般

  • Specify whether a cache should always check for newer versions, only delivering the cached content when there are no changes. (Some caches might deliver cached content even if the server page changed, simply because the cache copy isnt yet expired.)

  • 鎸囧畾鏌愪釜缂撳瓨鏄惁鎬绘槸妫鏌ヨ緝鏂扮増鏈紝浠呭綋鏃犳洿鏂版椂鎵嶄紶閫掓墍缂撳瓨鍐呭銆傦紙涓浜涚紦瀛樺嵆渚垮湪鏈嶅姟鍣ㄩ〉闈㈠彂鐢熷彉鍖栫殑鎯呭喌涓嬮兘鍙兘杩樹細浼犻佹墍缂撳瓨鐨勫唴瀹癸紝鍙洜涓虹紦瀛樻嫹璐濇病鏈夎繃鏈熴傦級

In Django, use the cache_control view decorator to specify these cache parameters. In this example, cache_control tells caches to revalidate the cache on every access and to store cached versions for, at most, 3,600 seconds:

鍦 Django 涓紝鍙娇鐢 cache_control 瑙嗗浘淇グ鍣ㄦ寚瀹氳繖浜涚紦瀛樺弬鏁般傚湪鏈緥涓紝 cache_control 鍛婅瘔缂撳瓨瀵规瘡娆¤闂兘閲嶆柊楠岃瘉缂撳瓨骞跺湪鏈闀 3600 绉掑唴淇濆瓨鎵缂撳瓨鐗堟湰锛

from django.views.decorators.cache import cache_control
@cache_control(must_revalidate=True, max_age=3600)
def my_view(request):
    ...

Any valid Cache-Control HTTP directive is valid in cache_control() . Heres a full list:

cache_control() 涓紝浠讳綍鏈夋晥 Cache-Control HTTP 鎸囦护閮芥槸鏈夋晥鐨勩備互涓嬫槸涓涓畬鏁寸殑娓呭崟锛

  • public=True

  • public=True

  • private=True

  • private=True

  • no_cache=True

  • no_cache=True

  • no_transform=True

  • no_transform=True

  • must_revalidate=True

  • must_revalidate=True

  • proxy_revalidate=True

  • proxy_revalidate=True

  • max_age=num_seconds

  • max_age=num_seconds

  • s_maxage=num_seconds

  • s_maxage=num_seconds

Tip

灏忔彁绀

For explanation of Cache-Control HTTP directives, see the specification at http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.

瑕佷簡瑙f湁鍏 Cache-Control HTTP 鎸囦护鐨勭浉鍏宠В閲, 鍙互鏌ラ槄 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 鐨勮鑼冩枃妗c

Note

娉ㄦ剰

The caching middleware already sets the cache headers max-age with the value of the CACHE_MIDDLEWARE_SETTINGS setting. If you use a custom max_age in a cache_control decorator, the decorator will take precedence, and the header values will be merged correctly.)

缂撳瓨涓棿浠跺凡缁忎娇鐢 CACHE_MIDDLEWARE_SETTINGS 璁剧疆璁惧畾浜嗙紦瀛樺ご鏍 max-age 銆傚鏋滀綘鍦 cache_control 淇グ鍣ㄤ腑浣跨敤浜嗚嚜瀹氫箟鐨 max_age 锛岃淇グ鍣ㄥ皢浼氬彇寰椾紭鍏堟潈锛岃澶存爣鐨勫煎皢琚纭湴琚悎骞躲傦級

Other Optimizations

鍏朵粬浼樺寲

Django comes with a few other pieces of middleware that can help optimize your applications performance:

Django 甯︽湁涓浜涘叾瀹冧腑闂翠欢鍙府鍔╂偍浼樺寲搴旂敤绋嬪簭鐨勬ц兘:

  • django.middleware.http.ConditionalGetMiddleware adds support for modern browsers to conditionally GET responses based on the ETag and Last-Modified headers.

  • django.middleware.http.ConditionalGetMiddleware 涓虹幇浠f祻瑙堝櫒澧炲姞浜嗘湁鏉′欢鍦 GET 鍩轰簬 ETagLast-Modified 澶存爣鐨勫搷搴旂殑鐩稿叧鏀寔銆

  • django.middleware.gzip.GZipMiddleware compresses responses for all moderns browsers, saving bandwidth and transfer time.

  • django.middleware.gzip.GZipMiddleware 涓烘墍鏈夌幇浠f祻瑙堝櫒鍘嬬缉鍝嶅簲鍐呭锛屼互鑺傜渷甯﹀鍜屼紶閫佹椂闂淬

Order of MIDDLEWARE_CLASSES

MIDDLEWARE_CLASSES 鐨勯『搴

If you use CacheMiddleware , its important to put it in the right place within the MIDDLEWARE_CLASSES setting, because the cache middleware needs to know the headers by which to vary the cache storage.

濡傛灉浣跨敤缂撳瓨涓棿浠讹紝涓瀹氳灏嗗叾鏀剧疆鍦 MIDDLEWARE_CLASSES 璁剧疆鐨勬纭綅缃紝鍥犱负缂撳瓨涓棿浠堕渶瑕佺煡閬撶敤浜庝骇鐢熶笉鍚岀紦瀛樺瓨鍌ㄧ殑鐨勫ご鏍囥

Put the CacheMiddleware after any middlewares that might add something to the Vary header, including the following:

CacheMiddleware 鏀剧疆鍦ㄦ墍鏈夊彲鑳藉悜 Vary 澶存爣娣诲姞鍐呭鐨勪腑闂翠欢涔嬪悗锛屽寘鎷笅鍒椾腑闂翠欢锛

  • SessionMiddleware , which adds Cookie

  • 娣诲姞 CookieSessionMiddleware

  • GZipMiddleware , which adds Accept-Encoding

  • 娣诲姞 Accept-EncodingGZipMiddleware ,

Whats Next?

鎺ヤ笅鏉ワ紵

Django ships with a number of contrib packagescool, optional features. Weve already covered a few of the: the admin system (Chapter 6) and the session/user framework (Chapter 11).

Django 甯︽湁涓浜涘姛鑳藉寘瑁呬簡涓浜涘緢閰风殑,鍙夌殑鐗硅壊. 鎴戜滑宸茬粡璁蹭簡涓浜: admin绯荤粺(绗6绔)鍜宻ession/user妗嗘灦(绗11绔).

The next chapter covers the rest of the contributed subframeworks. Theres a lot of cool tools available; you wont want to miss any of them.

涓嬩竴绔犱腑锛屾垜浠皢璁茶堪Django涓叾浠栫殑瀛愭鏋讹紝灏嗕細鏈夊緢澶氬緢閰风殑宸ュ叿鍑虹幇锛屼綘涓瀹氫笉鎯抽敊杩囧畠浠

Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This work is licensed under the GNU Free Document License.
Hosting graciously provided by media temple
Chinese translate hosting by py3k.cn.