One of the many strengths of Python is its batteries included philosophy: when you install Python, it comes with a large standard library of packages that you can start using immediately, without having to download anything else. Django aims to follow this philosophy, and it includes its own standard library of add-ons useful for common Web development tasks. This chapter covers that collection of add-ons.
Python鏈変紬澶氫紭鐐癸紝鍏朵腑涔嬩竴灏辨槸鈥滃紑鏈哄嵆鐢ㄢ濆師鍒欙細瀹夎Python鐨勫悓鏃跺畨瑁呭ソ澶ч噺鐨勬爣鍑嗚蒋浠跺寘锛岃繖鏍 浣犲彲浠ョ珛鍗充娇鐢ㄨ屼笉鐢ㄨ嚜宸卞幓涓嬭浇銆侱jango涔熼伒寰繖涓師鍒欙紝瀹冨悓鏍峰寘鍚簡鑷繁鐨勬爣鍑嗗簱銆傝繖涓绔犲氨鏉ヨ 杩欎簺闆嗘垚鐨勫瓙妗嗘灦銆
Djangos standard library lives in the package django.contrib . Within each subpackage is a separate piece of add-on functionality. These pieces are not necessarily related, but some django.contrib subpackages may require other ones.
Django鐨勬爣鍑嗗簱瀛樻斁鍦 django.contrib 鍖呬腑銆傛瘡涓瓙鍖呴兘鏄竴涓嫭绔嬬殑闄勫姞鍔熻兘鍖呫 瀹冧滑浜掔浉涔嬮棿涓鑸病鏈夊繀鐒剁殑鍏宠仈锛屼絾鏄湁浜 django.contrib 瀛愬寘鍙兘渚濊禆鍏朵粬鐨勫寘銆
Theres no hard requirement for the types of functionality in django.contrib . Some of the packages include models (and hence require you to install their database tables into your database), but others consist solely of middleware or template tags.
鍦 django.contrib 涓鍑芥暟鐨勭被鍨嬪苟娌℃湁寮哄埗瑕佹眰 銆傚叾涓竴浜涘寘涓甫鏈夋ā鍨嬶紙鍥犳闇瑕佷綘鍦ㄦ暟鎹簱涓畨瑁呭搴旂殑鏁版嵁琛級锛屼絾鍏跺畠涓浜涚敱鐙珛鐨勪腑闂翠欢鍙婃ā鏉挎爣绛剧粍鎴愩
The single characteristic the django.contrib packages have in common is this: if you were to remove the django.contrib package entirely, you could still use Djangos fundamental features with no problems. When the Django developers add new functionality to the framework, they use this rule of thumb in deciding whether the new functionality should live in django.contrib or elsewhere.
django.contrib 寮鍙戝寘鍏辨湁鐨勭壒鎬ф槸:灏辩畻浣犲皢鏁翠釜 django.contrib 寮鍙戝寘鍒犻櫎锛屼綘渚濈劧鍙互浣跨敤 Django 鐨勫熀纭鍔熻兘鑰屼笉浼氶亣鍒颁换浣曢棶棰樸傚綋 Django 寮鍙戣呭悜妗嗘灦澧炲姞鏂板姛鑳界殑鏃讹紝浠栦滑浼氫弗鏍兼牴鎹繖涓鏁欐潯鏉ュ喅瀹氭槸鍚︽妸鏂板姛鑳芥斁鍏 django.contrib 涓
django.contrib consists of these packages:
django.contrib 鐢变互涓嬪紑鍙戝寘缁勬垚锛
admin : The automatic admin site. See Chapters 6 and 18.
admin : 鑷姩鍖栫殑绔欑偣绠$悊宸ュ叿銆傝鏌ョ湅绗6绔犲拰绗18绔
auth : Djangos authentication framework. See Chapter 12.
auth : Django鐨勭敤鎴烽獙璇佹鏋躲傝鏌ョ湅绗12绔
comments : A comments application. This application is currently under heavy development and thus couldnt be covered fully in time for this books publication. Check the Django Web site for the latest information about the comments application.
comments : 涓涓瘎璁哄簲鐢紝鐩墠锛岃繖涓簲鐢ㄦ鍦ㄧ揣寮犵殑寮鍙戜腑锛屽洜姝ゅ湪鏈功鍑虹増鐨勬椂鍊欒繕涓嶈兘缁欏嚭涓涓畬鏁寸殑璇存槑锛屽叧浜庤繖涓簲鐢ㄧ殑鏇村淇℃伅璇峰弬瑙丏jango鐨勫畼鏂圭綉绔.
contenttypes : A framework for hooking into types of content, where each installed Django model is a separate content type. This framework is used internally by other contrib applications and is mostly intended for very advanced Django developers. Those developers should find out more about this application by reading the source code in django/contrib/contenttypes/ .
contenttypes : 杩欐槸涓涓敤浜庢枃妗g被鍨嬮挬瀛愮殑妗嗘灦锛屾瘡涓畨瑁呯殑Django妯″潡浣滀负涓绉嶇嫭绔嬬殑鏂囨。绫诲瀷銆傝繖涓鏋朵富瑕佸湪Django鍐呴儴琚叾浠栧簲鐢ㄤ娇鐢紝瀹冧富瑕侀潰鍚慏jango鐨勯珮绾у紑鍙戣呫傚彲浠ラ氳繃闃呰婧愮爜鏉ヤ簡瑙e叧浜庤繖涓鏋剁殑鏇村淇℃伅锛屾簮鐮佺殑浣嶇疆鍦 django/contrib/contenttypes/ .
csrf : Protection against Cross-Site Request Forgery (CSRF). See the later section titled CSRF Protection.
csrf : 杩欎釜妯″潡鐢ㄦ潵闃插尽璺ㄧ珯璇锋眰浼(CSRF).鍙傝鍚庨潰鏍囬涓”CSRF 闃插尽”鐨勫皬鑺傘
flatpages : A framework for managing simple flat HTML content in a database. See the later section titled Flatpages.
flatpages : 涓涓湪鏁版嵁搴撲腑绠$悊鍗曚竴HTML鍐呭鐨勬ā鍧楋紝鍙傝鍚庨潰鏍囬涓衡淔latpages鈥濈殑灏忚妭銆
humanize : A set of Django template filters useful for adding a human touch to data. See the later section titled Humanizing Data.
humanize : 涓绯诲垪 Django 妯″潡杩囨护鍣紝鐢ㄤ簬澧炲姞鏁版嵁鐨勪汉鎬у寲銆傚弬闃呯◢鍚庣殑绔犺妭銆婁汉鎬у寲鏁版嵁銆嬨
markup : A set of Django template filters that implement a number of common markup languages. See the later section titled Markup Filters.
markup : 涓绯诲垪鐨 Django 妯℃澘杩囨护鍣紝鐢ㄤ簬瀹炵幇涓浜涘父鐢ㄦ爣璁拌瑷銆傚弬闃呭悗缁珷鑺傘婃爣璁拌繃婊ゅ櫒銆嬨
redirects : A framework for managing redirects. See the later section titled Redirects.
redirects : 鐢ㄦ潵绠$悊閲嶅畾鍚戠殑妗嗘灦銆傚弬瑙佸悗闈㈡爣棰樹负銆婇噸瀹氬悜銆嬬殑灏忚妭銆
sessions : Djangos session framework. See Chapter 12.
sessions : Django 鐨勪細璇濇鏋讹紝鍙傝12绔犮
sitemaps : A framework for generating sitemap XML files. See Chapter 11.
sitemaps : 鐢ㄦ潵鐢熸垚缃戠珯鍦板浘鐨 XML 鏂囦欢鐨勬鏋躲傚弬瑙 11 绔犮
sites : A framework that lets you operate multiple Web sites from the same database and Django installation. See the next section, Sites.
sites : 涓涓浣犲彲浠ュ湪鍚屼竴涓暟鎹簱涓 Django 瀹夎涓鐞嗗涓綉绔欑殑妗嗘灦銆傚弬瑙佷笅涓鑺傦細绔欑偣銆
syndication : A framework for generating syndication feeds in RSS and Atom. See Chapter 11.
syndication : 涓涓敤 RSS 鍜 Atom 鏉ョ敓鎴愯仛鍚堣闃呮簮鐨勭殑妗嗘灦銆傚弬闃呯 11 绔犮
The rest of this chapter goes into detail about each django.contrib package that we havent yet covered in this book.
鏈珷鎺ヤ笅鏉ュ皢璇︾粏鎻忚堪鍓嶉潰娌℃湁浠嬬粛杩囩殑 django.contrib 寮鍙戝寘鍐呭銆
Djangos sites system is a generic framework that lets you operate multiple Web sites from the same database and Django project. This is an abstract concept, and it can be tricky to understand, so well start with a couple of scenarios where it would be useful.
Django 鐨勫绔欑偣绯荤粺鏄竴绉嶉氱敤妗嗘灦锛屽畠璁╀綘鍙互鍦ㄥ悓涓涓暟鎹簱鍜屽悓涓涓狣jango椤圭洰涓嬫搷浣滃涓綉绔欍傝繖鏄竴涓娊璞℃蹇碉紝鐞嗚В璧锋潵鍙兘鏈夌偣鍥伴毦锛屽洜姝ゆ垜浠粠鍑犱釜璁╁畠鑳芥淳涓婄敤鍦虹殑瀹為檯鎯呮櫙鍏ユ墜銆
As we explained in Chapter 1, the Django-powered sites LJWorld.com and Lawrence.com are operated by the same news organization: the Lawrence Journal-World newspaper in Lawrence, Kansas. LJWorld.com focuses on news, while Lawrence.com focuses on local entertainment. But sometimes editors want to publish an article on both sites.
姝e鎴戜滑鍦ㄧ涓绔犻噷鎵璁诧紝Django 鏋勫缓鐨勭綉绔 LJWorld.com 鍜 Lawrance.com 鏄敤鐢卞悓涓涓柊闂荤粍缁囨帶鍒剁殑锛氳偗钀ㄦ柉宸炲姵浼︽柉甯傜殑 鍔充鸡鏂棩鎶ヤ笘鐣 鎶ョ焊銆 LJWorld.com 涓昏鍋氭柊闂伙紝鑰 Lawrence.com 鍏虫敞鏈湴濞变箰銆傜劧鑰屾湁鏃讹紝缂栬緫鍙兘闇瑕佹妸涓绡囨枃绔犲彂甯冨埌 涓や釜 缃戠珯涓娿
The brain-dead way of solving the problem would be to use a separate database for each site and to require site producers to publish the same story twice: once for LJWorld.com and again for Lawrence.com. But thats inefficient for site producers, and its redundant to store multiple copies of the same story in the database.
瑙e喅姝ら棶棰樼殑姝昏剳绛嬫柟娉曞彲鑳芥槸浣跨敤姣忎釜绔欑偣鍒嗗埆浣跨敤涓嶅悓鐨勬暟鎹簱锛岀劧鍚庤姹傜珯鐐圭淮鎶よ呮妸鍚屼竴绡囨枃绔犲彂甯冧袱娆★細涓娆′负 LJWorld.com锛屽彟涓娆′负Lawrence.com銆備絾杩欏绔欑偣绠$悊鍛樻潵璇存槸浣庢晥鐜囩殑锛岃屼笖涓哄悓涓绡囨枃绔犲湪鏁版嵁搴撻噷淇濈暀澶氫釜鍓湰涔熸樉寰楀浣欍
The better solution? Both sites use the same article database, and an article is associated with one or more sites via a many-to-many relationship. The Django sites framework provides the database table to which articles can be related. Its a hook for associating data with one or more sites.
鏇村ソ鐨勮В鍐虫柟妗堬紵涓や釜缃戠珯鐢ㄧ殑鏄悓涓涓枃绔犳暟鎹簱锛屽苟灏嗘瘡涓绡囨枃绔犱笌涓涓垨澶氫釜绔欑偣鐢ㄥ瀵瑰鍏崇郴鍏宠仈璧锋潵銆侱jango 绔欑偣妗嗘灦鎻愪緵鏁版嵁搴撹杞藉摢浜涙枃绔犲彲浠ヨ鍏宠仈銆傚畠鏄竴涓妸鏁版嵁涓庝竴涓垨澶氫釜绔欑偣鍏宠仈璧锋潵鐨勯挬瀛愩
LJWorld.com and Lawrence.com both have e-mail alert functionality, which lets readers sign up to get notifications when news happens. Its pretty basic: a reader signs up on a Web form, and he immediately gets an e-mail saying, Thanks for your subscription.
LJWorld.com 鍜 Lawrence.com 閮芥湁閭欢鎻愰啋鍔熻兘锛屼娇璇昏呮敞鍐屽悗鍙互鍦ㄦ柊闂诲彂鐢熷悗绔嬪嵆鏀跺埌閫氱煡銆傝繖鏄竴绉嶅畬缇庣殑鐨勬満鍒讹細鏌愯鑰呮彁浜や簡娉ㄥ唽琛ㄥ崟锛岀劧鍚庨┈涓婂氨鍙楀埌涓灏佸唴瀹规槸鈥滄劅璋㈡偍鐨勬敞鍐屸濈殑閭欢銆
It would be inefficient and redundant to implement this signup-processing code twice, so the sites use the same code behind the scenes. But the Thank you for your subscription notice needs to be different for each site. By using Site objects, we can abstract the thank-you notice to use the values of the current sites name (e.g., 'LJWorld.com' ) and domain (e.g., 'www.ljworld.com' ).
鎶婅繖涓敞鍐岃繃绋嬬殑浠g爜瀹炵幇涓ら亶鏄剧劧鏄綆鏁堛佸浣欑殑锛屽洜姝や袱涓珯鐐瑰湪鍚庡彴浣跨敤鐩稿悓鐨勪唬鐮併備絾鎰熻阿娉ㄥ唽鐨勯氱煡鍦ㄤ袱涓綉绔欎腑闇瑕佷笉鍚屻傞氳繃浣跨敤 Site 瀵硅薄锛屾垜浠氳繃浣跨敤褰撳墠绔欑偣鐨 name (渚嬪 'LJWorld.com' )鍜 domain (渚嬪 'www.ljworld.com' )鍙互鎶婃劅璋㈤氱煡鎶芥彁鍑烘潵銆
The Django sites framework provides a place for you to store the name and domain for each site in your Django project, which means you can reuse those values in a generic way.
Django 鐨勫绔欑偣妗嗘灦涓轰綘鎻愪緵浜嗕竴涓綅缃潵瀛樺偍 Django 椤圭洰涓瘡涓珯鐐圭殑 name 鍜 domain 锛岃繖鎰忓懗鐫浣犲彲浠ョ敤鍚屾牱鐨勬柟娉曟潵閲嶇敤杩欎簺鍊笺
The sites framework is more a series of conventions than a framework. The whole thing is based on two simple concepts:
澶氱珯鐐规鏋朵笌鍏惰鏄竴涓鏋讹紝涓嶅璇存槸涓绯诲垪绾﹀畾銆傛墍鏈夌殑涓鍒囬兘鍩轰簬涓や釜绠鍗曠殑姒傚康锛
The Site model, found in django.contrib.sites , has domain and name fields.
浣嶄簬 django.contrib.sites 鐨 Site 妯″瀷鏈 domain 鍜 name 涓や釜瀛楁銆
The SITE_ID setting specifies the database ID of the Site object associated with that particular settings file.
SITE_ID 璁剧疆鎸囧畾浜嗕笌鐗瑰畾閰嶇疆鏂囦欢鐩稿叧鑱旂殑 Site 瀵硅薄涔嬫暟鎹簱 ID銆
How you use these two concepts is up to you, but Django uses them in a couple of ways automatically via simple conventions.
濡備綍杩愮敤杩欎袱涓蹇电敱浣犲喅瀹氾紝浣 Django 鏄氳繃鍑犱釜绠鍗曠殑绾﹀畾鑷姩浣跨敤鐨勩
To install the sites application, follow these steps:
瀹夎澶氱珯鐐瑰簲鐢ㄨ鎵ц浠ヤ笅鍑犱釜姝ラ锛
Add 'django.contrib.sites' to your INSTALLED_APPS .
灏 'django.contrib.sites' 鍔犲叆鍒 INSTALLED_APPS 涓
Run the command manage.py syncdb to install the django_site table into your database.
杩愯 manage.py syncdb 鍛戒护灏 django_site 琛ㄥ畨瑁呭埌鏁版嵁搴撲腑銆
Add one or more Site objects, either through the Django admin site or via the Python API. Create a Site object for each site/domain that this Django project powers.
閫氳繃 Django 绠$悊鍚庡彴鎴栭氳繃 Python API 娣诲姞涓涓垨鑰呭涓 ‘Site’ 瀵硅薄銆備负璇 Django 椤圭洰鏀拺鐨勬瘡涓珯锛堟垨鍩燂級鍒涘缓涓涓 Site 瀵硅薄銆
Define the SITE_ID setting in each of your settings files. This value should be the database ID of the Site object for the site powered by that settings file.
鍦ㄦ瘡涓缃枃浠朵腑瀹氫箟涓涓 SITE_ID 鍙橀噺銆傝鍙橀噺鍊煎簲褰撴槸璇ヨ缃枃浠舵墍鏀拺鐨勭珯鐐逛箣 Site 瀵硅薄鐨勬暟鎹簱 ID 銆
The sections that follow describe the various things you can do with the sites framework.
涓嬮潰鍑犺妭璁茶堪鐨勬槸鐢ㄥ绔欑偣妗嗘灦鑳藉瀹屾垚鐨勫嚑椤瑰伐浣溿
To reuse data on multiple sites, as explained in the first scenario, just create a ManyToManyField to Site in your models, for example:
姝e鍦ㄦ儏鏅竴涓墍瑙i噴鐨勶紝瑕佸湪澶氫釜绔欑偣闂撮噸鐢ㄦ暟鎹,浠呴渶鍦ㄦā鍨嬩腑涓 Site 娣诲姞涓涓 澶氬澶氬瓧娈 鍗冲彲锛屼緥濡傦細
from django.db import models from django.contrib.sites.models import Site class Article(models.Model): headline = models.CharField(maxlength=200) # ... sites = models.ManyToManyField(Site)
Thats the infrastructure you need to associate articles with multiple sites in your database. With that in place, you can reuse the same Django view code for multiple sites. Continuing the Article model example, heres what an article_detail view might look like:
杩欐槸鍦ㄦ暟鎹簱涓负澶氫釜绔欑偣杩涜鏂囩珷鍏宠仈鎿嶄綔鐨勫熀纭姝ラ銆傚湪閫傚綋鐨勪綅缃娇鐢ㄨ鎶鏈紝浣犲彲浠ュ湪澶氫釜绔欑偣涓噸澶嶄娇鐢ㄥ悓涓娈 Django 瑙嗗浘浠g爜銆傜户缁 Article 妯″瀷鑼冧緥锛屼笅闈㈡槸涓涓彲鑳界殑 article_detail 瑙嗗浘锛
from django.conf import settings def article_detail(request, article_id): try: a = Article.objects.get(id=article_id, sites__id=settings.SITE_ID) except Article.DoesNotExist: raise Http404 # ...
This view function is reusable because it checks the articles site dynamically, according to the value of the SITE_ID setting.
璇ヨ鍥炬柟娉曟槸鍙噸鐢ㄧ殑锛屽洜涓哄畠鏍规嵁 SITE_ID 璁剧疆鐨勫煎姩鎬佹鏌 articles 绔欑偣銆
For example, say LJWorld.coms settings file has a SITE_ID set to 1 , and Lawrence.coms settings file has a SITE_ID set to 2 . If this view is called when LJWorld.coms settings file is active, then it will limit the article lookup to articles in which the list of sites includes LJWorld.com.
渚嬪锛 LJWorld.coms 璁剧疆鏂囦欢涓湁鏈変釜 SITE_ID 璁剧疆涓 1 锛岃 Lawrence.coms 璁剧疆鏂囦欢涓湁涓 SITE_ID 璁剧疆涓 2 銆傚鏋滆瑙嗗浘鍦 LJWorld.coms 澶勪簬婵娲荤姸鎬佹椂琚皟鐢紝閭d箞瀹冨皢鎶婃煡鎵捐寖鍥村眬闄愪簬绔欑偣鍒楄〃鍖呮嫭 LJWorld.com 鍦ㄥ唴鐨勬枃绔犮
Similarly, you can associate a model to the Site model in a many-to-one relationship using ForeignKey .
鍚屾牱锛屼綘涔熷彲浠ヤ娇鐢 澶栭敭 鍦ㄥ瀵逛竴鍏崇郴涓皢涓涓ā鍨嬪叧鑱斿埌 Site 妯″瀷銆
For example, if an article is allowed on only a single site, you could use a model like this:
涓句緥鏉ヨ锛屽鏋滄煇绡囨枃绔犱粎浠呰兘澶熷嚭鐜板湪涓涓珯鐐逛笂锛屼綘鍙互浣跨敤涓嬮潰杩欐牱鐨勬ā鍨嬶細
from django.db import models from django.contrib.sites.models import Site class Article(models.Model): headline = models.CharField(maxlength=200) # ... site = models.ForeignKey(Site)
This has the same benefits as described in the last section.
杩欎笌鍓嶄竴鑺備腑浠嬬粛鐨勪竴鏍锋湁鐩娿
On a lower level, you can use the sites framework in your Django views to do particular things based on the site in which the view is being called, for example:
鍦ㄥ簳灞傦紝閫氳繃鍦 Django 瑙嗗浘涓娇鐢ㄥ绔欑偣妗嗘灦锛屼綘鍙互璁╄鍥炬牴鎹皟鐢ㄧ珯鐐逛笉鍚岃屽畬鎴愪笉鍚岀殑宸ヤ綔锛屼緥濡傦細
from django.conf import settings def my_view(request): if settings.SITE_ID == 3: # Do something. else: # Do something else.
Of course, its ugly to hard-code the site IDs like that. A slightly cleaner way of accomplishing the same thing is to check the current sites domain:
褰撶劧锛屽儚閭f牱瀵圭珯鐐 ID 杩涜纭紪鐮佹槸姣旇緝闅剧湅鐨勩傜暐涓虹畝娲佺殑瀹屾垚鏂瑰紡鏄煡鐪嬪綋鍓嶇殑绔欑偣鍩燂細
from django.conf import settings from django.contrib.sites.models import Site def my_view(request): current_site = Site.objects.get(id=settings.SITE_ID) if current_site.domain == 'foo.com': # Do something else: # Do something else.
The idiom of retrieving the Site object for the value of settings.SITE_ID is quite common, so the Site models manager (Site.objects ) has a get_current() method. This example is equivalent to the previous one:
浠 Site 瀵硅薄涓幏鍙 settings.SITE_ID 鍊肩殑鍋氭硶姣旇緝甯歌锛屽洜姝 Site 妯″瀷绠$悊鍣 (Site.objects ) 鍏峰涓涓 get_current() 鏂规硶銆備笅闈㈢殑渚嬪瓙涓庡墠涓涓槸绛夋晥鐨勶細
from django.contrib.sites.models import Site def my_view(request): current_site = Site.objects.get_current() if current_site.domain == 'foo.com': # Do something else: # Do something else.
Note
娉ㄦ剰
In this final example, you dont have to import django.conf.settings .
鍦ㄨ繖涓渶鍚庣殑渚嬪瓙閲岋紝浣犱笉鐢ㄥ鍏 django.conf.settings 銆
For a DRY (Dont Repeat Yourself) approach to storing your sites name and domain name, as explained in Scenario 2: Storing Your Site Name/Domain in One Place, just reference the name and domain of the current Site object. For example:
姝e鎯呮櫙浜屼腑鎵瑙i噴鐨勯偅鏍凤紝瀵逛簬鍌ㄥ瓨绔欏悕鍜屽煙鍚嶇殑 DRY (Dont Repeat Yourself) 鏂规硶锛堝湪涓涓綅缃偍瀛樼珯鍚嶅拰鍩熷悕锛夋潵璇达紝鍙渶寮曠敤褰撳墠 Site 瀵硅薄鐨 name 鍜 domain 銆備緥濡傦細
from django.contrib.sites.models import Site from django.core.mail import send_mail def register_for_newsletter(request): # Check form values, etc., and subscribe the user. # ... current_site = Site.objects.get_current() send_mail('Thanks for subscribing to %s alerts' % current_site.name, 'Thanks for your subscription. We appreciate it.\n\n-The %s team.' % current_site.name, 'editor@%s' % current_site.domain, [user_email]) # ...
Continuing our ongoing example of LJWorld.com and Lawrence.com, on Lawrence.com this e-mail has the subject line Thanks for subscribing to lawrence.com alerts. On LJWorld.com, the e-mail has the subject line Thanks for subscribing to LJWorld.com alerts. This same site-specific behavior is applied to the e-mails message body.
缁х画鎴戜滑姝e湪璁ㄨ鐨 LJWorld.com 鍜 Lawrence.com 渚嬪瓙锛屽湪Lawrence.com 璇ラ偖浠剁殑鏍囬琛屾槸鈥滄劅璋㈡敞鍐 Lawrence.com 鎻愰啋淇′欢鈥濄傚湪 LJWorld.com 锛岃閭欢鏍囬琛屾槸鈥滄劅璋㈡敞鍐 LJWorld.com 鎻愰啋淇′欢鈥濄傝繖绉嶇珯鐐瑰叧鑱旇涓烘柟寮忓閭欢淇℃伅涓讳綋涔熷悓鏍烽傜敤銆
An even more flexible (but more heavyweight) way of doing this would be to use Djangos template system. Assuming Lawrence.com and LJWorld.com have different template directories (TEMPLATE_DIRS ), you could simply delegate to the template system like so:
瀹屾垚杩欓」宸ヤ綔鐨勪竴绉嶆洿鍔犵伒娲伙紙浣嗛噸閲忕骇涔熸洿澶э級鐨勬柟娉曟槸浣跨敤 Django 鐨勬ā鏉跨郴缁熴傚亣瀹 Lawrence.com 鍜 LJWorld.com 鍚勮嚜鎷ユ湁涓嶅悓鐨勬ā鏉跨洰褰曪紙 TEMPLATE_DIRS 锛夛紝浣犲彲灏嗗伐浣滆交鏉惧湴杞氦缁欐ā鏉跨郴缁燂紝濡備笅鎵绀猴細
from django.core.mail import send_mail from django.template import loader, Context def register_for_newsletter(request): # Check form values, etc., and subscribe the user. # ... subject = loader.get_template('alerts/subject.txt').render(Context({})) message = loader.get_template('alerts/message.txt').render(Context({})) send_mail(subject, message, 'do-not-reply@example.com', [user_email]) # ...
In this case, you have to create subject.txt and message.txt templates in both the LJWorld.com and Lawrence.com template directories. As mentioned previously, that gives you more flexibility, but its also more complex.
鏈緥涓紝浣犱笉寰椾笉鍦 LJWorld.com 鍜 Lawrence.com 鐨勬ā鏉跨洰褰曚腑閮藉垱寤轰竴浠 subject.txt 鍜 message.txt 妯℃澘銆傛濡備箣鍓嶆墍璇达紝璇ユ柟娉曞甫鏉ヤ簡鏇村ぇ鐨勭伒娲绘э紝浣嗕篃甯︽潵浜嗘洿澶氬鏉傛с
Its a good idea to exploit the Site objects as much as possible to remove unneeded complexity and redundancy.
灏藉彲鑳藉鐨勫埄鐢 Site 瀵硅薄鏄噺灏戜笉蹇呰鐨勫鏉傘佸啑浣欏伐浣滅殑濂藉姙娉曘
Djangos get_absolute_url() convention is nice for getting your objects URLs without the domain name, but in some cases you might want to display the full URL with http:// and the domain and everything for an object. To do this, you can use the sites framework. Heres a simple example:
Django 鐨 get_absolute_url() 绾﹀畾瀵逛笌鑾峰彇涓嶅甫鍩熷悕鐨勫璞 URL 闈炲父鐞嗘兂锛屼絾鍦ㄦ煇浜涙儏褰笅锛屼綘鍙兘鎯虫樉绀烘煇涓璞″甫鏈 http:// 鍜屽煙鍚嶄互鍙婃墍鏈夐儴鍒嗙殑瀹屾暣 URL 銆傝瀹屾垚姝ゅ伐浣滐紝浣犲彲浠ヤ娇鐢ㄥ绔欑偣妗嗘灦銆備笅闈㈡槸涓畝鍗曠殑渚嬪瓙锛
>>> from django.contrib.sites.models import Site >>> obj = MyModel.objects.get(id=3) >>> obj.get_absolute_url() '/mymodel/objects/3/' >>> Site.objects.get_current().domain 'example.com' >>> 'http://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url()) 'http://example.com/mymodel/objects/3/'
If Site``s play a key role in your application, consider using the helpful ``CurrentSiteManager in your model(s). Its a model manager (see Appendix B) that automatically filters its queries to include only objects associated with the current Site .
濡傛灉 绔欑偣 鍦ㄤ綘鐨勫簲鐢ㄤ腑鎵紨寰堥噸瑕佺殑瑙掕壊锛岃鑰冭檻鍦ㄤ綘鐨勬ā鍨嬩腑浣跨敤鏂逛究鐨 CurrentSiteManager 銆傝繖鏄竴涓ā鍨嬬鐞嗗櫒锛堣闄勫綍B锛夛紝瀹冧細鑷姩杩囨护浣垮叾鍙寘鍚笌褰撳墠 绔欑偣 鐩稿叧鑱旂殑瀵硅薄銆
Use CurrentSiteManager by adding it to your model explicitly. For example:
閫氳繃鏄剧ず鍦板皢 CurrentSiteManager 鍔犲叆妯″瀷涓互浣跨敤瀹冦備緥濡傦細
from django.db import models from django.contrib.sites.models import Site from django.contrib.sites.managers import CurrentSiteManager class Photo(models.Model): photo = models.FileField(upload_to='/home/photos') photographer_name = models.CharField(maxlength=100) pub_date = models.DateField() site = models.ForeignKey(Site) objects = models.Manager() on_site = CurrentSiteManager()
With this model, Photo.objects.all() will return all Photo objects in the database, but Photo.on_site.all() will return only the Photo objects associated with the current site, according to the SITE_ID setting.
閫氳繃璇ユā鍨嬶紝 Photo.objects.all() 灏嗚繑鍥炴暟鎹簱涓墍鏈夌殑 Photo 瀵硅薄锛岃 Photo.on_site.all() 浠呮牴鎹 SITE_ID 璁剧疆杩斿洖涓庡綋鍓嶇珯鐐圭浉鍏宠仈鐨 Photo 瀵硅薄銆
In other words, these two statements are equivalent:
鎹㈣█涔嬶紝浠ヤ笅涓ゆ潯璇彞鏄瓑鏁堢殑锛
Photo.objects.filter(site=settings.SITE_ID) Photo.on_site.all()
How did CurrentSiteManager know which field of Photo was the Site ? It defaults to looking for a field called site . If your model has a ForeignKey or ManyToManyField called something other than site , you need to explicitly pass that as the parameter to CurrentSiteManager . The following model, which has a field called publish_on , demonstrates this:
CurrentSiteManager 鏄浣曠煡閬 Photo 鐨勫摢涓瓧娈垫槸 Site 鍛紵缂虹渷鎯呭喌涓嬶紝瀹冧細鏌ユ壘涓涓彨鍋 site 鐨勫瓧娈点傚鏋滄ā鍨嬩腑鏈変釜 澶栭敭 鎴 澶氬澶氬瓧娈 鍙仛 site 涔嬪 鐨勫悕瀛楋紝浣犲繀椤绘樉绀哄湴灏嗗畠浣滀负鍙傛暟浼犻掔粰 CurrentSiteManager 銆備笅闈㈢殑妯″瀷涓湁涓彨鍋 publish_on 鐨勫瓧娈碉紝濡備笅鎵绀猴細
from django.db import models from django.contrib.sites.models import Site from django.contrib.sites.managers import CurrentSiteManager class Photo(models.Model): photo = models.FileField(upload_to='/home/photos') photographer_name = models.CharField(maxlength=100) pub_date = models.DateField() publish_on = models.ForeignKey(Site) objects = models.Manager() on_site = CurrentSiteManager('publish_on')
If you attempt to use CurrentSiteManager and pass a field name that doesnt exist, Django will raise a ValueError .
濡傛灉璇曞浘浣跨敤 CurrentSiteManager 骞朵紶鍏ヤ竴涓笉瀛樺湪鐨勫瓧娈靛悕锛 Django 灏嗗紩鍙戜竴涓 ValueError 寮傚父銆
Note
娉ㄦ剰浜嬮」
Youll probably want to keep a normal (non-site-specific) Manager on your model, even if you use CurrentSiteManager . As explained in Appendix B, if you define a manager manually, then Django wont create the automatic objects = models.Manager() manager for you.
鍗充究鏄凡缁忎娇鐢ㄤ簡 CurrentSiteManager 锛屼綘涔熻杩樻兂鍦ㄦā鍨嬩腑鎷ユ湁涓涓甯哥殑锛堥潪绔欑偣鐩稿叧锛夌殑 绠$悊鍣 銆傛濡傚湪闄勫綍 B 涓墍瑙i噴鐨勶紝濡傛灉浣犳墜鍔ㄥ畾涔変簡涓涓鐞嗗櫒锛岄偅涔 Django 涓嶄細涓轰綘鍒涘缓鍏ㄨ嚜鍔ㄧ殑 objects = models.Manager() 绠$悊鍣ㄣ
Also, certain parts of Django namely, the Django admin site and generic views use whichever manager is defined first in the model, so if you want your admin site to have access to all objects (not just site-specific ones), put objects = models.Manager() in your model, before you define CurrentSiteManager .
鍚屾牱锛孌jango 鐨勭壒瀹氶儴鍒嗏斺斿嵆 Django 瓒呯骇绠$悊绔欑偣鍜岄氱敤瑙嗗浘鈥斺斾娇鐢ㄧ殑绠$悊鍣 棣栧厛 鍦ㄦā鍨嬩腑瀹氫箟锛屽洜姝ゅ鏋滃笇鏈涜秴绾х鐞嗙珯鐐硅兘澶熻闂墍鏈夊璞★紙鑰屼笉鏄粎浠呯珯鐐圭壒鏈夊璞★級锛岃浜庡畾涔 CurrentSiteManager 涔嬪墠鍦ㄦā鍨嬩腑鏀惧叆 objects = models.Manager() 銆
Although its not required that you use the sites framework, its strongly encouraged, because Django takes advantage of it in a few places. Even if your Django installation is powering only a single site, you should take a few seconds to create the site object with your domain and name , and point to its ID in your SITE_ID setting.
灏界骞朵笉鏄繀椤荤殑锛屾垜浠繕鏄己鐑堝缓璁娇鐢ㄥ绔欑偣妗嗘灦锛屽洜涓 Django 鍦ㄥ嚑涓湴鏂瑰埄鐢ㄤ簡瀹冦傚嵆浣垮彧鐢 Django 鏉ユ敮鎸佸崟涓綉绔欙紝浣犱篃搴旇鑺变竴鐐规椂闂寸敤 domain 鍜 name 鏉ュ垱寤虹珯鐐瑰璞★紝骞跺皢 SITE_ID 璁剧疆鎸囧悜瀹冪殑 ID 銆
Heres how Django uses the sites framework:
浠ヤ笅璁茶堪鐨勬槸 Django 濡備綍浣跨敤澶氱珯鐐规鏋讹細
In the redirects framework (see the later section Redirects), each redirect object is associated with a particular site. When Django searches for a redirect, it takes into account the current SITE_ID .
鍦ㄩ噸瀹氬悜妗嗘灦涓紙瑙佸悗闈㈢殑閲嶅畾鍚戜竴鑺傦級锛屾瘡涓涓噸瀹氬悜瀵硅薄閮戒笌涓涓壒瀹氱珯鐐瑰叧鑱斻傚綋 Django 鎼滅储閲嶅畾鍚戠殑鏃跺欙紝瀹冧細鑰冭檻褰撳墠鐨 SITE_ID 銆
In the comments framework, each comment is associated with a particular site. When a comment is posted, its site is set to the current SITE_ID , and when comments are listed via the appropriate template tag, only the comments for the current site are displayed.
鍦ㄦ敞鍐屾鏋朵腑锛屾瘡涓敞閲婇兘涓庣壒瀹氱珯鐐圭浉鍏炽傛瘡涓敞閲婅寮犺创鏃讹紝鍏 site 琚缃负褰撳墠鐨 SITE_ID 锛岃屽綋閫氳繃閫傚綋鐨勬ā鏉挎爣绛惧垪鍑烘敞閲婃椂锛屽彧鏈夊綋鍓嶇珯鐐圭殑娉ㄩ噴灏嗕細鏄剧ず銆
In the flatpages framework (see the later section Flatpages), each flatpage is associated with a particular site. When a flatpage is created, you specify its site , and the flatpage middleware checks the current SITE_ID in retrieving flatpages to display.
鍦 flatpages 妗嗘灦涓 (鍙傝鍚庨潰鐨 Flatpages 涓鑺傦級锛屾瘡涓 flatpage 閮戒笌鐗瑰畾鐨勭珯鐐圭浉鍏宠仈銆傚垱寤 flatpage 鏃讹紝浣犻兘灏嗘寚瀹氬畠鐨 site 锛岃 flatpage 涓棿浠跺湪鑾峰彇 flatpage 浠ユ樉绀哄畠鐨勮繃绋嬩腑锛屽皢鏌ョ湅褰撳墠鐨 SITE_ID 銆
In the syndication framework (see Chapter 11), the templates for title and description automatically have access to a variable {{ site }} , which is the Site object representing the current site. Also, the hook for providing item URLs will use the domain from the current Site object if you dont specify a fully qualified domain.
鍦 syndication 妗嗘灦涓紙鍙傞槄绗 11 绔狅級锛 title 鍜 description 鐨勬ā鏉胯嚜鍔ㄨ闂彉閲 {{ site }} 锛屽畠灏辨槸浠h〃褰撳墠鐫妗ㄧ殑 Site 瀵硅薄銆傝屼笖锛屽鏋滀綘涓嶆寚鍑轰竴涓畬鍏ㄥ悎鏍肩殑domain鐨勮瘽锛屾彁渚涚洰褰昒RLS鐨勯挬瀛愬皢浼氫娇鐢ㄥ綋鍓嶁淪ite鈥濆璞$殑domain銆
In the authentication framework (see Chapter 12), the django.contrib.auth.views.login view passes the current Site name to the template as {{ site_name }} .
鍦ㄨ韩浠介獙璇佹鏋讹紙鍙傝绗 12 绔狅級涓紝 django.contrib.auth.views.login 瑙嗗浘灏嗗綋鍓 Site 鍚嶇О浣滀负 {{ site_name }} 浼犻掔粰妯℃澘銆
Often youll have a database-driven Web application up and running, but youll need to add a couple of one-off static pages, such as an About page or a Privacy Policy page. It would be possible to use a standard Web server such as Apache to serve these files as flat HTML files, but that introduces an extra level of complexity into your application, because then you have to worry about configuring Apache, you have to set up access for your team to edit those files, and you cant take advantage of Djangos template system to style the pages.
灏界閫氬父鎯呭喌涓嬫绘槸寤洪犲拰杩愯鏁版嵁搴撻┍鍔ㄧ殑 Web 搴旂敤锛屼綘杩樻槸浼氶渶瑕佹坊鍔犱竴涓ゅ紶涓娆℃х殑闈欐侀〉闈紝渚嬪鈥滃叧浜庘濋〉闈紝鎴栬呪滈殣绉佺瓥鐣モ濋〉闈㈢瓑绛夈傚彲浠ョ敤鍍 Apache 杩欐牱鐨勬爣鍑哤eb鏈嶅姟鍣ㄦ潵澶勭悊杩欎簺闈欐侀〉闈紝浣嗗嵈浼氱粰搴旂敤甯︽潵涓浜涢澶栫殑澶嶆潅鎬э紝鍥犱负浣犲繀椤绘搷蹇冩庝箞閰嶇疆 Apache锛岃繕瑕佽缃潈闄愯鏁翠釜鍥㈤槦鍙互淇敼缂栬緫杩欎簺鏂囦欢锛岃屼笖浣犺繕涓嶈兘浣跨敤 Django 妯℃澘绯荤粺鏉ョ粺涓杩欎簺椤甸潰鐨勯鏍笺
The solution to this problem is Djangos flatpages application, which lives in the package django.contrib.flatpages . This application lets you manage such one-off pages via Djangos admin site, and it lets you specify templates for them using Djangos template system. It uses Django models behind the scenes, which means it stores the pages in a database, just like the rest of your data, and you can access flatpages with the standard Django database API.
杩欎釜闂鐨勮В鍐虫柟妗堟槸浣跨敤浣嶄簬 django.contrib.flatpages 寮鍙戝寘涓殑 Django 绠鍗曢〉闈紙flatpages锛夊簲鐢ㄧ▼搴忋傝搴旂敤璁╀綘鑳藉閫氳繃 Django 瓒呯骇绠$悊绔欑偣鏉ョ鐞嗚繖浜涗竴娆℃х殑椤甸潰锛岃繕鍙互璁╀綘浣跨敤 Django 妯℃澘绯荤粺鎸囧畾瀹冧滑浣跨敤鍝釜妯℃澘銆傚畠鍦ㄥ悗鍙颁娇鐢ㄤ簡 Django 妯″瀷锛屼篃灏辨槸璇村畠灏嗛〉闈㈠瓨鏀惧湪鏁版嵁搴撲腑锛屼綘涔熷彲浠ュ儚瀵瑰緟鍏朵粬鏁版嵁涓鏍风敤鏍囧噯 Django 鏁版嵁搴 API 瀛樺彇绠鍗曢〉闈€
Flatpages are keyed by their URL and site. When you create a flatpage, you specify which URL its associated with, along with which site(s) its on. (For more on sites, see the Sites section.)
绠鍗曢〉闈互瀹冧滑鐨 URL 鍜岀珯鐐逛负閿笺傚綋鍒涘缓绠鍗曢〉闈㈡椂锛屼綘鎸囧畾瀹冧笌鍝釜URL浠ュ強鍜屽摢涓珯鐐圭浉鍏宠仈 銆傦紙鏈夊叧绔欑偣鐨勬洿澶氫俊鎭紝璇锋煡闃呫婄珯鐐广嬩竴鑺傦級
To install the flatpages application, follow these steps:
瀹夎绠鍗曢〉闈㈠簲鐢ㄧ▼搴忓繀椤绘寜鐓т笅闈㈢殑姝ラ锛
Add 'django.contrib.flatpages' to your INSTALLED_APPS . django.contrib.flatpages depends on django.contrib.sites , so make sure the both packages are in INSTALLED_APPS .
娣诲姞 'django.contrib.flatpages' 鍒 INSTALLED_APPS 璁剧疆銆 django.contrib.flatpages 渚濊禆浜 django.contrib.sites , 鎵浠ョ‘淇濊繖涓や釜寮鍙戝寘閮藉寘鎷湪 INSTALLED_APPS 璁剧疆涓
Add 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' to your MIDDLEWARE_CLASSES setting.
灏 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' 娣诲姞鍒 MIDDLEWARE_CLASSES 璁剧疆涓
Run the command manage.py syncdb to install the two required tables into your database.
杩愯 manage.py syncdb 鍛戒护鍦ㄦ暟鎹簱涓垱寤哄繀闇鐨勪袱涓〃銆
The flatpages application creates two tables in your database: django_flatpage and django_flatpage_sites . django_flatpage simply maps a URL to a title and bunch of text content. django_flatpage_sites is a many-to-many table that associates a flatpage with one or more sites.
绠鍗曢〉闈㈠簲鐢ㄧ▼搴忓湪鏁版嵁搴撲腑鍒涘缓涓や釜琛細 django_flatpage 鍜 django_flatpage_sites 銆 django_flatpage 鍙槸灏 URL 鏄犲皠鍒版爣棰樺拰涓娈垫枃鏈唴瀹广 django_flatpage_sites 鏄竴涓瀵瑰琛紝鐢ㄤ簬鍏宠仈鏌愪釜绠鍗曢〉闈互鍙婁竴涓垨澶氫釜绔欑偣銆
The application comes with a single FlatPage model, defined in django/contrib/flatpages/models.py . It looks like this:
璇ュ簲鐢ㄦ墍甯︽潵鐨 FlatPage 妯″瀷鍦 django/contrib/flatpages/models.py 杩涜瀹氫箟锛屽涓嬫墍绀猴細
from django.db import models from django.contrib.sites.models import Site class FlatPage(models.Model): url = models.CharField(maxlength=100) title = models.CharField(maxlength=200) content = models.TextField() enable_comments = models.BooleanField() template_name = models.CharField(maxlength=70, blank=True) registration_required = models.BooleanField() sites = models.ManyToManyField(Site)
Lets examine these fields one at a time:
璁╂垜浠愰」鐪嬬湅杩欎簺瀛楁鐨勫惈涔夛細
url : The URL at which this flatpage lives, excluding the domain name but including the leading slash (e.g., /about/contact/ ).
url : 璇ョ畝鍗曢〉闈㈡墍澶勭殑 URL锛屼笉鍖呮嫭鍩熷悕锛屼絾鏄寘鍚墠瀵兼枩鏉 (渚嬪 /about/contact/ )銆
title : The title of the flatpage. The framework doesnt do anything special with this. Its your responsibility to display it in your template.
title : 绠鍗曢〉闈㈢殑鏍囬銆傛鏋朵笉瀵瑰畠浣滀换浣曠壒娈婂鐞嗐傜敱浣犻氳繃妯℃澘鏉ユ樉绀哄畠銆
content : The content of the flatpage (i.e., the HTML of the page). The framework doesnt do anything special with this. Its your responsibility to display it in the template.
content : 绠鍗曢〉闈㈢殑鍐呭 (鍗 HTML 椤甸潰)銆傛鏋朵笉浼氬瀹冧綔浠讳綍鐗瑰埆澶勭悊銆傜敱浣犺礋璐d娇鐢ㄦā鏉挎潵鏄剧ず銆
enable_comments : Whether to enable comments on this flatpage. The framework doesnt do anything special with this. You can check this value in your template and display a comment form if needed.
enable_comments : 鏄惁鍏佽璇ョ畝鍗曢〉闈娇鐢ㄨ瘎璁恒傛鏋朵笉瀵规鍋氫换浣曠壒鍒鐞嗐備綘鍙湪妯℃澘涓鏌ヨ鍊煎苟鏍规嵁闇瑕佹樉绀鸿瘎璁虹獥浣撱
template_name : The name of the template to use for rendering this flatpage. This is optional; if its not given or if this template doesnt exist, the framework will fall back to the template flatpages/default.html .
template_name : 鐢ㄦ潵瑙f瀽璇ョ畝鍗曢〉闈㈢殑妯℃澘鍚嶇О銆傝繖鏄竴涓彲閫夐」锛涘鏋滄湭鎸囧畾妯℃澘鎴栬妯℃澘涓嶅瓨鍦紝绯荤粺浼氶鑰屼娇鐢ㄩ粯璁ゆā鏉 flatpages/default.html 銆
registration_required : Whether registration is required for viewing this flatpage. This integrates with Djangos authentication/user framework, which is explained further in Chapter 12.
registration_required : 鏄惁娉ㄥ唽鐢ㄦ埛鎵嶈兘鏌ョ湅姝ょ畝鍗曢〉闈€傝璁剧疆椤归泦鎴愪簡 Djangos 楠岃瘉/鐢ㄦ埛妗嗘灦锛岃妗嗘灦浜庣鍗佷簩绔犺杩般
sites : The sites that this flatpage lives on. This integrates with Djangos sites framework, which is explained in the Sites section of this chapter.
sites : 璇ョ畝鍗曢〉闈㈡斁缃殑绔欑偣銆傝椤硅缃泦鎴愪簡 Django 澶氱珯鐐规鏋讹紝璇ユ鏋跺湪鏈珷鐨勩婂绔欑偣銆嬩竴鑺備腑鏈夋墍闃愯堪銆
You can create flatpages through either the Django admin interface or the Django database API. For more information on this, see the section Adding, Changing, and Deleting Flatpages.
浣犲彲浠ラ氳繃 Django 瓒呯骇绠$悊鐣岄潰鎴栬 Django 鏁版嵁搴 API 鏉ュ垱寤虹畝鍗曢〉闈€傝浜嗚В鏇村鍐呭锛岃鏌ラ槄銆婃坊鍔犮佷慨鏀瑰拰鍒犻櫎绠鍗曢〉闈€嬩竴鑺傘
Once youve created flatpages, FlatpageFallbackMiddleware does all of the work. Each time any Django application raises a 404 error, this middleware checks the flatpages database for the requested URL as a last resort. Specifically, it checks for a flatpage with the given URL with a site ID that corresponds to the SITE_ID setting.
涓鏃︾畝鍗曢〉闈㈠垱寤哄畬鎴愶紝 FlatpageFallbackMiddleware 灏嗗畬鎴愶紙鍓╀笅锛夋墍鏈夌殑宸ヤ綔銆傛瘡褰 Django 寮曞彂 404 閿欒锛屼綔涓虹粓鏋佹墜娈碉紝璇ヤ腑闂翠欢灏嗘牴鎹墍璇锋眰鐨 URL 妫鏌ュ钩椤甸潰鏁版嵁搴撱傜‘鍒囧湴璇达紝瀹冨皢浣跨敤鎵鎸囧畾鐨 URL浠ュ強 SITE_ID 璁剧疆瀵瑰簲鐨勭珯鐐 ID 鏌ユ壘涓涓畝鍗曢〉闈€
If it finds a match, it loads the flatpages template or flatpages/default.html if the flatpage has not specified a custom template. It passes that template a single context variable, flatpage , which is the flatpage object. It uses RequestContext in rendering the template.
濡傛灉鎵惧埌涓涓尮閰嶉」锛屽畠灏嗚浇鍏ヨ绠鍗曢〉闈㈢殑妯℃澘锛堝鏋滄病鏈夋寚瀹氱殑璇濓紝灏嗕娇鐢ㄩ粯璁ゆā鏉 flatpages/default.html 锛夈傚悓鏃讹紝瀹冩妸涓涓畝鍗曠殑涓婁笅鏂囧彉閲忊斺 flatpage 锛堜竴涓畝鍗曢〉闈㈠璞★級浼犻掔粰妯℃澘銆傚湪妯℃澘瑙f瀽杩囩▼涓紝瀹冨疄闄呯敤鐨勬槸 RequestContext 銆
If FlatpageFallbackMiddleware doesnt find a match, the request continues to be processed as usual.
濡傛灉 FlatpageFallbackMiddleware 娌℃湁鎵惧埌鍖归厤椤癸紝璇ヨ姹傜户缁甯稿鐞嗐
Note
娉ㄦ剰
This middleware only gets activated for 404 (page not found) errors not for 500 (server error) or other error responses. Also note that the order of MIDDLEWARE_CLASSES matters. Generally, you can put FlatpageFallbackMiddleware at or near the end of the list, because its a last resort.
璇ヤ腑闂翠欢浠呭湪鍙戠敓 404 锛堥〉闈㈡湭鎵惧埌锛夐敊璇椂琚縺娲伙紝鑰屼笉浼氬湪 500 锛堟湇鍔″櫒閿欒锛夋垨鍏朵粬閿欒鍝嶅簲鏃惰婵娲汇傝繕瑕佹敞鎰忕殑鏄繀椤昏冭檻 MIDDLEWARE_CLASSES 鐨勯『搴忛棶棰樸傞氬父锛屼綘鍙互鎶 FlatpageFallbackMiddleware 鏀惧湪鍒楄〃鏈鍚庯紝鍥犱负瀹冩槸涓绉嶇粓鏋佹墜娈点
You can add, change and delete flatpages in two ways:
鍙互鐢ㄤ袱绉嶆柟寮忓鍔犮佸彉鏇存垨鍒犻櫎绠鍗曢〉闈細
If youve activated the automatic Django admin interface, you should see a Flatpages section on the admin index page. Edit flatpages as you would edit any other object in the system.
濡傛灉宸茬粡婵娲讳簡鑷姩鐨 Django 瓒呯骇绠$悊鐣岄潰锛屼綘灏嗕細鍦ㄨ秴绾х鐞嗛〉闈㈢殑棣栭〉鐪嬪埌鏈変釜 Flatpages 鍖哄煙銆備綘鍙互鍍忕紪杈戠郴缁熶腑鍏跺畠瀵硅薄閭f牱缂栬緫绠鍗曢〉闈€
As described previously, flatpages are represented by a standard Django model that lives in django/contrib/flatpages/models.py . Hence, you can access flatpage objects via the Django database API, for example:
鍓嶉潰宸茬粡鎻愬埌锛岀畝鍗曢〉闈㈣〃鐜颁负 django/contrib/flatpages/models.py 涓殑鏍囧噯 Django 妯″瀷銆傚洜姝わ紝浣犲彲浠ラ氳繃 Django 鏁版嵁搴 API 鏉ュ瓨鍙栫畝鍗曢〉闈㈠璞★紝渚嬪锛
>>> from django.contrib.flatpages.models import FlatPage >>> from django.contrib.sites.models import Site >>> fp = FlatPage( ... url='/about/', ... title='About', ... content='<p>About this site...</p>', ... enable_comments=False, ... template_name='', ... registration_required=False, ... ) >>> fp.save() >>> fp.sites.add(Site.objects.get(id=1)) >>> FlatPage.objects.get(url='/about/') <FlatPage: /about/ -- About>
By default, flatpages are rendered via the template flatpages/default.html , but you can override that for a particular flatpage with the template_name field on the FlatPage object.
缂虹渷鎯呭喌涓嬶紝绯荤粺浣跨敤妯℃澘 flatpages/default.html 鏉ヨВ鏋愮畝鍗曢〉闈紝浣嗕綘涔熷彲浠ラ氳繃璁惧畾 FlatPage 瀵硅薄鐨 template_name 瀛楁鏉ヨ鐩栫壒瀹氱畝鍗曢〉闈㈢殑妯℃澘銆
Creating the flatpages/default.html template is your responsibility. In your template directory, just create a flatpages directory containing a default.html file.
浣犲繀椤昏嚜宸卞垱寤 flatpages/default.html 妯℃澘銆傚彧闇瑕佸湪妯℃澘鐩綍鍒涘缓涓涓 flatpages 鐩綍锛屽苟鎶 default.html 鏂囦欢缃簬鍏朵腑銆
Flatpage templates are passed a single context variable, flatpage , which is the flatpage object.
绠鍗曢〉闈㈡ā鏉垮彧鎺ュ彈鏈変竴涓笂涓嬫枃鍙橀噺鈥斺 flatpage 锛屼篃灏辨槸璇ョ畝鍗曢〉闈㈠璞°
Heres a sample flatpages/default.html template:
浠ヤ笅鏄竴涓 flatpages/default.html 妯℃澘鑼冧緥:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <html> <head> <title>{{ flatpage.title }}</title> </head> <body> {{ flatpage.content }} </body> </html>
Djangos redirects framework lets you manage redirects easily by storing them in a database and treating them as any other Django model object. For example, you can use the redirects framework to tell Django, Redirect any request to /music/ to /sections/arts/music/ . This comes in handy when you need to move things around on your site; Web developers should do whatever is necessary to avoid broken links.
閫氳繃灏嗛噸瀹氬悜瀛樺偍鍦ㄦ暟鎹簱涓苟灏嗗叾瑙嗕负 Django 妯″瀷瀵硅薄锛孌jango 閲嶅畾鍚戞鏋惰浣犺兘澶熻交鏉惧湴绠$悊瀹冧滑銆傛瘮濡傝锛屼綘鍙互閫氳繃閲嶅畾鍚戞鏋跺憡璇塂jango锛屾妸浠讳綍鎸囧悜 /music/ 鐨勮姹傞噸瀹氬悜鍒 /sections/arts/music/ 銆傚綋浣犻渶瑕佸湪绔欑偣涓Щ鍔ㄤ竴浜涗笢瑗挎椂锛岃繖椤瑰姛鑳藉氨娲句笂鐢ㄥ満浜嗏斺旂綉绔欏紑鍙戣呭簲璇ョ┓灏戒竴鍒囧姙娉曢伩鍏嶅嚭鐜板潖閾炬帴銆
To install the redirects application, follow these steps:
瀹夎閲嶅畾鍚戝簲鐢ㄧ▼搴忓繀椤婚伒寰互涓嬫楠わ細
Add 'django.contrib.redirects' to your INSTALLED_APPS .
灏 'django.contrib.redirects' 娣诲姞鍒 INSTALLED_APPS 璁剧疆涓
Add 'django.contrib.redirects.middleware.RedirectFallbackMiddleware' to your MIDDLEWARE_CLASSES setting.
灏 'django.contrib.redirects.middleware.RedirectFallbackMiddleware' 娣诲姞鍒 MIDDLEWARE_CLASSES 璁剧疆涓
Run the command manage.py syncdb to install the single required table into your database.
杩愯 manage.py syncdb 鍛戒护灏嗘墍闇鐨勮〃瀹夎鍒版暟鎹簱涓
manage.py syncdb creates a django_redirect table in your database. This is a simple lookup table with site_id , old_path , and new_path fields.
manage.py syncdb 鍦ㄦ暟鎹簱涓垱寤轰簡涓涓 django_redirect 琛ㄣ傝繖鏄竴涓畝鍗曠殑鏌ヨ琛紝鍙湁 site_id 銆 old_path 鍜 new_path 涓変釜瀛楁銆
You can create redirects through either the Django admin interface or the Django database API. For more, see the section Adding, Changing, and Deleting Redirects.
浣犲彲浠ラ氳繃 Django 瓒呯骇绠$悊鐣岄潰鎴栬 Django 鏁版嵁搴 API 鏉ュ垱寤洪噸瀹氬悜銆傝浜嗚В鏇村淇℃伅锛岃鍙傞槄銆婂鍔犮佸彉鏇村拰鍒犻櫎閲嶅畾鍚戙嬩竴鑺傘
Once youve created redirects, the RedirectFallbackMiddleware class does all of the work. Each time any Django application raises a 404 error, this middleware checks the redirects database for the requested URL as a last resort. Specifically, it checks for a redirect with the given old_path with a site ID that corresponds to the SITE_ID setting. (See the earlier section Sites for more information on SITE_ID and the sites framework.) Then it follows these steps:
涓鏃﹀垱寤轰簡閲嶅畾鍚戯紝 RedirectFallbackMiddleware 绫诲皢瀹屾垚鎵鏈夌殑宸ヤ綔銆傛瘡褰 Django 搴旂敤寮曞彂涓涓 404 閿欒锛屼綔涓虹粓鏋佹墜娈碉紝璇ヤ腑闂翠欢灏嗕负鎵璇锋眰鐨 URL 鍦ㄩ噸瀹氬悜鏁版嵁搴撲腑杩涜鏌ユ壘銆傜‘鍒囧湴璇达紝瀹冨皢浣跨敤缁欏畾鐨 old_path 浠ュ強 SITE_ID 璁剧疆瀵瑰簲鐨勭珯鐐 ID 鏌ユ壘閲嶅畾鍚戣缃傦紙鏌ラ槄鍓嶉潰鐨勩婂绔欑偣銆嬩竴鑺傚彲浜嗚В鍏充簬 SITE_ID 鍜屽绔欑偣妗嗘灦鐨勬洿澶氱粏鑺傦級 鐒跺悗锛屽畠灏嗘墽琛屼互涓嬩袱涓楠わ細
If it finds a match, and new_path is not empty, it redirects to new_path .
濡傛灉鎵惧埌浜嗗尮閰嶉」锛屽苟涓 new_path 闈炵┖锛屽畠灏嗛噸瀹氬悜鍒 new_path 銆
If it finds a match, and new_path is empty, it sends a 410 (Gone) HTTP header and an empty (contentless) response.
濡傛灉鎵惧埌浜嗗尮閰嶉」锛屼絾 new_path 涓虹┖锛屽畠灏嗗彂閫佷竴涓 410 (Gone) HTTP 澶翠俊鎭互鍙婁竴涓┖锛堟棤鍐呭锛夊搷搴斻
If it doesnt find a match, the request continues to be processed as usual.
濡傛灉鏈壘鍒板尮閰嶉」锛岃璇锋眰灏嗗甯稿鐞嗐
The middleware only gets activated for 404 errors not for 500 errors or responses of any other status code.
璇ヤ腑闂翠欢浠呬负 404 閿欒婵娲伙紝鑰屼笉浼氫负 500 閿欒鎴栧叾浠栦换浣曠姸鎬佺爜鐨勫搷搴旀墍婵娲汇
Note that the order of MIDDLEWARE_CLASSES matters. Generally, you can put RedirectFallbackMiddleware toward the end of the list, because its a last resort.
娉ㄦ剰蹇呴』鑰冭檻 MIDDLEWARE_CLASSES 鐨勯『搴忋傞氬父锛屼綘鍙互灏 RedirectFallbackMiddleware 鏀剧疆鍦ㄥ垪琛ㄧ殑鏈鍚庯紝鍥犱负瀹冩槸涓绉嶇粓鏋佹墜娈点
Note
娉ㄦ剰
If youre using both the redirect and flatpage fallback middleware, consider which one (redirect or flatpage) youd like checked first. We suggest flatpages before redirects (thus putting the flatpage middleware before the redirect middleware), but you might feel differently.
濡傛灉鍚屾椂浣跨敤閲嶅畾鍚戝拰绠鍗曢〉闈㈠洖閫涓棿浠讹紝 蹇呴』鑰冭檻鍏堟鏌ュ叾涓殑鍝竴涓紙閲嶅畾鍚戞垨绠鍗曢〉闈級銆傛垜浠缓璁皢绠鍗曢〉闈㈡斁鍦ㄩ噸瀹氬悜涔嬪墠锛堝洜姝ゅ皢绠鍗曢〉闈腑闂翠欢鏀剧疆鍦ㄩ噸瀹氬悜涓棿浠朵箣鍓嶏級锛屼絾浣犲彲鑳芥湁涓嶅悓鎯虫硶銆
You can add, change and delete redirects in two ways:
浣犲彲浠ヤ袱绉嶆柟寮忓鍔犮佸彉鏇村拰鍒犻櫎閲嶅畾鍚戯細
If youve activated the automatic Django admin interface, you should see a Redirects section on the admin index page. Edit redirects as you would edit any other object in the system.
濡傛灉宸茬粡婵娲讳簡鍏ㄨ嚜鍔ㄧ殑 Django 瓒呯骇绠$悊鐣岄潰锛屼綘搴旇鑳藉鍦ㄨ秴绾х鐞嗛椤电湅鍒伴噸瀹氬悜鍖哄煙銆傚彲浠ュ儚缂栬緫绯荤粺涓叾瀹冨璞′竴鏍风紪杈戦噸瀹氬悜銆
Redirects are represented by a standard Django model that lives in django/contrib/redirects/models.py . Hence, you can access redirect objects via the Django database API, for example:
django/contrib/redirects/models.py 涓殑涓涓爣鍑 Django 妯″瀷浠h〃浜嗛噸瀹氬悜銆傚洜姝わ紝浣犲彲浠ラ氳繃 Django 鏁版嵁搴 API 鏉ュ瓨鍙栭噸瀹氬悜瀵硅薄锛屼緥濡傦細
>>> from django.contrib.redirects.models import Redirect >>> from django.contrib.sites.models import Site >>> red = Redirect( ... site=Site.objects.get(id=1), ... old_path='/music/', ... new_path='/sections/arts/music/', ... ) >>> red.save() >>> Redirect.objects.get(old_path='/music/') <Redirect: /music/ ---> /sections/arts/music/>
The django.contrib.csrf package protects against Cross-Site Request Forgery (CSRF).
django.contrib.csrf 寮鍙戝寘鑳藉闃叉閬彈璺ㄧ珯璇锋眰浼犳敾鍑 (CSRF).
CSRF, also known as session riding, is a Web site security exploit. It happens when a malicious Web site tricks a user into unknowingly loading a URL from a site at which that user is already authenticated, hence taking advantage of the users authenticated status. This can be a bit tricky to understand at first, so we walk through two examples in this section.
CSRF, 鍙堝彨杩涚▼璺宠浆锛屾槸涓绉嶇綉绔欏畨鍏ㄦ敾鍑绘妧鏈傚綋鏌愪釜鎭舵剰缃戠珯鍦ㄧ敤鎴锋湭瀵熻鐨勬儏鍐典笅灏嗗叾浠庝竴涓凡缁忛氳繃韬唤楠岃瘉鐨勭珯鐐硅楠楄嚦涓涓柊鐨 URL 鏃讹紝杩欑鏀诲嚮灏卞彂鐢熶簡锛屽洜姝ゅ畠鍙互鍒╃敤鐢ㄦ埛宸茬粡閫氳繃韬唤楠岃瘉鐨勭姸鎬併傚紑濮嬬殑鏃跺欙紝瑕佺悊瑙h繖绉嶆敾鍑绘妧鏈瘮杈冨洶闅撅紝鍥犳鎴戜滑鍦ㄦ湰鑺傚皢浣跨敤涓や釜渚嬪瓙鏉ヨ鏄庛
Suppose youre logged in to a webmail account at example.com . This webmail site has a Log Out button that points to the URL example.com/logout that is, the only action you need to take in order to log out is to visit the page example.com/logout .
鍋囧畾浣犲凡缁忕櫥褰曞埌 example.com 鐨勭綉椤甸偖浠惰处鍙枫傝缃戦〉閭欢绔欑偣涓婃湁涓涓櫥鍑烘寜閽寚鍚戜簡 URL example.com/logout 锛屾崲鍙ヨ瘽璇达紝瑕佺櫥鍑虹殑璇濓紝闇瑕佸仛鐨勫敮涓鍔ㄤ綔灏辨槸璁块棶 URL 锛 example.com/logout 銆
A malicious site can coerce you to visit the URL example.com/logout by including that URL as a hidden <iframe> on its own (malicious) page. Thus, if youre logged in to the example.com webmail account and visit the malicious page that has an <iframe> to example.com/logout , the act of visiting the malicious page will log you out from example.com .
閫氳繃鍦紙鎭舵剰锛夌綉椤典笂鐢ㄩ殣钘忎竴涓寚鍚 URL example.com/logout 鐨 <iframe> ,鎭舵剰缃戠珯鍙互寮鸿揩浣犺闂 URL 銆傚洜姝わ紝濡傛灉浣犵櫥褰 example.com 鐨勭綉椤甸偖浠惰处鍙蜂箣鍚庯紝璁块棶浜嗗甫鏈夋寚鍚 example.com/logout 涔 <iframe> 鐨勬伓鎰忕珯鐐癸紝璁块棶璇ユ伓鎰忛〉闈㈢殑鍔ㄤ綔灏嗕娇浣犵櫥鍑 example.com 銆
Clearly, being logged out of a webmail site against your will is not a terrifying breach of security, but this same type of exploit can happen to any site that trusts users, such as an online banking site or an e-commerce site.
璇氱劧锛屽浣犺岃█鐧诲嚭涓涓綉椤甸偖浠剁珯鐐瑰苟涓嶄細鏋勬垚澶氬ぇ鐨勫畨鍏ㄧ牬鍧忥紝浣嗗悓鏍风殑鏀诲嚮鍙兘鍙戠敓鍦 浠讳綍 淇′换鐢ㄦ埛鐨勭珯鐐逛箣涓婏紝姣斿鍦ㄧ嚎閾惰缃戠珯鎴栬呯數瀛愬晢鍔$綉绔欍
In the previous example, example.com was partially at fault because it allowed a state change (i.e., logging the user out) to be requested via the HTTP GET method. Its much better practice to require an HTTP POST for any request that changes state on the server. But even Web sites that require POST for state-changing actions are vulnerable to CSRF.
鍦ㄤ笂涓涓緥瀛愪腑锛 example.com 搴旇璐熼儴鍒嗚矗浠伙紝鍥犱负瀹冨厑璁搁氳繃 HTTP GET 鏂规硶杩涜鐘舵佸彉鏇达紙鍗崇櫥鍏ュ拰鐧诲嚭锛夈傚鏋滃鏈嶅姟鍣ㄧ殑鐘舵佸彉鏇磋姹備娇鐢 HTTP POST 鏂规硶锛屾儏鍐靛氨濂藉緱澶氫簡銆備絾鏄紝鍗充究鏄己鍒惰姹備娇鐢 POST 鏂规硶杩涜鐘舵佸彉鏇存搷浣滀篃鏄撳彈鍒 CSRF 鏀诲嚮銆
Suppose example.com has upgraded its Log Out functionality so that its a <form> button that is requested via POST to the URL example.com/logout . Furthermore, the logout <form> includes this hidden field:
鍋囪 example.com 瀵圭櫥鍑哄姛鑳借繘琛屼簡鍗囩骇锛岀櫥鍑 <form> 鎸夐挳鏄氳繃涓涓寚鍚 URL example.com/logout 鐨 POST 鍔ㄤ綔瀹屾垚锛屽悓鏃跺湪 <form> 涓姞鍏ヤ簡浠ヤ笅闅愯棌鐨勫瓧娈碉細
<input type="hidden" name="confirm" value="true" />
This ensures that a simple POST to the URL example.com/logout wont log a user out; in order for a user to log out, the user must request example.com/logout via POST and send the confirm POST variable with a value of 'true' .
杩欏氨纭繚浜嗙敤绠鍗曠殑 POST 鍒 example.com/logout 涓嶄細璁╃敤鎴风櫥鍑猴紱瑕佽鐢ㄦ埛鐧诲嚭锛岀敤鎴峰繀椤婚氳繃 POST 鍚 example.com/logout 鍙戦佽姹 骞朵笖 鍙戦佷竴涓间负 'true' 鐨 POST 鍙橀噺銆
Well, despite the extra security, this arrangement can still be exploited by CSRF the malicious page just needs to do a little more work. Attackers can create an entire form targeting your site, hide it in an invisible <iframe> , and then use JavaScript to submit that form automatically.
灏界澧炲姞浜嗛澶栫殑瀹夊叏鏈哄埗锛岃繖绉嶈璁′粛鐒朵細閬埌 CSRF 鐨勬敾鍑烩斺旀伓鎰忛〉闈粎闇涓鐐圭偣鏀硅繘鑰屽凡銆傛敾鍑昏呭彲浠ラ拡瀵逛綘鐨勭珯鐐硅璁℃暣涓〃鍗曪紝骞跺皢鍏惰棌韬簬涓涓笉鍙鐨 <iframe> 涓紝鐒跺悗浣跨敤 Javascript 鑷姩鎻愪氦璇ヨ〃鍗曘
How, then, can your site protect itself from this exploit? The first step is to make sure all GET requests are free of side effects. That way, if a malicious site includes one of your pages as an <iframe> , it wont have a negative effect.
閭d箞锛屾槸鍚﹀彲浠ヨ绔欑偣鍏嶅彈杩欑鏀诲嚮鍛紵绗竴姝ワ紝棣栧厛纭繚鎵鏈 GET 鏂规硶娌℃湁鍓綔鐢ㄣ傝繖鏍蜂互鏉ワ紝濡傛灉鏌愪釜鎭舵剰绔欑偣灏嗕綘鐨勯〉闈㈠寘鍚负 <iframe> 锛屽畠灏嗕笉浼氫骇鐢熻礋闈㈡晥鏋溿
That leaves POST requests. The second step is to give each POST <form> a hidden field whose value is secret and is generated from the users session ID. Then, when processing the form on the server side, check for that secret field and raise an error if it doesnt validate.
璇ユ妧鏈病鏈夎冭檻 POST 璇锋眰銆傜浜屾灏辨槸缁欐墍鏈 POST 鐨 <form> 涓涓 闅愯棌瀛楁锛屽畠鐨勫兼槸淇濆瘑鐨勫苟鏍规嵁鐢ㄦ埛杩涚▼鐨 ID 鐢熸垚銆傝繖鏍凤紝浠庢湇鍔″櫒绔闂〃鍗曟椂锛屽彲浠ユ鏌ヨ淇濆瘑鐨勫瓧娈碉紝涓嶅惢鍚堟椂鍙互寮曞彂涓涓敊璇
This is exactly what Djangos CSRF prevention layer does, as explained in the sections that follow.
杩欐鏄 Django CSRF 闃叉姢灞傚畬鎴愮殑宸ヤ綔锛屾濡備笅闈㈢殑灏忚妭鎵浠嬬粛鐨勩
The django.contrib.csrf package contains only one module: middleware.py . This module contains a Django middleware class, CsrfMiddleware , which implements the CSRF protection.
django.contrib.csrf 寮鍙戝寘鍙湁涓涓ā鍧楋細 middleware.py 銆傝妯″潡鍖呭惈浜嗕竴涓 Django 涓棿浠剁被鈥斺 CsrfMiddleware 锛岃绫诲疄鐜颁簡 CSRF 闃叉姢鍔熻兘銆
To activate this CSRF protection, add 'django.contrib.csrf.middleware.CsrfMiddleware' to the MIDDLEWARE_CLASSES setting in your settings file. This middleware needs to process the response after SessionMiddleware , so CsrfMiddleware must appear before SessionMiddleware in the list (because the response middleware is processed last-to-first). Also, it must process the response before the response gets compressed or otherwise mangled, so CsrfMiddleware must come after GZipMiddleware . Once youve added that to your MIDDLEWARE_CLASSES setting, youre done. See the section Order of MIDDLEWARE_CLASSES in Chapter 13 for more explanation.
鍦ㄨ缃枃浠朵腑灏 'django.contrib.csrf.middleware.CsrfMiddleware' 娣诲姞鍒 MIDDLEWARE_CLASSES 璁剧疆涓彲婵娲 CSRF 闃叉姢銆傝涓棿浠跺繀椤诲湪 SessionMiddleware 涔嬪悗 鎵ц锛屽洜姝ゅ湪鍒楄〃涓 CsrfMiddleware 蹇呴』鍑虹幇鍦 SessionMiddleware 涔嬪墠 锛堝洜涓哄搷搴斾腑闂翠欢鏄嚜鍚庡悜鍓嶆墽琛岀殑锛夈傚悓鏃讹紝瀹冧篃蹇呴』鍦ㄥ搷搴旇鍘嬬缉鎴栬В鍘嬩箣鍓嶅鍝嶅簲缁撴灉杩涜澶勭悊锛屽洜姝 CsrfMiddleware 蹇呴』鍦 GZipMiddleware 涔嬪悗鎵ц銆備竴鏃﹀皢瀹冩坊鍔犲埌 MIDDLEWARE_CLASSES 璁剧疆涓紝浣犲氨瀹屾垚浜嗗伐浣溿傚弬闃呯 13 绔犱腑鐨勩奙IDDLEWARE_CLASSES 鐨勯『搴忋嬩竴鑺備簡瑙f洿澶氳癄閲娿
In case youre interested, heres how CsrfMiddleware works. It does these two things:
濡傛灉鎰熷叴瓒g殑璇濓紝涓嬮潰鏄 CsrfMiddleware 鐨勫伐浣滄ā寮忋傚畠瀹屾垚浠ヤ笅涓ら」宸ヤ綔锛
It modifies outgoing requests by adding a hidden form field to all POST forms, with the name csrfmiddlewaretoken and a value that is a hash of the session ID plus a secret key. The middleware does not modify the response if theres no session ID set, so the performance penalty is negligible for requests that dont use sessions.
瀹冧慨鏀瑰綋鍓嶅鐞嗙殑璇锋眰锛屽悜鎵鏈夌殑 POST 琛ㄥ崟澧炴坊涓涓殣钘忕殑琛ㄥ崟瀛楁锛屼娇鐢ㄥ悕绉版槸 csrfmiddlewaretoken 锛屽间负褰撳墠浼氳瘽 ID 鍔犱笂涓涓瘑閽ョ殑鏁e垪鍊笺傚鏋滄湭璁剧疆浼氳瘽 ID 锛岃涓棿浠跺皢 涓嶄細 淇敼鍝嶅簲缁撴灉锛屽洜姝ゅ浜庢湭浣跨敤浼氳瘽鐨勮姹傛潵璇存ц兘鎹熷け鏄彲浠ュ拷鐣ョ殑銆
On all incoming POST requests that have the session cookie set, it checks that csrfmiddlewaretoken is present and correct. If it isnt, the user will get a 403 HTTP error. The content of the 403 error page is the message Cross Site Request Forgery detected. Request aborted.
瀵逛簬鎵鏈夊惈浼氳瘽 cookie 闆嗗悎鐨勪紶鍏 POST 璇锋眰锛屽畠灏嗘鏌ユ槸鍚﹀瓨鍦 csrfmiddlewaretoken 鍙婂叾鏄惁姝g‘銆傚鏋滀笉鏄殑璇濓紝鐢ㄦ埛灏嗕細鏀跺埌涓涓 403 HTTP 閿欒銆403 閿欒椤甸潰鐨勫唴瀹规槸娑堟伅锛氭娴嬪埌璺ㄧ珯浼璇锋眰銆傝姹傝缁堟銆傗
This ensures that only forms originating from your Web site can be used to POST data back.
璇ユ楠ょ‘淇濆彧鏈夋簮鑷綘鐨勭珯鐐圭殑琛ㄥ崟鎵嶈兘灏嗘暟鎹 POST 鍥炴潵銆
This middleware deliberately targets only HTTP POST requests (and the corresponding POST forms). As we explained, GET requests ought never to have side effects; its your own responsibility to ensure this.
璇ヤ腑闂翠欢鐗规剰鍙拡瀵 HTTP POST 璇锋眰锛堜互鍙婂搴旂殑 POST 琛ㄥ崟锛夈傚鎴戜滑鎵瑙i噴鐨勶紝姘歌繙涓嶅簲璇ュ洜涓轰娇鐢ㄤ簡 GET 璇锋眰鑰屼骇鐢熻礋闈㈡晥搴旓紝浣犲繀椤昏嚜宸辨潵纭繚杩欎竴鐐广
POST requests not accompanied by a session cookie are not protected, but they dont need to be protected, because a malicious Web site could make these kind of requests anyway.
鏈娇鐢ㄤ細璇 cookie 鐨 POST 璇锋眰鏃犳硶鍙楀埌淇濇姢锛屼絾瀹冧滑涔熶笉 闇瑕 鍙楀埌淇濇姢锛屽洜涓烘伓鎰忕綉绔欏彲鐢ㄤ换鎰忔柟娉曟潵鍒堕犺繖绉嶈姹傘
To avoid altering non-HTML requests, the middleware checks the responses Content-Type header before modifying it. Only pages that are served as text/html or application/xml+xhtml are modified.
涓轰簡閬垮厤杞崲闈 HTML 璇锋眰锛屼腑闂翠欢鍦ㄧ紪杈戝搷搴旂粨鏋滀箣鍓嶅瀹冪殑 Content-Type 澶存爣杩涜妫鏌ャ傚彧鏈夋爣璁颁负 text/html 鎴 application/xml+xhtml 鐨勯〉闈㈡墠浼氳淇敼銆
CsrfMiddleware requires Djangos session framework to work. (See Chapter 12 for more on sessions.) If youre using a custom session or authentication framework that manually manages session cookies, this middleware will not help you.
CsrfMiddleware 鐨勮繍琛岄渶瑕 Django 鐨勪細璇濇鏋躲傦紙鍙傞槄绗 12 绔犱簡瑙f洿澶氬叧浜庝細璇濈殑鍐呭锛夊鏋滀綘浣跨敤浜嗚嚜瀹氫箟浼氳瘽鎴栬呰韩浠介獙璇佹鏋舵墜鍔ㄧ鐞嗕細璇 cookies锛岃涓棿浠跺皢甯笉涓婁綘鐨勫繖銆
If your application creates HTML pages and forms in some unusual way (e.g., if it sends fragments of HTML in JavaScript document.write statements), you might bypass the filter that adds the hidden field to the form. In this case, the form submission will always fail. (This happens because CsrfMiddleware uses a regular expression to add the csrfmiddlewaretoken field to your HTML before the page is sent to the client, and the regular expression sometimes cannot handle wacky HTML.) If you suspect this might be happening, just view the source in your Web browser to see whether csrfmiddlewaretoken was inserted into your <form> .
濡傛灉浣犵殑搴旂敤绋嬪簭浠ユ煇绉嶉潪甯歌鐨勬柟娉曞垱寤 HTML 椤甸潰锛堜緥濡傦細鍦 Javascript 鐨 document.write 璇彞涓彂閫 HTML 鐗囨锛夛紝浣犲彲鑳戒細缁曞紑浜嗗悜琛ㄥ崟娣诲姞闅愯棌瀛楁鐨勮繃婊ゅ櫒銆傚湪姝ゆ儏鍐典笅锛岃〃鍗曟彁浜ゆ案杩滄棤娉曟垚鍔熴傦紙杩欐槸鍥犱负鍦ㄩ〉闈㈣鍙戦佸埌瀹㈡埛绔箣鍓嶏紝 CsrfMiddleware 浣跨敤姝e垯琛ㄨ揪寮忓悜 HTML 涓坊鍔 csrfmiddlewaretoken 瀛楁锛岃屾湁鏃舵鍒欒〃杈惧紡鏃犳硶澶勭悊闈炲父瑙勭殑 HTML銆傦級濡傛灉浣犳鐤戝彂鐢熻繖绫讳簨鎯咃紝鍙渶鍦ㄦ祻瑙堝櫒涓煡鐪嬫簮鐮佺殑琛ㄥ崟涓槸鍚﹀凡缁忔彃鍏ヤ簡 csrfmiddlewaretoken 銆
For more CSRF information and examples, visit http://en.wikipedia.org/wiki/CSRF.
鎯充簡瑙f洿澶氬叧浜 CSRF 鐨勪俊鎭拰渚嬪瓙鐨勮瘽锛屽彲浠ヨ闂 http://en.wikipedia.org/wiki/CSRF 銆
This application holds a set of Django template filters useful for adding a human touch to data. To activate these filters, add 'django.contrib.humanize' to your INSTALLED_APPS setting. Once youve done that, use {% load humanize %} in a template, and youll have access to the filters described in the following sections.
璇ュ簲鐢ㄧ▼搴忓寘鎷竴绯诲垪 Django 妯℃澘杩囨护鍣紝鐢ㄤ簬澧炲姞鏁版嵁鐨勪汉鎬у寲銆傝婵娲昏繖浜涜繃婊ゅ櫒锛屼粎闇灏 'django.contrib.humanize' 鍔犲叆鍒 INSTALLED_APPS 璁剧疆涓備竴鏃﹀畬鎴愯椤瑰伐浣滐紝鍦ㄦā鏉夸腑浣跨敤 {% load humanize %} 灏辫兘璁块棶鍚庣画灏忚妭涓杩扮殑杩囨护鍣ㄤ簡銆
For numbers 1 through 9, this filter returns the number spelled out. Otherwise, it returns the numeral. This follows Associated Press style.
瀵逛簬 1 鍒 9 鐨勬暟瀛楋紝璇ヨ繃婊ゅ櫒杩斿洖浜嗘暟瀛楃殑鎷煎啓褰㈠紡銆傚惁鍒欙紝瀹冨皢杩斿洖鏁板瓧銆傝繖閬靛惊鐨勬槸缇庤仈绀鹃鏍笺
Examples:
涓句緥锛
1 becomes one.
1 鍙樻垚 one 銆
2 becomes two.
2 鍙樻垚 two 銆
10 becomes 10.
10 鍙樻垚 10 銆
You can pass in either an integer or a string representation of an integer.
浣犲彲浠ヤ紶鍏ヤ竴涓暣鏁版垨鑰呰〃绀烘暣鏁扮殑瀛楃涓层
This filter converts an integer to a string containing commas every three digits.
璇ヨ繃婊ゅ櫒灏嗘暣鏁拌浆鎹负姣忎笁涓暟瀛楃敤涓涓楀彿鍒嗛殧鐨勫瓧绗︿覆銆
Examples:
渚嬪锛
4500 becomes 4,500.
4500 鍙樻垚 4,500 銆
45000 becomes 45,000.
45000 鍙樻垚 45,000 銆
450000 becomes 450,000.
450000 鍙樻垚 450,000 銆
4500000 becomes 4,500,000.
4500000 鍙樻垚 4,500,000 銆
You can pass in either an integer or a string representation of an integer.
浣犲彲浠ヤ紶鍏ユ暣鏁版垨鑰呰〃绀烘暣鏁扮殑瀛楃涓层
This filter converts a large integer to a friendly text representation. It works best for numbers over 1 million.
璇ヨ繃婊ゅ櫒灏嗕竴涓緢澶х殑鏁存暟杞崲鎴愬弸濂界殑鏂囨湰琛ㄧず鏂瑰紡銆傚畠瀵逛簬瓒呰繃涓鐧句竾鐨勬暟瀛楁渶濂界敤銆
Examples:
渚嬪锛
1000000 becomes 1.0 million.
1000000 鍙樻垚 1.0 million 銆
1200000 becomes 1.2 million.
1200000 鍙樻垚 1.2 million 銆
1200000000 becomes 1.2 billion.
1200000000 鍙樻垚 1.2 billion 銆
Values up to 1 quadrillion (1,000,000,000,000,000) are supported.
鏈澶ф敮鎸佷笉瓒呰繃涓鍗冪殑浜旀鏂癸紙1,000,000,000,000,000锛夈
You can pass in either an integer or a string representation of an integer.
浣犲彲浠ヤ紶鍏ユ暣鏁版垨鑰呰〃绀烘暣鏁扮殑瀛楃涓层
This filter converts an integer to its ordinal as a string.
璇ヨ繃婊ゅ櫒灏嗘暣鏁拌浆鎹负搴忔暟璇嶇殑瀛楃涓插舰寮忋
Examples:
渚嬪锛
1 becomes 1st.
1 鍙樻垚 1st 銆
2 becomes 2nd.
2 鍙樻垚 2nd 銆
3 becomes 3rd.
3 鍙樻垚 3rd 銆
You can pass in either an integer or a string representation of an integer.
浣犲彲浠ヤ紶鍏ユ暣鏁版垨鐫琛ㄧず鏁存暟鐨勫瓧绗︿覆銆
The following collection of template filters implements common markup languages:
涓嬪垪妯℃澘杩囨护鍣ㄩ泦鍚堝疄鐜颁簡甯歌鐨勬爣璁拌瑷锛
textile : Implements Textile (http://en.wikipedia.org/wiki/Textile_%28markup_language%29)
textile : 瀹炵幇浜 Textile (http://en.wikipedia.org/wiki/Textile_%28markup_language%29)
markdown : Implements Markdown (http://en.wikipedia.org/wiki/Markdown)
markdown : 瀹炵幇浜 Markdown (http://en.wikipedia.org/wiki/Markdown)
restructuredtext : Implements ReStructured Text (http://en.wikipedia.org/wiki/ReStructuredText)
restructuredtext : 瀹炵幇浜 ReStructured Text (http://en.wikipedia.org/wiki/ReStructuredText)
In each case, the filter expects formatted markup as a string and returns a string representing the marked-up text. For example, the textile filter converts text that is marked up in Textile format to HTML:
姣忕鎯呭舰涓嬶紝杩囨护鍣ㄩ兘鏈熸湜瀛楃涓插舰寮忕殑鏍煎紡鍖栨爣璁帮紝骞惰繑鍥炶〃绀烘爣璁版枃鏈殑瀛楃涓层備緥濡傦細 textile 杩囨护鍣ㄦ妸浠 Textile 鏍煎紡鏍囪鐨勬枃鏈浆鎹负 HTML 銆
{% load markup %} {{ object.content|textile }}
To activate these filters, add 'django.contrib.markup' to your INSTALLED_APPS setting. Once youve done that, use {% load markup %} in a template, and youll have access to these filters. For more documentation, read the source code in django/contrib/markup/templatetags/markup.py.
瑕佹縺娲昏繖浜涜繃婊ゅ櫒锛屼粎闇灏 'django.contrib.markup' 娣诲姞鍒 INSTALLED_APPS 璁剧疆涓備竴鏃﹀畬鎴愪簡璇ラ」宸ヤ綔锛屽湪妯℃澘涓娇鐢 {% load markup %} 灏辫兘浣跨敤杩欎簺杩囨护鍣ㄣ傝鎯虫帉鎻℃洿澶氫俊鎭殑璇濓紝鍙槄璇 django/contrib/markup/templatetags/markup.py. 鍐呯殑婧愪唬鐮併
Many of these contributed frameworks (CSRF, the auth system, etc.) do their magic by providing a piece of middleware . Middleware is essentially code that runs before and/or after every single request and can modify each request and response at will. Next, well discuss Djangos built-in middleware and explain how you can write your own.
杩欎簺缁ф壙妗嗘灦锛圕SRF銆佽韩浠介獙璇佺郴缁熺瓑绛夛級閫氳繃鎻愪緵 涓棿浠 鏉ュ疄鐜板叾濂囧鐨勫姛鑳姐傛湰璐ㄤ笂锛屼腑闂翠欢灏辨槸鍦ㄦ瘡涓姹備箣鍓嶆垨/鍜屼箣鍚庤繍琛岀殑浠g爜锛屽畠浠彲闅忔剰淇敼姣忎釜璇锋眰鎴栧搷搴斻傛帴涓嬫潵锛屾垜浠皢璁ㄨ Django 鐨勫唴寤轰腑闂翠欢锛屽苟瑙i噴濡備綍缂栧啓鑷繁鐨勪腑闂翠欢銆
鍏充簬鏈瘎娉ㄧ郴缁
鏈珯浣跨敤涓婁笅鏂囧叧鑱旂殑璇勬敞绯荤粺鏉ユ敹闆嗗弽棣堜俊鎭備笉鍚屼簬涓鑸鏁寸珷鍋氳瘎娉ㄧ殑鍋氭硶锛 鎴戜滑鍏佽浣犲姣忎竴涓嫭绔嬬殑鈥滄枃鏈潡鈥濆仛璇勬敞銆備竴涓滄枃鏈潡鈥濈湅璧锋潵鏄繖鏍风殑锛
涓涓滄枃鏈潡鈥濇槸涓涓钀斤紝涓涓垪琛ㄩ」锛屼竴娈典唬鐮侊紝鎴栬呭叾浠栦竴灏忔鍐呭銆 浣犻変腑瀹冧細楂樹寒搴︽樉绀:
瑕佸鏂囨湰鍧楀仛璇勬敞锛屼綘鍙渶瑕佺偣鍑诲畠鏃佽竟鐨勬爣璇嗗潡:
鎴戜滑浼氫粩缁嗛槄璇绘瘡涓瘎璁猴紝濡傛灉鍙兘鐨勮瘽鎴戜滑涔熶細鎶婅瘎娉ㄨ冭檻鍒版湭鏉ョ殑鐗堟湰涓幓:
濡傛灉浣犳効鎰忎綘鐨勮瘎娉ㄨ閲囩敤锛岃纭繚鐣欎笅浣犵殑鍏ㄥ悕 (娉ㄦ剰涓嶆槸鏄电О鎴栫畝绉帮級
Many, many thanks to Jack Slocum; the inspiration and much of the code for the comment system comes from Jack's blog, and this site couldn't have been built without his wonderful
YAHOO.ext
library. Thanks also to Yahoo for YUI itself.