In the previous chapter, we explained how to set up a Django project and run the Django development server. Of course, that site doesnt actually do anything useful yetall it does is display the It worked! message. Lets change that. This chapter introduces how to create dynamic Web pages with Django.
鍓嶄竴绔犱腑锛屾垜浠В閲婁簡濡備綍寤虹珛涓涓 Django 椤圭洰骞跺惎鍔 Django 寮鍙戞湇鍔″櫒銆傚綋鐒讹紝閭d釜缃戠珯瀹為檯骞舵病鏈夊共浠涔堟湁鐢ㄧ殑浜嬫儏锛屽畠鎵鍋氱殑鍙槸鏄剧ず It worked! 娑堟伅銆傝鎴戜滑鏉ュ仛浜涙敼鍙樸傛湰绔犲皢浠嬬粛濡備綍浣跨敤 Django 鍒涘缓鍔ㄦ佺綉椤点
As our first goal, lets create a Web page that displays the current date and time. This is a good example of a dynamic Web page, because the contents of the page are not staticrather, the contents change according to the result of a computation (in this case, a calculation of the current time). This simple example doesnt involve a database or any sort of user inputjust the output of your servers internal clock.
鎴戜滑鐨勭涓涓洰鏍囨槸鍒涘缓涓涓樉绀哄綋鍓嶆棩鏈熷拰鏃堕棿鐨勭綉椤点傝繖鏄竴涓笉閿欑殑 鍔ㄦ 缃戦〉鑼冧緥锛屽洜涓鸿椤甸潰鐨勫唴瀹逛笉鏄潤鎬佺殑銆傜浉鍙嶏紝鍏跺唴瀹规槸闅忕潃璁$畻(鏈緥涓槸瀵瑰綋鍓嶆椂闂寸殑璁$畻)鐨勭粨鏋滆屽彉鍖栫殑銆傝繖涓畝鍗曠殑鑼冧緥鏃笉娑夊強鏁版嵁搴擄紝涔熶笉闇瑕佷换浣曠敤鎴疯緭鍏ワ紝浠呰緭鍑烘湇鍔″櫒鐨勫唴閮ㄦ椂閽熴
To create this page, well write a view function . A view function, or view for short, is simply a Python function that takes a Web request and returns a Web response. This response can be the HTML contents of a Web page, or a redirect, or a 404 error, or an XML document, or an image or anything, really. The view itself contains whatever arbitrary logic is necessary to return that response. This code can live anywhere you want, as long as its on your Python path. Theres no other requirementno magic, so to speak. For the sake of putting the code somewhere , lets create a file called views.py in the mysite directory, which you created in the previous chapter.
鎴戜滑灏嗙紪鍐欎竴涓 瑙嗗浘鍑芥暟 浠ュ垱寤鸿椤甸潰銆傛墍璋撶殑瑙嗗浘鍑芥暟锛堟垨 瑙嗗浘 锛夛紝鍙笉杩囨槸涓涓帴鍙 Web 璇锋眰骞惰繑鍥 Web 鍝嶅簲鐨 Python 鍑芥暟銆傚疄闄呬笂锛岃鍝嶅簲鍙互鏄竴浠界綉椤电殑 HTML 鍐呭銆佷竴娆¢噸瀹氬悜銆佷竴鏉 404 閿欒銆佷竴浠 XML 鏂囨。銆佷竴骞呭浘鐗囷紝鎴栧叾瀹冧换浣曚笢瑗裤傝鍥炬湰韬寘鍚繑鍥炶鍝嶅簲鎵闇鐨勪换鎰忛昏緫銆傝娈典唬鐮佸彲浠ラ殢鎰忔斁缃紝鍙鍦 Python 鐨勮矾寰勮缃腑灏卞彲浠ヤ簡銆傛病鏈夊叾瀹冭姹傗斺斾篃鍙互璇存槸娌℃湁浠讳綍濂囩壒涔嬪銆備负浜嗙粰杩欎簺浠g爜涓涓 瀛樿韩涔嬪 锛岃鎴戜滑鍦ㄤ笂涓绔犳墍鍒涘缓鐨 mysite 鐩綍涓柊寤轰竴浠藉悕涓 views.py 鐨勬枃浠躲
Heres a view that returns the current date and time, as an HTML document:
浠ヤ笅鏄竴涓互 HTML 鏂瑰紡杩斿洖褰撳墠鐨勬棩鏈熶笌鏃堕棿鐨勮鍥 (view)锛岋細
from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
Lets step through this code one line at a time:
鎴戜滑閫愯閫愬彞鍦板垎鏋愪竴閬嶈繖娈典唬鐮侊細
First, we import the class HttpResponse , which lives in the django.http module. See Appendix H for further details on the HttpRequest and HttpResponse objects.
棣栧厛锛屾垜浠粠 django.http 妯″潡瀵煎叆锛坕mport锛 HttpResponse 绫汇傚弬闃呴檮褰 H 浜嗚В鏇村鍏充簬 HttpRequest 鍜 HttpResponse 鐨勭粏鑺傘
Then we import the datetime module from Pythons standard library, the set of useful modules that comes with Python. The datetime module contains several functions and classes for dealing with dates and times, including a function that returns the current time.
鐒跺悗鎴戜滑浠 Python 鏍囧噯搴(Python 鑷甫鐨勫疄鐢ㄦā鍧楅泦鍚)涓鍏ワ紙import) datetime 妯″潡銆 datetime 妯″潡鍖呭惈鍑犱釜澶勭悊鏃ユ湡鍜屾椂闂寸殑鍑芥暟锛坒unctions锛夊拰绫(classes)锛屽叾涓氨鍖呮嫭杩斿洖褰撳墠鏃堕棿鐨勫嚱鏁般
Next, we define a function called current_datetime . This is the view function. Each view function takes an HttpRequest object as its first parameter, which is typically named request .
鎺ヤ笅鏉ワ紝鎴戜滑瀹氫箟浜嗕竴涓彨鍋 current_datetime 鐨勫嚱鏁般傝繖灏辨槸鎵璋撶殑瑙嗗浘鍑芥暟锛坴iew function锛夈傛瘡涓鍥惧嚱鏁伴兘浠ヤ竴涓 HttpRequest 瀵硅薄涓虹涓涓弬鏁帮紝璇ュ弬鏁伴氬父鍛藉悕涓 request 銆
Note that the name of the view function doesnt matter; it doesnt have to be named in a certain way in order for Django to recognize it. Were calling it current_datetime here, because that name clearly indicates what it does, but it could just as well be named super_duper_awesome_current_time , or something equally revolting. Django doesnt care. The next section explains how Django finds this function.
娉ㄦ剰瑙嗗浘鍑芥暟鐨勫悕绉板苟涓嶉噸瑕侊紱骞朵笉涓瀹氶潪寰椾互鏌愮鐗瑰畾鐨勬柟寮忓懡鍚嶆墠鑳借 Django 璇嗗埆瀹冦傛澶勶紝鎴戜滑绉颁箣涓 current_datetime 锛屽彧鏄洜涓鸿鍚嶅瓧鏄庣‘鍦版寚鍑轰簡瀹冪殑鍔熻兘锛岃屽畠涔熷彲浠ヨ鍛藉悕涓 super_duper_awesome_current_time 鎴栬呭叾瀹冨悓鏍疯帿鍚嶅叾濡欑殑鍚嶅瓧銆侱jango 骞朵笉鍏冲績鍏跺悕瀛椼備笅涓鑺傚皢瑙i噴 Django 濡備綍鏌ユ壘璇ュ嚱鏁般
The first line of code within the function calculates the current date/time, as a datetime.datetime object, and stores that as the local variable now .
鍑芥暟涓殑绗竴琛屼唬鐮佽绠楀綋鍓嶆棩鏈熷拰鏃堕棿锛屽苟浠 datetime.datetime 瀵硅薄鐨勫舰寮忎繚瀛樹负灞閮ㄥ彉閲 now 銆
The second line of code within the function constructs an HTML response using Pythons format-string capability. The %s within the string is a placeholder, and the percent sign after the string means Replace the %s with the value of the variable now . (Yes, the HTML is invalid, but were trying to keep the example simple and short.)
鍑芥暟鐨勭浜岃浠g爜鐢 Python 鐨勬牸寮忓寲瀛楃涓诧紙format-string锛夊姛鑳芥瀯閫犱簡涓娈 HTML 鍝嶅簲銆傚瓧绗︿覆閲岄潰鐨 %s 鏄崰浣嶇锛屽瓧绗︿覆涔嬪悗鐨勭櫨鍒嗗彿琛ㄧず浣跨敤鍙橀噺 now 鐨勫兼浛鎹 %s 銆(鏄殑锛岃繖娈 HTML 涓嶅悎娉曪紝浣嗘垜浠彧涓嶈繃鏄兂璁╄寖渚嬪敖閲忎繚鎸佺畝鐭屽凡銆傦級
Finally, the view returns an HttpResponse object that contains the generated response. Each view function is responsible for returning an HttpResponse object. (There are exceptions, but well get to those later.)
鏈鍚庯紝璇ヨ鍥捐繑鍥炰竴涓寘鍚墍鐢熸垚鍝嶅簲鐨 HttpResponse 瀵硅薄銆傛瘡涓鍥惧嚱鏁伴兘璐熻矗杩斿洖涓涓 HttpResponse 瀵硅薄銆傦紙涔熸湁渚嬪锛屼絾鏄垜浠◢鍚庢墠浼氭帴瑙﹀埌銆傦級
Djangos Time Zone
Django 鏃跺尯 (Time Zone)
Django includes a TIME_ZONE setting that defaults to America/Chicago . This probably isnt where you live, so you might want to change it in your settings.py . See Appendix E for details.
Django 鍖呭惈涓涓粯璁や负 America/Chicago 鐨 TIME_ZONE 璁剧疆銆傝繖鍙兘涓嶆槸浣犳墍灞呬綇鐨勬椂鍖猴紝鍥犳浣犲彲浠ュ湪 settings.py 鏂囦欢涓慨鏀瑰畠銆傝鍙傞槄闄勫綍 E 浜嗚В鏇村缁嗚妭銆
So, to recap, this view function returns an HTML page that includes the current date and time. But how do we tell Django to use this code? Thats where URLconfs come in.
閭d箞姒傛嫭璧锋潵锛岃瑙嗗浘鍑芥暟杩斿洖浜嗗寘鍚綋鍓嶆棩鏈熷拰鏃堕棿鐨勪竴娈 HTML 椤甸潰銆備絾鏄浣曞憡璇 Django 浣跨敤杩欐浠g爜鍛紵杩欏氨鏄 URLconfs 绮夊ⅷ鐧诲満鐨勫湴鏂逛簡銆
A URLconf is like a table of contents for your Django-powered Web site. Basically, its a mapping between URL patterns and the view functions that should be called for those URL patterns. Its how you tell Django, For this URL, call this code, and for that URL, call that code. Remember that the view functions need to be on the Python path.
URLconf 灏卞儚鏄 Django 鎵鏀拺缃戠珯鐨勭洰褰曘傚畠鐨勬湰璐ㄦ槸 URL 妯″紡浠ュ強瑕佷负璇 URL 妯″紡璋冪敤鐨勮鍥惧嚱鏁颁箣闂寸殑鏄犲皠琛ㄣ備綘灏辨槸浠ヨ繖绉嶆柟寮忓憡璇 Django锛屽浜庤繖涓 URL 璋冪敤杩欐浠g爜锛屽浜庨偅涓 URL 璋冪敤閭f浠g爜銆備絾蹇呴』璁颁綇鐨勬槸瑙嗗浘鍑芥暟蹇呴』浣嶄簬 Python 鎼滅储璺緞涔嬩腑銆
Your Python Path
Python 鎼滅储璺緞
Your Python path is the list of directories on your system where Python looks when you use the Python import statement.
Python 鎼滅储璺緞 灏辨槸浣跨敤 import 璇彞鏃讹紝Python 鎵鏌ユ壘鐨勭郴缁熺洰褰曟竻鍗曘
For example, lets say your Python path is set to ['', '/usr/lib/python2.4/site-packages', '/home/username/djcode/'] . If you execute the Python code from foo import bar , Python will first check for a module called foo.py in the current directory. (The first entry in the Python path, an empty string, means the current directory.) If that file doesnt exist, Python will look for the file /usr/lib/python2.4/site-packages/foo.py . If that file doesnt exist, it will try /home/username/djcode/foo.py . Finally, if that file doesnt exist, it will raise ImportError .
涓句緥鏉ヨ锛屽亣瀹氫綘灏 Python 璺緞璁剧疆涓 ['','/usr/lib/python2.4/site-packages','/home/username/djcode/'] 銆傚鏋滄墽琛屼唬鐮 from foo import bar 锛孭ython 灏嗕細棣栧厛鍦ㄥ綋鍓嶇洰褰曟煡鎵 foo.py 妯″潡( Python 璺緞绗竴椤圭殑绌哄瓧绗︿覆琛ㄧず褰撳墠鐩綍)銆傚鏋滄枃浠朵笉瀛樺湪锛孭ython灏嗘煡鎵 /usr/lib/python2.4/site-packages/foo.py 鏂囦欢銆傚鏋滄枃浠朵篃涓嶅瓨鍦紝瀹冨皢灏濊瘯 /home/username/djcode/foo.py 銆傛渶鍚庯紝濡傛灉 杩欎釜 鏂囦欢杩樹笉瀛樺湪锛屽畠灏嗗紩鍙 ImportError 寮傚父銆
If youre interested in seeing the value of your Python path, start the Python interactive interpreter and type import sys , followed by print sys.path .
濡傛灉瀵逛簡瑙 Python 鎼滅储璺緞鍊兼劅鍏磋叮锛屽彲浠ュ惎鍔 Python 浜や簰寮忚В閲婄▼搴忥紝杈撳叆 import sys 锛屾帴鐫杈撳叆 print sys.path 銆
Generally you dont have to worry about setting your Python pathPython and Django will take care of things for you automatically behind the scenes. (If youre curious, setting the Python path is one of the things that the manage.py file does.)
閫氬父锛屼綘涓嶅繀鍏冲績 Python 鎼滅储璺緞鐨勮缃侾ython 鍜 Django 浼氬湪鍚庡彴鑷姩甯綘澶勭悊濂姐(濡傛灉鏈夊叴瓒d簡瑙g殑璇濓紝Python 鎼滅储璺緞鐨勮缃伐浣滄槸 manage.py 鏂囦欢鐨勮亴鑳戒箣涓銆)
When you executed django-admin.py startproject in the previous chapter, the script created a URLconf for you automatically: the file urls.py . Lets edit that file. By default, it looks something like this:
鍓嶄竴绔犱腑鎵ц django-admin.py startproject 鏃讹紝璇ヨ剼鏈細鑷姩涓轰綘寤轰簡涓浠 URLconf锛堝嵆 urls.py 鏂囦欢锛夈傝鎴戜滑缂栬緫涓涓嬭繖浠芥枃浠躲傜己鐪佹儏鍐典笅瀹冩槸涓嬮潰杩欎釜鏍峰瓙锛
from django.conf.urls.defaults import * urlpatterns = patterns('', # Example: # (r'^mysite/', include('mysite.apps.foo.urls.foo')), # Uncomment this for admin: # (r'^admin/', include('django.contrib.admin.urls')), )
Lets step through this code one line at a time:
璁╂垜浠愯閫愬彞鍒嗘瀽涓閬嶈繖娈典唬鐮侊細
The first line imports all objects from the django.conf.urls.defaults module, including a function called patterns .
绗竴琛屼粠 django.conf.urls.defaults 妯″潡寮曞叆浜嗘墍鏈夌殑瀵硅薄锛屽叾涓寘鎷簡鍙仛 patterns 鐨勫嚱鏁般
The second line calls the function patterns() and saves the result into a variable called urlpatterns . The patterns() function gets passed only a single argumentthe empty string. The rest of the lines are commented out. (The string can be used to supply a common prefix for view functions, but well skip this advanced usage for now.)
绗簩琛岃皟鐢 patterns() 鍑芥暟骞跺皢杩斿洖缁撴灉淇濆瓨鍒 urlpatterns 鍙橀噺銆 patterns() 鍑芥暟鍙紶鍏ヤ簡涓涓┖瀛楃涓插弬鏁般傚叾浠栦唬鐮佽閮借娉ㄩ噴鎺変簡銆 (璇ュ瓧绗︿覆鍙敤浣滆鍥惧嚱鏁扮殑閫氱敤鍓嶇紑锛屼絾鐩墠鎴戜滑灏嗙暐杩囪繖绉嶉珮绾х敤娉曘傦級
The main thing to note here is the variable urlpatterns , which Django expects to find in your ROOT_URLCONF module. This variable defines the mapping between URLs and the code that handles those URLs.
褰撳墠搴旇娉ㄦ剰鏄 urlpatterns 鍙橀噺锛 Django 鏈熸湜鑳戒粠 ROOT_URLCONF 妯″潡涓壘鍒板畠銆傝鍙橀噺瀹氫箟浜 URL 浠ュ強鐢ㄤ簬澶勭悊杩欎簺 URL 鐨勪唬鐮佷箣闂寸殑鏄犲皠鍏崇郴銆
By default, everything in the URLconf is commented outyour Django application is a blank slate. (As a side note, thats how Django knew to show you the It worked! page in the last chapter. If your URLconf is empty, Django assumes you just started a new project and, hence, displays that message.)
榛樿鎯呭喌涓嬶紝URLconf 鎵鏈夊唴瀹归兘琚敞閲婅捣鏉ヤ簡鈥斺擠jango 搴旂敤绋嬪簭杩樻槸鐧界増涓鍧椼傦紙鏃佹敞锛氳繖涔熷氨鏄笂涓绔犱腑 Django 鏄剧ず鈥淚t worked!鈥濋〉闈㈢殑鍘熷洜銆傚鏋 URLconf 涓虹┖锛孌jango 浼氳瀹氫綘鎵嶅垱寤哄ソ鏂伴」鐩紝鍥犳涔熷氨鏄剧ず閭g淇℃伅銆傦級
Lets edit this file to expose our current_datetime view:
鐜板湪缂栬緫璇ユ枃浠朵互灞曠ず鎴戜滑鐨 current_datetime 瑙嗗浘:
from django.conf.urls.defaults import * from mysite.views import current_datetime urlpatterns = patterns('', (r'^time/$', current_datetime), )
We made two changes here. First, we imported the current_datetime view from its module (mysite/views.py , which translates into mysite.views in Python import syntax). Next, we added the line (r'^time/$', current_datetime), . This line is referred to as a URLpattern its a Python tuple in which the first element is a simple regular expression and the second element is the view function to use for that pattern.
鎴戜滑鍋氫簡涓ゅ淇敼銆傞鍏堬紝鎴戜滑浠庢ā鍧 (鍦 Python 鐨 import 璇硶涓紝 mysite/views.py 杞瘧涓 mysite.views ) 涓紩鍏ヤ簡 current_datetime 瑙嗗浘銆傛帴鐫锛屾垜浠姞鍏ヤ簡 (r'^time/$', current_datetime), 杩欎竴琛屻傝琛屽氨鏄墍璋撶殑 URLpattern 锛屽畠鏄竴涓 Python 鍏冪粍,鍏剁涓涓厓绱犳槸绠鍗曠殑姝e垯琛ㄨ揪寮忥紝绗簩涓厓绱犳槸涓鸿妯″紡搴旂敤鐨勮鍥惧嚱鏁般
In a nutshell, we just told Django that any request to the URL /time/ should be handled by the current_datetime view function.
绠鍗曟潵璇达紝鎴戜滑鍙槸鍛婅瘔 Django锛屾墍鏈夋寚鍚 URL /time/ 鐨勮姹傞兘搴旂敱 current_datetime 杩欎釜瑙嗗浘鍑芥暟鏉ュ鐞嗐
A few things are worth pointing out:
涓嬮潰鏄竴浜涢渶瑕佹敞鎰忕殑鍦版柟锛
Note that, in this example, we passed the current_datetime view function as an object without calling the function. This is a key feature of Python (and other dynamic languages): functions are first-class objects, which means you can pass them around just like any other variables. Cool stuff, eh?
娉ㄦ剰锛岃渚嬩腑锛屾垜浠皢 current_datetime 瑙嗗浘鍑芥暟浣滀负瀵硅薄浼犻掞紝鑰屼笉鏄皟鐢ㄥ畠銆傝繖鏄 Python (鍙婂叾瀹冨姩鎬佽瑷鐨) 鐨勪竴涓噸瑕佺壒鎬э細鍑芥暟鏄竴绾у璞★紙first-class objects锛夛紝 涔熷氨鏄浣犲彲浠ュ儚浼犻掑叾瀹冨彉閲忎竴鏍蜂紶閫掑畠浠傚緢閰峰惂锛
The r in r'^time/$' means that '^time/$ is a Python raw string. This allows regular expressions to be written without overly verbose escaping.
r'^time/$' 涓殑 r 琛ㄧず '^time/$' 鏄竴涓師濮嬪瓧绗︿覆銆傝繖鏍蜂竴鏉ュ氨鍙互閬垮厤 姝e垯琛ㄨ揪寮忔湁杩囧鐨勮浆涔夊瓧绗︺
You should exclude the expected slash at the beginning of the '^time/$' expression in order to match /time/ . Django automatically puts a slash before every expression. At first glance, this may seem odd, but URLconfs can be included in other URLconfs, and leaving off the leading slash simplifies matters. This is further covered in Chapter 8.
涓嶅繀鍦 '^time/$' 鍓嶅姞鏂滄潬锛/锛夋潵鍖归厤 /time/ 锛 鍥犱负 Django 浼氳嚜鍔ㄥ湪姣忎釜琛 杈惧紡鍓嶆坊鍔犱竴涓枩鏉犮備箥鐪嬭捣鏉ワ紝杩欏ソ鍍忔湁鐐瑰鎬紝浣嗘槸 URLconfs 鍙兘鐢卞叾瀹冪殑 URLconfs 鎵寮曠敤, 鎵浠ヤ笉鍔犲墠闈㈢殑鏂滄潬鍙浜嬫儏绠鍗曚竴浜涖傝繖涓鐐瑰湪绗 8 绔犱腑灏嗘湁杩涗竴姝ラ槓杩般
The caret character (^ ) and dollar sign character ($ ) are important. The caret means require that the pattern matches the start of the string, and the dollar sign means require that the pattern matches the end of the string.
涓婄澶 ^ 鍜岀編鍏冪鍙 $ 绗﹀彿闈炲父閲嶈銆備笂绠ご瑕佹眰琛ㄨ揪寮忓瀛楃涓茬殑澶撮儴杩涜鍖归厤锛岀編鍏冪鍙峰垯瑕佹眰琛ㄨ揪寮忓瀛楃涓茬殑灏鹃儴杩涜鍖归厤銆
This concept is best explained by example. If we had instead used the pattern '^time/' (without a dollar sign at the end), then any URL that starts with time/ would match, such as /time/foo and /time/bar , not just /time/ . Similarly, if we had left off the initial caret character ('time/$' ), Django would match any URL that ends with time/ , such as /foo/bar/time/ . Thus, we use both the caret and dollar sign to ensure that only the URL /time/ matches. Nothing more, nothing less.
鏈濂借繕鏄敤鑼冧緥鏉ヨ鏄庝竴涓嬭繖涓蹇点傚鏋滄垜浠敤 '^time/' 锛堢粨灏炬病鏈$), 閭d箞浠 time/ 寮濮嬬殑 浠绘剰 URL 閮戒細鍖归厤锛屾瘮濡 /time/foo 鍜 /time/bar 锛 涓嶄粎浠呮槸 /time/ 銆傚悓鏍风殑锛屽鏋滄垜浠幓鎺夋渶鍓嶉潰鐨 ^ ( 'time/$' ), Django 涓鏍蜂細鍖归厤鐢 time/ 缁撴潫鐨 浠绘剰 URL /time/ 锛屾瘮濡 /foo/bar/time/ 銆 鍥犳锛屾垜浠繀椤诲悓鏃剁敤涓 ^ 鍜 $ 鏉ョ簿纭尮閰 URL /time/ 銆備笉鑳藉涔熶笉鑳藉皯銆
You may be wondering what happens if someone requests /time . This is handled as youd hope (via a redirect) as long as the APPEND_SLASH setting is True . (See Appendix E for some good bedtime reading on this topic.)
浣犲彲鑳芥兂濡傛灉鏈変汉璇锋眰 /time 涔熷彲浠ュ悓鏍峰鐞嗐傚鏋 APPEND_SLASH 鐨 璁剧疆鏄 True 鐨勮瘽锛岀郴缁熶細閲嶅畾鍚戝埌 /time/ 锛岃繖鏍峰氨鍙互涓鏍峰鐞嗕簡銆 (鏈夊叧鍐呭璇锋煡鐪嬮檮褰 E )
To test our changes to the URLconf, start the Django development server, as you did in Chapter 2, by running the command python manage.py runserver . (If you left it running, thats fine, too. The development server automatically detects changes to your Python code and reloads as necessary, so you dont have to restart the server between changes.) The server is running at the address http://127.0.0.1:8000/ , so open up a Web browser and go to http://127.0.0.1:8000/time/ . You should see the output of your Django view.
鍚姩Django寮鍙戞湇鍔″櫒鏉ユ祴璇曚慨鏀瑰ソ鐨 URLconf, 杩愯鍛戒护琛 python manage.py runserver 銆 (濡傛灉浣犺瀹冧竴鐩磋繍琛屼篃鍙互锛屽紑鍙戞湇鍔″櫒浼氳嚜鍔ㄧ洃娴嬩唬鐮佹敼鍔ㄥ苟鑷姩閲嶆柊杞藉叆锛屾墍浠ヤ笉闇瑕佹墜宸ラ噸鍚級 寮鍙戞湇鍔″櫒鐨勫湴鍧鏄 http://127.0.0.1:8000/ 锛屾墦寮浣犵殑娴忚鍣ㄨ闂 http://127.0.0.1:8000/time/ 銆 浣犲氨鍙互鐪嬪埌杈撳嚭缁撴灉浜嗐
Hooray! Youve made your first Django-powered Web page.
涓囧瞾锛佷綘宸茬粡鍒涘缓浜嗙涓涓狣jango鐨剋eb椤甸潰銆
Regular Expressions
姝e垯琛ㄨ揪寮
Regular expressions (or regexes ) are a compact way of specifying patterns in text. While Django URLconfs allow arbitrary regexes for powerful URL-matching capability, youll probably use only a few regex patterns in practice. Heres a small selection of common patterns:
姝e垯琛ㄨ揪寮 (鎴 regexes ) 鏄氱敤鐨勬枃鏈ā寮忓尮閰嶇殑鏂规硶銆侱jango URLconfs 鍏佽浣 浣跨敤浠绘剰鐨勬鍒欒〃杈惧紡鏉ュ仛寮烘湁鍔涚殑URL鏄犲皠锛屼笉杩囬氬父浣犲疄闄呬笂鍙兘鍙渶瑕佷娇鐢ㄥ緢灏戠殑涓 閮ㄥ垎鍔熻兘銆備笅闈㈠氨鏄竴浜涘父鐢ㄩ氱敤妯″紡锛
Symbol | Matches |
---|---|
. (dot) | Any character |
\d | Any digit |
[A-Z] | Any character, A-Z (uppercase) |
[a-z] | Any character, a-z (lowercase) |
[A-Za-z] | Any character, a-z (case insensitive) |
+ | One or more of the previous expression (e.g., \d+ matches one or more digit) |
[^/]+ | All characters except forward slash |
? | Zero or more of the previous expression (e.g., \d* matches zero or more digits) |
{1,3} | Between one and three (inclusive) of the previous expression |
绗﹀彿 | 鍖归厤 |
---|---|
. (dot) | 浠绘剰瀛楃 |
\d | 浠绘剰鏁板瓧 |
[A-Z] | 浠绘剰瀛楃, A-Z (澶у啓) |
[a-z] | 浠绘剰瀛楃, a-z (灏忓啓) |
[A-Za-z] | 浠绘剰瀛楃, a-z (涓嶅尯鍒嗗ぇ灏忓啓) |
+ | 鍖归厤涓涓垨鏇村 (渚嬪, \d+ 鍖归厤涓涓垨 澶氫釜鏁板瓧瀛楃) |
[^/]+ | 涓嶆槸/鐨勪换鎰忓瓧绗 |
* | 鍖归厤0涓垨鏇村 (渚嬪, \d* 鍖归厤0涓 鎴栨洿澶氭暟瀛楀瓧绗) |
{1,3} | 鍖归厤1涓埌3涓紙鍖呭惈锛 |
For more on regular expressions, see http://www.djangoproject.com/r/python/re-module/.
鏈夊叧姝e垯琛ㄨ揪寮忕殑鏇村鍐呭锛岃璁块棶 http://www.djangoproject.com/r/python/re-module/.
We should point out several things about what just happened. Heres the nitty-gritty of what goes on when you run the Django development server and make requests to Web pages:
鎴戜滑蹇呴』瀵瑰垰鎵嶆墍鍙戠敓鐨勫嚑浠朵簨鎯呰繘琛屼竴浜涜鏄庛傚畠浠槸杩愯Django寮鍙戞湇鍔″櫒鍜屾瀯閫燱eb椤甸潰璇锋眰鐨勬湰璐ㄦ墍鍦ㄣ
The command python manage.py runserver imports a file called settings.py from the same directory. This file contains all sorts of optional configuration for this particular Django instance, but one of the most important settings is ROOT_URLCONF . The ROOT_URLCONF setting tells Django which Python module should be used as the URLconf for this Web site.
鍛戒护 python manage.py runserver 浠庡悓涓鐩綍杞藉叆鏂囦欢 settings.py 銆 璇ユ枃浠跺寘鍚簡杩欎釜鐗瑰畾鐨凞jango瀹炰緥鎵鏈夌殑鍚勭鍙夐厤缃紝鍏朵腑涓涓渶閲嶈鐨勯厤缃氨鏄 ROOT_URLCONF 銆 ROOT_URLCONF 鍛婅瘔Django鍝釜Python妯″潡搴旇鐢ㄤ綔鏈綉绔欑殑 URLconf銆
Remember when django-admin.py startproject created the files settings.py and urls.py ? Well, the autogenerated settings.py has a ROOT_URLCONF that points to the autogenerated urls.py . Convenient.
杩樿寰 django-admin.py startproject 鍒涘缓鐨勬枃浠 settings.py 鍜 urls.py 鍚楋紵 杩欐椂绯荤粺鑷姩鐢熸垚鐨 settings.py 閲 ROOT_URLCONF 榛樿璁剧疆鏄 urls.py 銆
When a request comes insay, a request to the URL /time/ Django loads the URLconf pointed to by the ROOT_URLCONF setting. Then it checks each of the URLpatterns in that URLconf in order, comparing the requested URL with the patterns one at a time, until it finds one that matches. When it finds one that matches, it calls the view function associated with that pattern, passing an HttpRequest object as the first parameter to the function. (More on HttpRequest later.)
褰撹闂 URL /time/ 鏃讹紝Django 鏍规嵁 ROOT_URLCONF 鐨勮缃杞 URLconf 銆 鐒跺悗鎸夐『搴忛愪釜鍖归厤URLconf閲岀殑URLpatterns锛岀洿鍒版壘鍒颁竴涓尮閰嶇殑銆傚綋鎵惧埌杩欎釜鍖归厤 鐨刄RLpatterns灏辫皟鐢ㄧ浉鍏宠仈鐨剉iew鍑芥暟锛屽苟鎶 HttpRequest 瀵硅薄浣滀负绗竴涓弬鏁般 锛堢◢鍚庡啀缁欏嚭 HttpRequest 鐨勬洿澶氫俊鎭級
The view function is responsible for returning an HttpResponse object.
璇 view 鍑芥暟璐熻矗杩斿洖涓涓 HttpResponse 瀵硅薄銆
You now know the basics of how to make Django-powered pages. Its quite simple, reallyjust write view functions and map them to URLs via URLconfs. You might think it would be slow to map URLs to functions using a series of regular expressions, but youd be surprised.
浣犵幇鍦ㄧ煡閬撲簡鎬庝箞鍋氫竴涓 Django-powered 椤甸潰浜嗭紝鐪熺殑寰堢畝鍗曪紝鍙渶瑕佸啓瑙嗗浘鍑芥暟骞剁敤 URLconfs鎶婂畠浠拰URLs瀵瑰簲璧锋潵銆備綘鍙兘浼氳涓虹敤涓绯诲垪姝e垯琛ㄨ揪寮忓皢URLs鏄犲皠鍒板嚱鏁颁篃璁镐細姣旇緝鎱紝浣嗕簨瀹炲嵈浼氳浣犳儕璁躲
Django濡備綍澶勭悊涓涓姹傦細瀹屾暣鐨勭粏鑺
In addition to the straightforward URL-to-view mapping just described, Django provides quite a bit of flexibility in processing requests.
闄や簡鍒氭墠鎵璇村埌鐨勭畝鏄嶶RL-to-view鏄犲皠鏂瑰紡涔嬪锛孌jango鍦ㄨ姹傚鐞嗘柟闈㈡彁渚涗簡澶ч噺鐨勭伒娲绘с
The typical flowURLconf resolution to a view function which returns an HttpResponse can be short-circuited or augmented via middleware. The deep secrets of middleware will be fully covered in Chapter 15, but a quick sketch (see Figure 3-1) should aid you in conceptually fitting the pieces together.
閫氳繃 URLconf 瑙f瀽鍒板摢涓鍥惧嚱鏁版潵杩斿洖 HttpResponse 鍙互閫氳繃涓棿浠讹紙middleware) 鏉ョ煭璺垨鑰呭寮恒傚叧浜庝腑闂翠欢鐨勭粏鑺傚皢鍦ㄧ鍗佷簲绔犺缁嗚皥璁猴紝杩欓噷缁欏嚭 鍥3-1 璁╀綘鍏堜簡瑙 澶т綋姒傚康.
Figure 3-1: The complete flow of a Django request and response.
鍥3-1锛欴jango璇锋眰鍥炲簲娴佺▼
When an HTTP request comes in from the browser, a server-specific handler constructs the HttpRequest passed to later components and handles the flow of the response processing.
褰撴湇鍔″櫒鏀跺埌涓涓狧TTP璇锋眰浠ュ悗锛屼竴涓湇鍔″櫒鐗瑰畾鐨 handler 浼氬垱寤 HttpRequest 骞朵紶閫掔粰涓嬩竴涓粍浠跺苟澶勭悊銆
The handler then calls any available Request or View middleware. These types of middleware are useful for augmenting incoming HttpRequest objects as well as providing special handling for specific types of requests. If either returns an HttpResponse , processing bypasses the view.
杩欎釜 handler 鐒跺悗璋冪敤鎵鏈夊彲鐢ㄧ殑Request鎴栬匳iew涓棿浠躲傝繖浜涚被鍨嬬殑涓棿浠堕氬父鏄敤鏉 澧炲己 HttpRequest 瀵硅薄鏉ュ涓浜涚壒鍒被鍨嬬殑request鍋氫簺鐗瑰埆澶勭悊銆傚彧瑕佸叾涓湁涓涓 杩斿洖 HttpResponse 锛岀郴缁熷氨璺宠繃瀵硅鍥剧殑澶勭悊銆
Bugs slip by even the best programmers, but exception middleware can help squash them. If a view function raises an exception, control passes to the Exception middleware. If this middleware does not return an HttpResponse , the exception is re-raised.
鍗充究鏄渶妫掔殑绋嬪簭鍛樹篃浼氭湁鍑洪敊鐨勬椂鍊欙紝 杩欎釜鏃跺 寮傚父澶勭悊涓棿浠讹紙exception middleware锛 鍙互甯綘鐨勫ぇ蹇欍傚鏋滀竴涓鍥惧嚱鏁版姏鍑哄紓甯革紝鎺у埗鍣ㄤ細浼犻掔粰寮傚父澶勭悊涓棿浠跺鐞嗐傚鏋滆繖涓 涓棿浠舵病鏈夎繑鍥 HttpResponse 锛屾剰鍛崇潃瀹冧笉鑳藉鐞嗚繖涓紓甯革紝杩欎釜寮傚父灏嗕細鍐嶆鎶涘嚭銆
Even then, all is not lost. Django includes default views that create a friendly 404 and 500 response.
鍗充究鏄繖鏍凤紝浣犱篃涓嶇敤鎷呭績銆侱jango鍖呭惈缂虹渷鐨勮鍥炬潵鐢熸垚鍙嬪ソ鐨404 鍜 500 鍥炲簲锛坮esponse锛夈
Finally, response middleware is good for post-processing an HttpResponse just before its sent to the browser or doing cleanup of request-specific resources.
鏈鍚庯紝 response middleware 鍋氬彂閫 HttpResponse 缁欐祻瑙堝櫒涔嬪墠鐨勫悗澶勭悊鎴栬呮竻闄 璇锋眰鐢ㄥ埌鐨勭浉鍏宠祫婧愩
CCEb7v <a href=”http://bsjvasklorrk.com/“>bsjvasklorrk</a>, [url=http://pawbauojlify.com/]pawbauojlify[/url], [link=http://hqsadrjkvwny.com/]hqsadrjkvwny[/link], http://koarrgjahnad.com/
Nows a good time to highlight a key philosophy behind URLconfs and behind Django in general: the principle of loose coupling . Simply put, loose coupling is a software-development approach that values the importance of making pieces interchangeable. If two pieces of code are loosely coupled, then changes made to one of the pieces will have little or no effect on the other.
鐜板湪鏄ソ鏃舵満鏉ユ寚鍑篋jango鍜孶RL閰嶇疆鑳屽悗鐨勫摬瀛︼細 鏉捐﹀悎 鍘熷垯銆傜畝鍗曠殑璇达紝鏉捐﹀悎鏄竴涓 閲嶈鐨勪繚璇佷簰鎹㈡х殑杞欢寮鍙戞柟娉曘傚鏋滀袱娈典唬鐮佹槸鏉捐﹀悎鐨勶紝閭d箞鏀瑰姩鍏朵腑涓娈典唬鐮佷笉浼 褰卞搷鍙︿竴娈典唬鐮侊紝鎴栬呭彧鏈夊緢灏戠殑涓鐐瑰奖鍝嶃
Djangos URLconfs are a good example of this principle in practice. In a Django Web application, the URL definitions and the view functions they call are loosely coupled; that is, the decision of what the URL should be for a given function, and the implementation of the function itself, reside in two separate places. This lets a developer switch out one piece without affecting the other.
Django鐨刄RL閰嶇疆灏辨槸涓涓緢濂界殑渚嬪瓙銆傚湪Django鐨勫簲鐢ㄧ▼搴忎腑锛孶RL鐨勫畾涔夊拰瑙嗗浘鍑芥暟涔嬮棿鏄澗 鑰﹀悎鐨勶紝鎹㈠彞璇濊锛屽喅瀹歎RL杩斿洖鍝釜瑙嗗浘鍑芥暟鍜屽疄鐜拌繖涓鍥惧嚱鏁版槸鍦ㄤ袱涓笉鍚岀殑鍦版柟銆傝繖浣垮緱 寮鍙戜汉鍛樺彲浠ヤ慨鏀逛竴鍧楄屼笉浼氬奖鍝嶅彟涓鍧椼
In contrast, other Web development platforms couple the URL to the program. In typical PHP (http://www.php.net/) applications, for example, the URL of your application is designated by where you place the code on your filesystem. In early versions of the CherryPy Python Web framework (http://www.cherrypy.org/), the URL of your application corresponded to the name of the method in which your code lived. This may seem like a convenient shortcut in the short term, but it can get unmanageable in the long run.
鐩告瘮涔嬩笅锛屽叾浠栫殑Web寮鍙戝钩鍙扮揣鑰﹀悎鍜孶RL鍒颁唬鐮佷腑銆傚湪鍏稿瀷鐨凱HP (http://www.php.net/) 搴旂敤锛孶RL鐨勮璁℃槸閫氳繃鏀剧疆浠g爜鐨勭洰褰曟潵瀹炵幇銆傚湪鏃╂湡鐨 CherryPy Python Web framework (http://www.cherrypy.org/) 涓紝URL瀵瑰簲澶勭悊鐨勭殑鏂规硶鍚嶃傝繖鍙兘鍦ㄧ煭鏈熺湅璧锋潵鏄究鍒╀箣涓撅紝 浣嗘槸闀挎湡浼氬甫鏉ラ毦缁存姢鐨勯棶棰樸
For example, consider the view function we wrote earlier, which displays the current date and time. If we wanted to change the URL for the application say, move it from /time/ to /currenttime/ we could make a quick change to the URLconf, without having to worry about the underlying implementation of the function. Similarly, if we wanted to change the view functionaltering its logic somehowwe could do that without affecting the URL to which the function is bound. Furthermore, if we wanted to expose the current-date functionality at several URLs, we could easily take care of that by editing the URLconf, without having to touch the view code.
姣旀柟璇达紝鑰冭檻鏈変竴涓互鍓嶅啓鐨勮鍥惧嚱鏁帮紝杩欎釜鍑芥暟鏄剧ず褰撳墠鏃ユ湡鍜屾椂闂淬傚鏋滄垜浠兂鎶婂畠鐨刄RL 浠庡師鏉ョ殑 /time/ 鏀瑰彉鍒 /currenttime/ 锛屾垜浠彧闇瑕佸揩閫熺殑淇敼涓涓婾RL閰嶇疆鍗冲彲锛 涓嶇敤鎷呭績杩欎釜鍑芥暟鐨勫唴閮ㄥ疄鐜般傚悓鏍风殑锛屽鏋滄垜浠兂瑕佷慨鏀硅繖涓嚱鏁扮殑鍐呴儴瀹炵幇涔熶笉鐢ㄦ媴蹇冧細褰卞搷 鍒板搴旂殑URL銆傛澶栵紝濡傛灉鎴戜滑鎯宠杈撳嚭杩欎釜鍑芥暟鍒 涓浜 URL锛 鎴戜滑鍙渶瑕佷慨鏀筓RL閰嶇疆鑰屼笉鐢 鍘绘敼鍔ㄨ鍥剧殑浠g爜銆
Thats loose coupling in action. Well continue to point out examples of this important philosophy throughout this book.
Django澶ч噺搴旂敤鏉捐﹀悎銆傛垜浠皢鍦ㄦ湰涔︿腑缁х画缁欏嚭杩欎竴閲嶈鍝插鐨勭浉鍏充緥瀛愩
In our URLconf thus far, weve defined only a single URLpattern: the one that handles requests to the URL /time/ . What happens when a different URL is requested?
鍦ㄦ垜浠綋鍓嶇殑杩欎釜URL閰嶇疆涓紝鎴戜滑涔嬪畾涔変簡涓涓猆RL妯″紡锛氬鐞哢RL /time/ 銆 褰撹姹傚叾浠朥RL浼氭庝箞鏍峰憿锛
To find out, try running the Django development server and hitting a page such as http://127.0.0.1:8000/hello/ or http://127.0.0.1:8000/does-not-exist/ , or even http://127.0.0.1:8000/ (the site root). You should see a Page not found message (see Figure 3-2). (Pretty, isnt it? We Django people sure do like our pastel colors.) Django displays this message because you requested a URL thats not defined in your URLconf.
璁╂垜浠瘯璇曠湅锛岃繍琛孌jango寮鍙戞湇鍔″櫒骞惰闂被浼 http://127.0.0.1:8000/hello/ 鎴栬 http://127.0.0.1:8000/does-not-exist/ 锛岀敋鑷 http://127.0.0.1:8000/ (缃戠珯鏍圭洰褰)銆備綘灏嗕細鐪嬪埌涓涓 鈥淧age not found鈥 椤甸潰锛堝浘 3锛2锛夈傦紙鎸烘紓浜殑锛屾槸鍚э紵 浣犱細鍠滄涓婃垜浠殑閰嶈壊鏂规鐨;-) 濡傛灉璇锋眰鐨刄RL娌℃湁鍦║RL閰嶇疆閲岃缃紝Django灏变細鏄剧ず杩欎釜椤甸潰銆
Figure 3-2. Djangos 404 page
鍥 3-2. Django鐨 404 椤甸潰
The utility of this page goes beyond the basic 404 error message; it also tells you precisely which URLconf Django used and every pattern in that URLconf. From that information, you should be able to tell why the requested URL threw a 404.
杩欎釜椤甸潰鐨勫姛鑳戒笉鍙槸鏄剧ず404鐨勫熀鏈敊璇俊鎭紝瀹冨悓鏍风簿纭殑鍛婅瘔浣燚jango浣跨敤浜嗗摢涓猆RL閰嶇疆鍜 杩欎釜閰嶇疆閲岀殑姣忎竴涓ā寮忋傝繖鏍凤紝浣犲簲璇ヨ兘浜嗚В鍒颁负浠涔堣繖涓姹備細鎶涘嚭404閿欒銆
Naturally, this is sensitive information intended only for you, the Web developer. If this were a production site deployed live on the Internet, we wouldnt want to expose that information to the public. For that reason, this Page not found page is only displayed if your Django project is in debug mode . Well explain how to deactivate debug mode later. For now, just know that every Django project is in debug mode when you first create it, and if the project is not in debug mode, a different response is given.
褰撶劧锛岃繖浜涙晱鎰熺殑淇℃伅搴旇鍙憟鐜扮粰浣狅紞寮鍙戣呫傚鏋滄槸閮ㄧ讲鍒颁簡鍥犵壒缃戜笂鐨勭珯鐐瑰氨涓嶅簲璇ユ毚闇 杩欎簺淇℃伅銆傚嚭浜庤繖涓冭檻锛岃繖涓淧age not found鈥濋〉闈㈠彧浼氬湪 璋冭瘯妯″紡锛坉ebug mode锛 涓 鏄剧ず銆傛垜浠皢鍦ㄤ互鍚庤鏄庢庝箞鍏抽棴璋冭瘯妯″紡銆傜幇鍦紝浣犲彧闇瑕佺煡閬撴墍鏈夌殑Django椤圭洰鍦ㄥ垱寤哄悗閮 鏄湪璋冭瘯妯″紡涓嬬殑锛屽鏋滃叧闂簡璋冭瘯妯″紡锛岀粨鏋滃皢浼氫笉涓鏍枫
In our first view example, the contents of the pagethe current date/time were dynamic, but the URL (/time/ ) was static. In most dynamic Web applications, though, a URL contains parameters that influence the output of the page.
鍦ㄦ垜浠殑绗竴涓鍥捐寖渚嬩腑锛屽敖绠″唴瀹规槸鍔ㄦ佺殑锛屼絾鏄疷RL 锛 /time/ 锛夋槸闈欐佺殑銆傚湪 澶у鏁板姩鎬亀eb搴旂敤绋嬪簭锛孶RL閫氬父閮藉寘鍚湁鐩稿叧鐨勫弬鏁般
Lets create a second view that displays the current date and time offset by a certain number of hours. The goal is to craft a site in such a way that the page /time/plus/1/ displays the date/time one hour into the future, the page /time/plus/2/ displays the date/time two hours into the future, the page /time/plus/3/ displays the date/time three hours into the future, and so on.
璁╂垜浠垱寤虹浜屼釜瑙嗗浘鏉ユ樉绀哄綋鍓嶆椂闂村拰鍔犱笂鏃堕棿鍋忓樊閲忕殑鏃堕棿锛岃璁℃槸杩欐牱鐨勶細 /time/plus/1/ 鏄剧ず褰撳墠鏃堕棿锛1涓皬鏃剁殑椤甸潰 /time/plus/2/ 鏄剧ず褰撳墠鏃堕棿锛2涓皬鏃剁殑椤甸潰 /time/plus/3/ 鏄剧ず褰撳墠鏃堕棿锛3涓皬鏃剁殑椤甸潰锛屼互姝ょ被鎺ㄣ
A novice might think to code a separate view function for each hour offset, which might result in a URLconf like this:
鏂版墜鍙兘浼氳冭檻鍐欎笉鍚岀殑瑙嗗浘鍑芥暟鏉ュ鐞嗘瘡涓椂闂村亸宸噺锛孶RL閰嶇疆鐪嬭捣鏉ュ氨璞¤繖鏍凤細
urlpatterns = patterns('', (r'^time/$', current_datetime), (r'^time/plus/1/$', one_hour_ahead), (r'^time/plus/2/$', two_hours_ahead), (r'^time/plus/3/$', three_hours_ahead), (r'^time/plus/4//$', four_hours_ahead), )
Clearly, this line of thought is flawed. Not only would this result in redundant view functions, but also the application is fundamentally limited to supporting only the predefined hour rangesone, two, three, or four hours. If, all of a sudden, we wanted to create a page that displayed the time five hours into the future, wed have to create a separate view and URLconf line for that, furthering the duplication and insanity. We need to do some abstraction here.
寰堟槑鏄撅紝杩欐牱澶勭悊鏄笉澶Ε褰撶殑銆備笉浣嗘湁寰堝鍐椾綑鐨勮鍥惧嚱鏁帮紝鑰屼笖鏁翠釜搴旂敤涔熻闄愬埗浜嗗彧鏀寔 棰勫厛瀹氫箟濂界殑鏃堕棿娈碉紝2灏忔椂锛3灏忔椂锛屾垨鑰4灏忔椂銆傚鏋滃摢澶╂垜浠瀹炵幇 5 灏忔椂锛屾垜浠氨 涓嶅緱涓嶅啀鍗曠嫭鍒涘缓鏂扮殑瑙嗗浘鍑芥暟鍜岄厤缃甎RL锛屾棦閲嶅鍙堟贩涔便傛垜浠渶瑕佸湪杩欓噷鍋氫竴鐐规娊璞★紝鎻愬彇 涓浜涘叡鍚岀殑涓滆タ鍑烘潵銆
If youre experienced in another Web development platform, such as PHP or Java, you may be thinking, Hey, lets use a query string parameter!, something like /time/plus?hours=3 , in which the hours would be designated by the hours parameter in the URLs query string (the part after the ? ).
濡傛灉浣犳湁鍏朵粬Web寮鍙戝钩鍙扮殑缁忛獙锛屼緥濡侾HP鎴栬匤AVA锛屼綘鍙兘浼氭兂锛屽ソ鍚э紝璁╂垜浠潵鐢ㄤ竴涓 鏌ヨ瀛楃涓插弬鏁版潵琛ㄧず瀹冧滑鍚э紝渚嬪 /time/plus?hours=3 锛屽摢涓椂闂存鐢 hours 鍙傛暟浠h〃锛孶RL鐨勬煡璇㈠瓧绗︿覆(query string)鏄疷RL閲 ? 鍚庨潰鐨勫瓧绗︿覆銆
You can do that with Django (and well tell you how later, if you really must know), but one of Djangos core philosophies is that URLs should be beautiful. The URL /time/plus/3/ is far cleaner, simpler, more readable, easier to recite to somebody aloud and just plain prettier than its query string counterpart. Pretty URLs are a sign of a quality Web application.
浣 鍙互 鍦―jango閲屼篃杩欐牱鍋 (濡傛灉浣犵湡鐨勬兂瑕佽繖鏍峰仛锛屾垜浠◢鍚庝細鍛婅瘔浣犳庝箞鍋氾級锛 浣嗘槸Django鐨勪竴涓牳蹇冪悊蹇靛氨鏄疷RL蹇呴』鐪嬭捣鏉ユ紓浜俇RL /time/plus/3/ 鏇村姞娓呮櫚锛 鏇寸畝鍗曪紝涔熸洿鏈夊彲璇绘э紝鍙互寰堝鏄撶殑澶у0蹇靛嚭鏉ワ紝鍥犱负瀹冩槸绾枃鏈紝娌℃湁鏌ヨ瀛楃涓查偅涔 澶嶆潅銆傛紓浜殑URL灏卞儚鏄珮璐ㄩ噺鐨刉eb搴旂敤鐨勪竴涓爣蹇椼
Djangos URLconf system encourages pretty URLs by making it easier to use pretty URLs than not to.
Django鐨刄RL閰嶇疆绯荤粺鍙互浣夸綘寰堝鏄撶殑璁剧疆婕備寒鐨刄RL锛岃屽敖閲忎笉瑕佽冭檻瀹冪殑 鍙嶉潰 銆
Continuing with our hours_ahead example, lets put a wildcard in the URLpattern. As we mentioned previously, a URLpattern is a regular expression; hence, we can use the regular expression pattern \d+ to match one or more digits:
缁х画鎴戜滑鐨 hours_ahead 鑼冧緥锛岃鎴戜滑鍦║RL妯″紡閲屼娇鐢ㄩ氶厤绗︺傛垜浠墠闈㈣鍒帮紝URL妯″紡 鏄竴涓鍒欒〃杈惧紡锛屽洜姝わ紝鎴戜滑鍙互浣跨敤姝e垯琛ㄨ揪寮忔ā寮 \d+ 鏉ュ尮閰嶄竴涓垨澶氫釜鏁板瓧锛
from django.conf.urls.defaults import * from mysite.views import current_datetime, hours_ahead urlpatterns = patterns('', (r'^time/$', current_datetime), (r'^time/plus/\d+/$', hours_ahead), )
This URLpattern will match any URL such as /time/plus/2/ , /time/plus/25/ , or even /time/plus/100000000000/ . Come to think of it, lets limit it so that the maximum allowed offset is 99 hours. That means we want to allow either one- or two-digit numbersin regular expression syntax, that translates into \d{1,2} :
杩欎釜URL妯″紡灏嗗尮閰嶇被浼 /time/plus/2/ , /time/plus/25/ ,鐢氳嚦 /time/plus/100000000000/ 鐨勪换浣昒RL銆傛洿杩涗竴姝ワ紝璁╂垜浠妸瀹冮檺鍒跺湪鏈澶у厑璁99涓皬鏃讹紝 杩欐牱鎴戜滑灏卞彧鍏佽涓涓垨涓や釜鏁板瓧锛屾鍒欒〃杈惧紡鐨勮娉曞氨鏄 \d{1,2} :
(r'^time/plus/\d{1,2}/$', hours_ahead),
Note
澶囨敞
When building Web applications, its always important to consider the most outlandish data input possible, and decide whether or not the application should support that input. Weve curtailed the outlandishness here by limiting the offset to 99 hours. And, by the way, The Outlandishness Curtailers would be a fantastic, if verbose, band name.
鍦ㄥ缓閫燱eb搴旂敤鐨勬椂鍊欙紝灏藉彲鑳藉鑰冭檻鍙兘鐨勬暟鎹緭鍏ユ槸寰堥噸瑕佺殑锛岀劧鍚庡喅瀹氬摢浜涙垜浠彲浠ユ帴鍙椼 鍦ㄨ繖閲屾垜浠氨璁剧疆浜99涓皬鏃剁殑鏃堕棿娈甸檺鍒躲
Now that weve designated a wildcard for the URL, we need a way of passing that data to the view function, so that we can use a single view function for any arbitrary hour offset. We do this by placing parentheses around the data in the URLpattern that we want to save. In the case of our example, we want to save whatever number was entered in the URL, so lets put parentheses around the \d{1,2} :
鐜板湪鎴戜滑宸茬粡璁捐浜嗕竴涓甫閫氶厤绗︾殑URL锛屾垜浠渶瑕佷竴涓柟娉曟妸瀹冧紶閫掑埌瑙嗗浘鍑芥暟閲屽幓锛岃繖鏍 鎴戜滑鍙敤涓涓鍥惧嚱鏁板氨鍙互澶勭悊鎵鏈夌殑鏃堕棿娈典簡銆傛垜浠娇鐢ㄥ渾鎷彿鎶婂弬鏁板湪URL妯″紡閲屾爣璇 鍑烘潵銆傚湪杩欎釜渚嬪瓙涓紝鎴戜滑鎯宠鎶婅繖浜涙暟瀛椾綔涓哄弬鏁帮紝鐢ㄥ渾鎷彿鎶 \d{1,2} 鍖呭洿璧锋潵锛
(r'^time/plus/(\d{1,2})/$', hours_ahead),
If youre familiar with regular expressions, youll be right at home here; were using parentheses to capture data from the matched text.
濡傛灉浣犵啛鎮夋鍒欒〃杈惧紡锛岄偅涔堜綘搴旇宸茬粡浜嗚В锛屾鍒欒〃杈惧紡涔熸槸鐢ㄥ渾鎷彿鏉ヤ粠鏂囨湰閲 鎻愬彇 鏁版嵁鐨勩
The final URLconf, including our previous current_datetime view, looks like this:
鏈缁堢殑 current_datetime URLconf锛屽寘鍚垜浠墠闈㈢殑瑙嗗浘锛岀湅璧锋潵鍍忚繖鏍凤細
from django.conf.urls.defaults import * from mysite.views import current_datetime, hours_ahead urlpatterns = patterns('', (r'^time/$', current_datetime), (r'^time/plus/(\d{1,2})/$', hours_ahead), )
With that taken care of, lets write the hours_ahead view.
鐜板湪寮濮嬪啓 hours_ahead 瑙嗗浘銆
Coding Order
缂栫爜娆″簭
In this example, we wrote the URLpattern first and the view second, but in the previous example, we wrote the view first, then the URLpattern. Which technique is better? Well, every developer is different.
杩欎釜渚嬪瓙涓紝鎴戜滑鍏堝啓浜哢RLpattern 锛岀劧鍚庢槸瑙嗗浘锛屼絾鏄湪鍓嶉潰鐨勪緥瀛愪腑锛 鎴戜滑鍏堝啓浜嗚鍥撅紝鐒跺悗鏄疷RLpattern 銆傚摢绉嶆妧鏈洿濂斤紵鍡紝鎬庝箞璇村憿锛屾瘡涓紑鍙戣呮槸涓嶄竴鏍风殑銆
If youre a big-picture type of person, it may make the most sense to you to write all of the URLpatterns for your application at the same time, at the start of your project, and then code up the views. This has the advantage of giving you a clear to-do list, and it essentially defines the parameter requirements for the view functions youll need to write.
濡傛灉浣犳槸鍠滄浠庢讳綋涓婃潵鎶婃彙浜嬬墿锛堟敞锛氭垨璇戜负鈥滃ぇ灞瑙傗濓級绫诲瀷鐨勪汉锛屼綘搴旇浼氭兂鍦ㄩ」鐩紑濮 鐨勬椂鍊欏氨鍐欎笅鎵鏈夌殑URL閰嶇疆銆傝繖浼氱粰浣犲甫鏉ヤ竴浜涘ソ澶勶紝渚嬪锛岀粰浣犱竴涓竻鏅扮殑to-do鍒楄〃锛岃浣 鏇村ソ鐨勫畾涔夎鍥炬墍闇鐨勫弬鏁般
If youre more of a bottom-up developer, you might prefer to write the views first, and then anchor them to URLs afterward. Thats OK, too.
濡傛灉浣犱粠鏇村儚鏄竴涓嚜搴曞悜涓婄殑寮鍙戣咃紝浣犲彲鑳芥洿鍠滄鍏堝啓瑙嗗浘锛 鐒跺悗鎶婂畠浠寕鎺ュ埌URL涓娿傝繖鍚屾牱鏄彲浠ョ殑銆
In the end, it comes down to which technique fits your brain the best. Both approaches are valid.
鏈鍚庯紝鍙栧喅涓庝綘鍠滄鍝鎶鏈紝涓ょ鏂规硶閮芥槸鍙互鐨勩
hours_ahead is very similar to the current_datetime view we wrote earlier, with a key difference: it takes an extra argument, the number of hours of offset. Add this to views.py :
hours_ahead 鍜屾垜浠互鍓嶅啓鐨 current_datetime 寰堣薄锛屽叧閿殑鍖哄埆鍦ㄤ簬锛 瀹冨浜嗕竴涓澶栧弬鏁帮紝鏃堕棿宸 views.py 淇敼濡備笅:
def hours_ahead(request, offset): offset = int(offset) dt = datetime.datetime.now() + datetime.timedelta(hours=offset) html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt) return HttpResponse(html)
Lets step through this code one line at a time:
璁╂垜浠竴娆′竴琛岄氫竴涓嬭繖浜涗唬鐮侊細
Just as we did for our current_datetime view, we import the class django.http.HttpResponse and the datetime module.
灏卞儚鎴戜滑鍦ㄦ垜浠殑 current_datetime 瑙嗗浘涓墍浣滅殑涓鏍凤紝鎴戜滑瀵煎叆 django.http.HttpResponse 绫诲拰 datetime 妯″潡銆
The view function, hours_ahead , takes two parameters: request and offset .
瑙嗗浘鍑芥暟, hours_ahead , 鏈 涓や釜 鍙傛暟: request 鍜 offset .
request is an HttpRequest object, just as in current_datetime . Well say it again: each view always takes an HttpRequest object as its first parameter.
request 鏄竴涓 HttpRequest 瀵硅薄, 灏卞儚鍦 current_datetime 涓竴鏍. 鍐嶈涓娆″ソ浜: 姣忎竴涓鍥 鎬绘槸 浠ヤ竴涓 HttpRequest 瀵硅薄浣滀负 瀹冪殑绗竴涓弬鏁般
offset is the string captured by the parentheses in the URLpattern. For example, if the requested URL were /time/plus/3/ , then offset would be the string '3' . If the requested URL were /time/plus/21/ , then offset would be the string '21' . Note that captured strings will always be strings , not integers, even if the string is composed of only digits, such as '21' .
offset 鏄粠鍖归厤鐨刄RL閲屾彁鍙栧嚭鏉ョ殑銆備緥濡傦細 濡傛灉URL鏄 /time/plus/3/ 閭d箞 offset 鏄瓧绗︿覆 '3' 锛 濡傛灉URL鏄 /time/plus/21/ 锛岄偅涔 offset 鏄瓧绗︿覆 '21' 锛 娉ㄦ剰锛屾彁鍙栫殑瀛楃涓叉绘槸 瀛楃涓 锛屼笉鏄暣鏁帮紝鍗充究閮芥槸鏁板瓧缁勬垚锛屽氨璞 '21' 銆
We decided to call the variable offset , but you can call it whatever youd like, as long as its a valid Python identifier. The variable name doesnt matter; all that matters is that its the second argument to the function (after request ). Its also possible to use keyword, rather than positional, arguments in an URLconf. We cover that in Chapter 8.
鍦ㄨ繖閲屾垜浠懡鍚嶅彉閲忎负 offset 锛屼綘涔熷彲浠ヤ换鎰忓懡鍚嶅畠锛屽彧瑕佺鍚圥ython 鐨勮娉曘傚彉閲忓悕鏄棤鍏崇揣瑕佺殑锛岄噸瑕佺殑鏄畠鐨勪綅缃紝瀹冩槸杩欎釜鍑芥暟鐨勭浜屼釜 鍙傛暟 (鍦 request 鐨勫悗闈級銆備綘杩樺彲浠ヤ娇鐢ㄥ叧閿瓧鏉ュ畾涔夊畠锛岃屼笉鏄敤 浣嶇疆銆傝鎯呰鐪嬬鍏珷銆
The first thing we do within the function is call int() on offset . This converts the string value to an integer.
鎴戜滑鍦ㄨ繖涓嚱鏁颁腑瑕佸仛鐨勭涓浠朵簨鎯呭氨鏄湪 offset 涓婅皟鐢 int() . 杩欎細鎶婅繖涓瓧绗︿覆鍊艰浆鎹负鏁存暟銆
Note that Python will raise a ValueError exception if you call int() on a value that cannot be converted to an integer, such as the string 'foo' . However, in this example we dont have to worry about catching that exception, because we can be certain offset will be a string containing only digits. We know that because the regular-expression pattern in our URLconf (\d{1,2}) captures only digits. This illustrates another nicety of URLconfs: they provide a fair level of input validation.
娉ㄦ剰Python鍙兘浼氬湪浣犺皟鐢 int() 鏉ヨ浆鎹竴涓笉鑳借浆鎹㈡垚鏁存暟鏃舵姏鍑 ValueError 寮傚父锛屼緥濡傚瓧绗︿覆 'foo' 銆 褰撶劧锛屽湪杩欎釜鑼冧緥涓垜浠笉鐢ㄦ媴蹇冭繖涓棶棰橈紝鍥犱负鎴戜滑宸茬粡纭畾 offset 鏄 鍙寘鍚暟瀛楀瓧绗︾殑瀛楃涓层傚洜涓烘鍒欒〃杈惧紡 (\d{1,2}) 鍙彁鍙栨暟瀛楀瓧绗︺ 杩欎篃鏄疷RL閰嶇疆鐨勫彟涓涓ソ澶勶細鎻愪緵浜嗘竻鏅扮殑杈撳叆鏁版嵁鏈夋晥鎬х‘璁ゃ
The next line of the function shows why we called int() on offset . On this line, we calculate the current time plus a time offset of offset hours, storing the result in dt . The datetime.timedelta function requires the hours parameter to be an integer.
涓嬩竴琛屾樉绀轰簡鎴戜滑涓轰粈涔堣皟鐢 int() 鏉ヨ浆鎹 offset 銆 杩欎竴琛屾垜浠 璁$畻褰撳墠鏃堕棿鍔犱笂杩欎釜鏃堕棿宸 offset 灏忔椂锛屼繚瀛樼粨鏋滃埌鍙橀噺 dt 銆 datetime.timedelta 鍑芥暟鐨勫弬鏁 hours 蹇呴』鏄暣鏁扮被鍨嬨
Next, we construct the HTML output of this view function, just as we did in current_datetime . A small difference in this line from the previous line is that it uses Pythons format-string capability with two values, not just one. Hence, there are two %s symbols in the string and a tuple of values to insert: (offset, dt) .
杩欒鍜屽墠闈㈢殑閭h鐨勭殑涓涓井灏忓樊鍒氨鏄紝瀹冧娇鐢ㄥ甫鏈変袱涓肩殑Python鐨勬牸寮忓寲瀛楃涓插姛鑳斤紝 鑰屼笉浠呬粎鏄竴涓笺傚洜姝わ紝鍦ㄥ瓧绗︿覆涓湁涓や釜 %s 绗﹀彿鍜屼竴涓互杩涜鎻掑叆鐨勫肩殑鍏冪粍锛 (offset, dt) 銆
Finally, we return an HttpResponse of the HTMLagain, just as we did in current_datetime .
鏈鍚庯紝鎴戜滑鍐嶄竴娆¤繑鍥炰竴涓狧TML鐨 HttpResponse 锛屽氨鍍忔垜浠湪 current_datetime 鍋氱殑涓鏍枫
With that view function and URLconf written, start the Django development server (if its not already running), and visit http://127.0.0.1:8000/time/plus/3/ to verify it works. Then try http://127.0.0.1:8000/time/plus/5/ . Then http://127.0.0.1:8000/time/plus/24/ . Finally, visit http://127.0.0.1:8000/time/plus/100/ to verify that the pattern in your URLconf only accepts one- or two-digit numbers; Django should display a Page not found error in this case, just as we saw in the 404 Errors section earlier. The URL http://127.0.0.1:8000/time/plus/ (with no hour designation) should also throw a 404.
鍦ㄥ畬鎴愯鍥惧嚱鏁板拰URL閰嶇疆缂栧啓鍚庯紝鍚姩Django寮鍙戞湇鍔″櫒锛岀敤娴忚鍣ㄨ闂 http://127.0.0.1:8000/time/plus/3/ 鏉ョ‘璁ゅ畠宸ヤ綔姝e父銆 鐒跺悗鏄 http://127.0.0.1:8000/time/plus/5/ 銆傚啀鐒跺悗鏄 http://127.0.0.1:8000/time/plus/24/ 銆傛渶鍚庯紝璁块棶 http://127.0.0.1:8000/time/plus/100/ 鏉ユ楠孶RL閰嶇疆閲岃缃殑妯″紡鏄惁鍙 鎺ュ彈涓涓垨涓や釜鏁板瓧锛汥jango浼氭樉绀轰竴涓 Page not found error 椤甸潰, 鍜屼互鍓嶇湅鍒扮殑 404 閿欒涓鏍枫傝闂甎RL http://127.0.0.1:8000/time/plus/ (娌℃湁 瀹氫箟鏃堕棿宸) 涔熶細鎶涘嚭404閿欒銆
If youre following along while coding at the same time, youll notice that the views.py file now contains two views. (We omitted the current_datetime view from the last set of examples for clarity.) Put together, views.py should look like this:
浣犵幇鍦ㄥ凡缁忔敞鎰忓埌 views.py 鏂囦欢涓寘鍚簡涓や釜瑙嗗浘锛 views.py 鐪嬭捣鏉ヨ薄杩欐牱锛
from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html) def hours_ahead(request, offset): offset = int(offset) dt = datetime.datetime.now() + datetime.timedelta(hours=offset) html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt) return HttpResponse(html)
Take a moment to admire the fine Web application weve made so far now lets break it! Well deliberately introduce a Python error into our views.py file by commenting out the offset = int(offset) line in the hours_ahead view:
鑺卞嚑鍒嗛挓鏃堕棿娆h祻涓涓嬫垜浠啓濂界殑Web搴旂敤绋嬪簭锛岀劧鍚庢垜浠啀鏉ユ悶鐐瑰皬鐮村潖銆傛垜浠晠鎰忓湪 views.py 鏂囦欢涓紩鍏ヤ竴椤 Python 閿欒锛屾敞閲婃帀 hours_ahead 瑙嗗浘涓殑 offset = int(offset) 涓琛屻
def hours_ahead(request, offset): #offset = int(offset) dt = datetime.datetime.now() + datetime.timedelta(hours=offset) html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt) return HttpResponse(html)
Load up the development server and navigate to /time/plus/3/ . Youll see an error page with a significant amount of information, including a TypeError message displayed at the very top: "unsupported type for timedelta hours component: str" .
鍚姩寮鍙戞湇鍔″櫒锛岀劧鍚庤闂 /time/plus/3/ 銆備綘浼氱湅鍒颁竴涓寘鍚ぇ閲忎俊鎭殑鍑洪敊椤碉紝鏈涓婇潰 鐨勪竴鏉 TypeError 淇℃伅鏄細 "unsupported type for timedelta hours component: str" 銆
What happened? Well, the datetime.timedelta function expects the hours parameter to be an integer, and we commented out the bit of code that converted offset to an integer. That caused datetime.timedelta to raise the TypeError . Its the typical kind of small bug that every programmer runs into at some point.
鎬庝箞鍥炰簨鍛紵鏄殑锛 datetime.timedelta 鍑芥暟瑕佹眰 hours 鍙傛暟蹇呴』涓烘暣鍨嬶紝 鑰屾垜浠敞閲婃帀浜嗗皢 offset 杞负鏁村瀷鐨勪唬鐮併傝繖鏍峰鑷 datetime.timedelta 寮瑰嚭 TypeError 寮傚父銆傝繖鏄墍鏈夌▼搴忓憳鏌愪釜鏃跺欓兘鍙兘纰板埌鐨勪竴绉嶅吀鍨嬮敊璇
The point of this example was to demonstrate Djangos error pages. Take some time to explore the error page and get to know the various bits of information it gives you.
杩欎釜渚嬪瓙鏄负浜嗗睍绀 Django 鐨勫嚭閿欓〉闈€傛垜浠潵鑺变簺鏃堕棿鐪嬩竴鐪嬭繖涓嚭閿欓〉锛屼簡瑙d竴涓嬪叾涓 缁欏嚭浜嗗摢浜涗俊鎭
Here are some things to notice:
浠ヤ笅鏄煎緱娉ㄦ剰鐨勪竴浜涜鐐癸細
At the top of the page, you get the key information about the exception: the type of exception, any parameters to the exception (the "unsupported type" message in this case), the file in which the exception was raised, and the offending line number.
鍦ㄩ〉闈㈤《閮紝浣犲彲浠ュ緱鍒板叧閿殑寮傚父淇℃伅锛氬紓甯告暟鎹被鍨嬨佸紓甯哥殑鍙傛暟 (濡傛湰渚嬩腑鐨 "unsupported type" 锛夈佸湪鍝釜鏂囦欢涓紩鍙戜簡寮傚父銆佸嚭閿欑殑琛屽彿绛夌瓑銆
Under the key exception information, the page displays the full Python traceback for this exception. This is similar to the standard traceback you get in Pythons command-line interpreter, except its more interactive. For each frame in the stack, Django displays the name of the file, the function/method name, the line number, and the source code of that line.
鍦ㄥ叧閿紓甯镐俊鎭笅鏂癸紝璇ラ〉闈㈡樉绀轰簡瀵硅寮傚父鐨勫畬鏁 Python 杩借釜淇℃伅銆傝繖绫讳技浜庝綘鍦 Python 鍛戒护琛岃В閲婂櫒涓幏寰楃殑杩芥函淇℃伅锛屽彧涓嶈繃鍚庤呮洿鍏蜂氦浜掓с傚鏍堜腑鐨勬瘡涓甯э紝Django 鍧囨樉绀轰簡鍏舵枃浠跺悕銆佸嚱鏁版垨鏂规硶鍚嶃佽鍙峰強璇ヨ婧愪唬鐮併
Click the line of source code (in dark gray), and youll see several lines from before and after the erroneous line, to give you context.
鐐瑰嚮璇ヨ浠g爜 (浠ユ繁鐏拌壊鏄剧ず)锛屼綘鍙互鐪嬪埌鍑洪敊琛岀殑鍓嶅悗鍑犺锛屼粠鑰屽緱鐭ョ浉鍏充笂涓嬫枃鎯呭喌銆
Click Local vars under any frame in the stack to view a table of all local variables and their values, in that frame, at the exact point in the code at which the exception was raised. This debugging information is invaluable.
鐐瑰嚮鏍堜腑鐨勪换浣曚竴甯х殑鈥淟ocal vars鈥濆彲浠ョ湅鍒颁竴涓墍鏈夊眬閮ㄥ彉閲忕殑鍒楄〃锛屼互鍙婂湪鍑洪敊 閭d竴甯ф椂瀹冧滑鐨勫笺傝繖浜涜皟璇曚俊鎭槸鏃犱环鐨勩
Note the Switch to copy-and-paste view text under the Traceback header. Click those words, and the traceback will switch to a alternate version that can be easily copied and pasted. Use this when you want to share your exception traceback with others to get technical support such as the kind folks in the Django IRC chat room or on the Django users mailing list.
娉ㄦ剰鈥淭raceback鈥濅笅闈㈢殑鈥淪witch to copy-and-paste view鈥濇枃瀛椼傜偣鍑昏繖浜涘瓧锛岃拷婧細 鍒囨崲鍙︿竴涓鍥撅紝瀹冭浣犲緢瀹规槗鍦板鍒跺拰绮樿创杩欎簺鍐呭銆傚綋浣犳兂鍚屽叾浠栦汉鍒嗕韩杩欎簺寮傚父 杩芥函浠ヨ幏寰楁妧鏈敮鎸佹椂锛堟瘮濡傚湪 Django 鐨 IRC 鑱婂ぉ瀹ゆ垨閭欢鍒楄〃涓級锛屽彲浠ヤ娇鐢ㄥ畠銆
Next, the Request information section includes a wealth of information about the incoming Web request that spawned the error: GET and POST information, cookie values, and meta information, such as CGI headers. Appendix H has a complete reference of all the information a request object contains.
鎺ヤ笅鏉ョ殑鈥淩equest information鈥濋儴鍒嗗寘鍚簡鏈夊叧浜х敓閿欒鐨 Web 璇锋眰鐨勫ぇ閲忎俊鎭細 GET 鍜 POST銆乧ookie 鍊笺佸厓鏁版嵁锛堣薄 CGI 澶达級銆傚湪闄勫綍H閲岀粰鍑轰簡request鐨勫璞$殑 瀹屾暣鍙傝冦
Below the Request information section, the Settings section lists all of the settings for this particular Django installation. All the available settings are covered in detail in Appendix E. For now, take a look at the settings to get an idea of the information available.
Request淇℃伅鐨勪笅闈紝鈥淪ettings鈥濆垪鍑轰簡 Django 浣跨敤鐨勫叿浣撻厤缃俊鎭傚悓鏍峰湪闄勫綍E 缁欏嚭浜唖ettings 閰嶇疆鐨勫畬鏁村弬鑰冦傜幇鍦紝澶ф娴忚涓涓嬶紝瀵瑰畠浠湁涓ぇ鑷村嵃璞″氨濂戒簡銆
The Django error page is capable of displaying more information in certain special cases, such as the case of template syntax errors. Well get to those later, when we discuss the Django template system. For now, uncomment the offset = int(offset) line to get the view function working properly again.
Django 鐨勫嚭閿欓〉鏌愪簺鎯呭喌涓嬫湁鑳藉姏鏄剧ず鏇村鐨勪俊鎭紝姣斿妯℃澘璇硶閿欒銆傛垜浠璁 Django 妯℃澘绯荤粺鏃跺啀璇村畠浠傜幇鍦紝鍙栨秷 offset = int(offset) 杩欒鐨勬敞閲婏紝璁╁畠閲嶆柊姝e父 宸ヤ綔銆
Are you the type of programmer who likes to debug with the help of carefully placed print statements? You can use the Django error page to do sojust without the print statements. At any point in your view, temporarily insert an assert False to trigger the error page. Then, you can view the local variables and state of the program. (Theres a more advanced way to debug Django views, which well explain later, but this is the quickest and easiest.)
涓嶇煡閬撲綘鏄笉鏄偅绉嶄娇鐢ㄥ皬蹇冩斁缃殑 print 璇彞鏉ュ府鍔╄皟璇曠殑绋嬪簭鍛橈紵浣犲叾瀹炲彲浠ョ敤 Django 鍑洪敊椤垫潵鍋氳繖浜涳紝鑰屼笉鐢 print 璇彞銆傚湪浣犺鍥剧殑浠讳綍浣嶇疆锛屼复鏃舵彃鍏ヤ竴涓 assert False 鏉ヨЕ鍙戝嚭閿欓〉銆傜劧鍚庯紝浣犲氨鍙互鐪嬪埌灞閮ㄥ彉閲忓拰绋嬪簭璇彞浜嗐傦紙杩樻湁鏇撮珮绾х殑鍔炴硶鏉ヨ皟璇 Django 瑙嗗浘锛屾垜浠悗鏉ュ啀璇达紝浣嗚繖涓槸鏈蹇嵎鏈绠鍗曠殑鍔炴硶浜嗐傦級
Finally, its obvious that much of this information is sensitiveit exposes the innards of your Python code and Django configurationand it would be foolish to show this information on the public Internet. A malicious person could use it to attempt to reverse-engineer your Web application and do nasty things. For that reason, the Django error page is only displayed when your Django project is in debug mode. Well explain how to deactivate debug mode later. For now, just know that every Django project is in debug mode automatically when you start it. (Sound familiar? The Page not found errors, described in the 404 Errors section, work the same way.)
鏈鍚庯紝寰堟樉鐒惰繖浜涗俊鎭緢澶氭槸鏁忔劅鐨勶紝瀹冩毚闇蹭簡浣 Python 浠g爜鐨勫唴閮ㄧ粨鏋勪互鍙 Django 閰嶇疆锛屽湪 Internet 涓婂叕寮杩欎俊鎭槸寰堟剼锠㈢殑銆備笉鎬濂芥剰鐨勪汉浼氬皾璇曚娇鐢ㄥ畠鏀诲嚮浣犵殑 Web 搴旂敤绋嬪簭锛屽仛浜涗笅娴佷箣浜嬨傚洜姝わ紝Django 鍑洪敊淇℃伅浠呭湪 debug 妯″紡涓嬫墠浼氭樉鐜般傛垜浠◢鍚 璇存槑濡備綍绂佺敤 debug 妯″紡銆傜幇鍦紝浣犲彧瑕佺煡閬 Django 鏈嶅姟鍣ㄥ湪浣犲紑鍚畠鏃堕粯璁よ繍琛屽湪 debug 妯″紡灏辫浜嗐傦紙鍚捣鏉ュ緢鐔熸倝锛熲淧age not found鈥濋敊璇紝鈥404 閿欒鈥濅竴鑺備篃杩欐牱鎻忚堪杩囥傦級
Weve so far been producing views by hard-coding HTML into the Python code. Unfortunately, this is nearly always a bad idea. Luckily, Django ships with a simple yet powerful template engine that allows you to separate the design of the page from the underlying code. Well dive into Djangos template engine in the next chapter.
鎴戜滑鐜板湪宸茬粡瀛︿細浜嗘庝箞鍦≒ython浠g爜閲岀‖缂栫爜HTML浠g爜鏉ュ鐞嗚鍥俱傚彲鎯滅殑鏄紝杩欑鏂规硶閫氬父涓嶆槸涓涓ソ鏂规硶銆傚垢杩愮殑鏄紝Django鍐呭缓鏈変竴涓畝鍗曟湁寮哄ぇ鐨勬ā鏉垮鐞嗗紩鎿庢潵璁╀綘鍒嗙涓ょ宸ヤ綔锛氳璁TML椤甸潰鍜岀紪鍐橮ython浠g爜銆備笅涓绔犳垜浠皢娣卞叆鍒癉jango鐨勬ā鏉垮紩鎿庨噷鍘汇
鍏充簬鏈瘎娉ㄧ郴缁
鏈珯浣跨敤涓婁笅鏂囧叧鑱旂殑璇勬敞绯荤粺鏉ユ敹闆嗗弽棣堜俊鎭備笉鍚屼簬涓鑸鏁寸珷鍋氳瘎娉ㄧ殑鍋氭硶锛 鎴戜滑鍏佽浣犲姣忎竴涓嫭绔嬬殑鈥滄枃鏈潡鈥濆仛璇勬敞銆備竴涓滄枃鏈潡鈥濈湅璧锋潵鏄繖鏍风殑锛
涓涓滄枃鏈潡鈥濇槸涓涓钀斤紝涓涓垪琛ㄩ」锛屼竴娈典唬鐮侊紝鎴栬呭叾浠栦竴灏忔鍐呭銆 浣犻変腑瀹冧細楂樹寒搴︽樉绀:
瑕佸鏂囨湰鍧楀仛璇勬敞锛屼綘鍙渶瑕佺偣鍑诲畠鏃佽竟鐨勬爣璇嗗潡:
鎴戜滑浼氫粩缁嗛槄璇绘瘡涓瘎璁猴紝濡傛灉鍙兘鐨勮瘽鎴戜滑涔熶細鎶婅瘎娉ㄨ冭檻鍒版湭鏉ョ殑鐗堟湰涓幓:
濡傛灉浣犳効鎰忎綘鐨勮瘎娉ㄨ閲囩敤锛岃纭繚鐣欎笅浣犵殑鍏ㄥ悕 (娉ㄦ剰涓嶆槸鏄电О鎴栫畝绉帮級
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.