The Django Book

Chapter 3: The Basics of Dynamic Web Pages

绗笁绔狅細鍔ㄦ佺綉椤靛熀纭

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 鍒涘缓鍔ㄦ佺綉椤点

Your First View: Dynamic Content

绗竴浠借鍥撅細鍔ㄦ佸唴瀹

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 浜嗚В鏇村鍏充簬 HttpRequestHttpResponse 鐨勭粏鑺傘

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/ChicagoTIME_ZONE 璁剧疆銆傝繖鍙兘涓嶆槸浣犳墍灞呬綇鐨勬椂鍖猴紝鍥犳浣犲彲浠ュ湪 settings.py 鏂囦欢涓慨鏀瑰畠銆傝鍙傞槄闄勫綍 E 浜嗚В鏇村缁嗚妭銆

Mapping URLs to Views

灏 URL 鏄犲皠鍒拌鍥

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/.

How Django Processes a Request

Django鏄庝箞澶勭悊璇锋眰鐨

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_URLCONFROOT_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.pyurls.py 鍚楋紵 杩欐椂绯荤粺鑷姩鐢熸垚鐨 settings.pyROOT_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鏄犲皠鍒板嚱鏁颁篃璁镐細姣旇緝鎱紝浣嗕簨瀹炲嵈浼氳浣犳儕璁躲

How Django Processes a Request: Complete Details

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 璁╀綘鍏堜簡瑙 澶т綋姒傚康.

The complete flow of a Django request and response. Django request 鍜 response 鐨勫畬鏁存祦绋嬨

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 缁欐祻瑙堝櫒涔嬪墠鐨勫悗澶勭悊鎴栬呮竻闄 璇锋眰鐢ㄥ埌鐨勭浉鍏宠祫婧愩

URLconfs and Loose Coupling

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澶ч噺搴旂敤鏉捐﹀悎銆傛垜浠皢鍦ㄦ湰涔︿腑缁х画缁欏嚭杩欎竴閲嶈鍝插鐨勭浉鍏充緥瀛愩

404 Errors

404 閿欒

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灏变細鏄剧ず杩欎釜椤甸潰銆

Screenshot of Djangos 404 page. Djangos 404 椤甸潰鎴睆.

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椤圭洰鍦ㄥ垱寤哄悗閮 鏄湪璋冭瘯妯″紡涓嬬殑锛屽鏋滃叧闂簡璋冭瘯妯″紡锛岀粨鏋滃皢浼氫笉涓鏍枫

Your Second View: Dynamic URLs

绗簩涓鍥撅細鍔ㄦ乁RL

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锛屾棦閲嶅鍙堟贩涔便傛垜浠渶瑕佸湪杩欓噷鍋氫竴鐐规娊璞★紝鎻愬彇 涓浜涘叡鍚岀殑涓滆タ鍑烘潵銆

A Word About Pretty URLs

鍏充簬婕備寒URL鐨勪竴鐐瑰缓璁

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锛岃屽敖閲忎笉瑕佽冭檻瀹冪殑 鍙嶉潰

Wildcard URLpatterns

甯﹂氶厤绗︾殑URL鍖归厤妯″紡

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 , 鏈 涓や釜 鍙傛暟: requestoffset .

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 灏忔椂锛屼繚瀛樼粨鏋滃埌鍙橀噺 dtdatetime.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)

Djangos Pretty Error Pages

Django 婕備寒鐨勫嚭閿欓〉闈

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 閿欒鈥濅竴鑺備篃杩欐牱鎻忚堪杩囥傦級

Whats next?

涓嬩竴绔犲皢瑕佽?

System Message: WARNING/2 (<string>, line 2055)

Title underline too short.

涓嬩竴绔犲皢瑕佽?
``````````

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鐨勬ā鏉垮紩鎿庨噷鍘汇

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