In the previous chapter, you may have noticed something peculiar in how we returned the text in our example views. Namely, the HTML was hard-coded directly in our Python code.
鍦ㄥ墠涓绔犱腑锛屼綘鍙兘宸茬粡娉ㄦ剰鍒版垜浠湪渚嬪瓙瑙嗗浘涓繑鍥炴枃鏈殑鏂瑰紡鏈夌偣鐗瑰埆銆備篃灏辨槸璇达紝HTML琚‖鎬у湴鐩存帴鍐欏叆 Python 浠g爜涔嬩腑銆
This arrangement leads to several problems:
杩欑澶勭悊浼氬鑷翠竴浜涢棶棰橈細
Any change to the design of the page requires a change to the Python code. The design of a site tends to change far more frequently than the underlying Python code, so it would be convenient if the the design could change without needing to modify the Python code.
瀵归〉闈㈣璁¤繘琛岀殑浠讳綍鏀瑰彉閮藉繀椤诲 Python 浠g爜杩涜鐩稿簲鐨勪慨鏀广傜珯鐐硅璁$殑淇敼寰寰姣斿簳灞 Python 浠g爜鐨勪慨鏀硅棰戠箒寰楀锛屽洜姝ゅ鏋滃彲浠ュ湪涓嶈繘琛 Python 浠g爜淇敼鐨勬儏鍐典笅鍙樻洿璁捐锛岄偅灏嗕細鏂逛究寰楀銆
Writing Python code and designing HTML are two different disciplines, and most professional Web development environments split these responsibilities between separate people (or even separate departments). Designers and HTML/CSS coders shouldnt have to edit Python code to get their job done; they should deal with HTML.
Python 浠g爜缂栧啓鍜 HTML 璁捐鏄袱椤逛笉鍚岀殑宸ヤ綔锛屽ぇ澶氭暟涓撲笟鐨勭綉绔欏紑鍙戠幆澧冮兘灏嗕粬浠垎閰嶇粰涓嶅悓鐨勪汉鍛橈紙鐢氳嚦涓嶅悓閮ㄩ棬锛夋潵瀹屾垚銆傝璁′汉鍛樺拰 HTML/CSS 缂栧啓浜哄憳閮戒笉搴旇閫氳繃缂栬緫 Python 浠g爜鏉ュ畬鎴愯嚜宸辩殑宸ヤ綔锛涗粬浠簲璇ュ鐞嗙殑鏄 HTML銆
Similarly, its most efficient if programmers can work on Python code and designers can work on templates at the same time, rather than one person waiting for the other to finish editing a single file that contains both Python and HTML.
鍚岀悊锛岀▼搴忓憳缂栧啓 Python 浠g爜鍜岃璁′汉鍛樺埗浣滄ā鏉垮悓鏃惰繘琛岀殑宸ヤ綔鏂瑰紡鏁堢巼鏄渶楂樼殑锛岃繙鑳滀簬璁╀竴涓汉绛夊緟鍙︿竴涓汉瀹屾垚瀵规煇涓棦鍖呭惈 Python 鍙堝寘鍚 HTML 鐨勬枃浠剁殑缂栬緫宸ヤ綔銆
For these reasons, its much cleaner and more maintainable to separate the design of the page from the Python code itself. We can do this with Djangos template system , which we discuss in this chapter.
鍩轰簬杩欎簺鍘熷洜锛屽皢椤甸潰鐨勮璁″拰Python鐨勪唬鐮佸垎绂诲紑浼氭洿骞插噣绠娲佹洿瀹规槗缁存姢銆傛垜浠彲浠ヤ娇鐢 Django鐨 妯℃澘绯荤粺 (Template System)鏉ュ疄鐜拌繖绉嶆ā寮忥紝杩欏氨鏄湰绔犺鍏蜂綋璁ㄨ鐨勯棶棰樸
A Django template is a string of text that is intended to separate the presentation of a document from its data. A template defines placeholders and various bits of basic logic (i.e., template tags) that regulate how the document should be displayed. Usually, templates are used for producing HTML, but Django templates are equally capable of generating any text-based format.
Lets dive in with a simple example template. This template describes an HTML page that thanks a person for placing an order with a company. Think of it as a form letter:
璁╂垜浠繁鍏ュ垎鏋愪竴涓畝鍗曠殑渚嬪瓙妯℃澘銆傝妯℃澘鎻忚堪浜嗕竴涓悜鏌愪釜涓庡叕鍙哥鍗曚汉鍛樿嚧璋 HTML 椤甸潰銆傚彲灏嗗叾瑙嗕负涓涓牸寮忎俊鍑斤細
<html> <head><title>Ordering notice</title></head> <body> <p>Dear {{ person_name }},</p> <p>Thanks for placing an order from {{ company }}. It's scheduled to ship on {{ ship_date|date:"F j, Y" }}.</p> <p>Here are the items you've ordered:</p> <ul> {% for item in item_list %} <li>{{ item }}</li> {% endfor %} </ul> {% if ordered_warranty %} <p>Your warranty information will be included in the packaging.</p> {% endif %} <p>Sincerely,<br />{{ company }}</p> </body> </html>
This template is basic HTML with some variables and template tags thrown in. Lets step through it:
璇ユā鏉挎槸涓娈垫坊鍔犱簡浜涜鍙橀噺鍜屾ā鏉挎爣绛剧殑鍩虹 HTML 銆傝鎴戜滑閫愬彞杩囦竴閬嶏細
Any text surrounded by a pair of braces (e.g., {{ person_name }} ) is a variable . This means insert the value of the variable with the given name. How do we specify the values of the variables? Well get to that in a moment.
鐢ㄤ袱涓ぇ鎷彿鎷捣鏉ョ殑鏂囧瓧锛堜緥濡 {{ person_name }} 锛夋槸 鍙橀噺(variable) 銆傝繖鎰忓懗鐫灏嗘寜鐓х粰瀹氱殑鍚嶅瓧鎻掑叆鍙橀噺鐨勫笺傚浣曟寚瀹氬彉閲忕殑鍊煎憿锛熺◢鍚庡氨浼氳鏄庛
Any text thats surrounded by curly braces and percent signs (e.g., {% if ordered_warranty %} ) is a template tag . The definition of a tag is quite broad: a tag just tells the template system to do something.
琚ぇ鎷彿鍜岀櫨鍒嗗彿鍖呭洿鐨勬枃鏈(渚嬪 {% if ordered_warranty %} )鏄 妯℃澘鏍囩(template tag) 銆傛爣绛(tag)瀹氫箟姣旇緝鏄庣‘锛屽嵆锛氫粎閫氱煡妯℃澘绯荤粺瀹屾垚鏌愪簺宸ヤ綔鐨勬爣绛俱
This example template contains two tags: the {% for item in item_list %} tag (a for tag) and the {% if ordered_warranty %} tag (an if tag).
杩欎釜绀轰緥妯℃澘鍖呭惈涓や釜鏍囩(tag): {% for item in item_list %} 鏍囩(涓涓 for 鏍囩) 鍜 {% if ordered_warranty %} 鏍囩 (涓涓 if 鏍囩)銆
A for tag acts as a simple loop construct, letting you loop over each item in a sequence. An if tag, as you may expect, acts as a logical if statement. In this particular case, the tag checks whether the value of the ordered_warranty variable evaluates to True . If it does, the template system will display everything between the {% if ordered_warranty %} and {% endif %} . If not, the template system wont display it. The template system also supports {% else %} and other various logic statements.
for 鏍囩鐢ㄤ簬鏋勫缓绠鍗曠殑寰幆锛屽厑璁镐綘閬嶅巻寰幆涓殑姣忎竴椤广 if 鏍囩锛屾濡備綘鎵鏂欙紝鏄敤鏉ユ墽琛岄昏緫鍒ゆ柇鐨勩傚湪杩欎釜渚嬪瓙涓爣绛炬娴 ordered_warranty 鍙橀噺鍊兼槸鍚︿负 True 銆 濡傛灉鏄紝妯℃澘绯荤粺灏嗘樉绀 {% if ordered_warranty %} 涓 {% endif %} 涔嬮棿鐨勬墍鏈夊唴瀹广 濡傛灉涓嶆槸妯℃澘绯荤粺涓嶄細鏄剧ず瀹冦傚畠褰撶劧涔熸敮鎸 {% else %} 浠ュ強鍏朵粬澶氱閫昏緫鍒ゆ柇鏂瑰紡銆
Finally, the second paragraph of this template has an example of a filter , with which you can alter the display of a variable. In this example, {{ ship_date|date:"F j, Y" }} , were passing the ship_date variable to the date filter, giving the date filter the argument "F j, Y" . The date filter formats dates in a given format, as specified by that argument. Filters are attached using a pipe character (| ), as a reference to Unix pipes.
鏈鍚庯紝杩欎釜妯℃澘鐨勭浜屾钀芥湁涓涓 filter 杩囨护鍣ㄧ殑渚嬪瓙,瀹冭兘璁╀綘鐢ㄦ潵杞崲鍙橀噺鐨勮緭鍑猴紝 鍦ㄨ繖涓緥瀛愪腑, {{ship_date|date:"F j, Y" }} 灏嗗彉閲 ship_date 鐢 date 杩囨护鍣ㄦ潵杞崲,杞崲鐨勫弬鏁版槸 "F j, Y" . date 杩囨护鍣ㄦ牴鎹寚瀹氱殑鍙傛暟杩涜鏍煎紡杈 鍑.杩囨护鍣ㄦ槸鐢ㄧ閬撳瓧绗( | )鏉ヨ皟鐢ㄧ殑,灏卞拰Unix绠¢亾涓鏍.
Each Django template has access to several built-in tags and filters, many of which are discussed in the sections that follow. Appendix F contains the full list of tags and filters, and its a good idea to familiarize yourself with that list so you know whats possible. Its also possible to create your own filters and tags, which we cover in Chapter 10.
Django 妯℃澘鍚湁寰堝鍐呯疆鐨則ags鍜宖ilters,鎴戜滑灏嗛檰缁繘琛屽涔. 闄勫綍F鍒楀嚭浜嗗緢澶氱殑tags鍜宖ilters鐨勫垪琛,鐔熸倝杩欎簺鍒楄〃瀵逛綘鏉ヨ鏄釜濂藉缓璁. 瀛︿範瀹岀鍗佺珷锛屼綘灏辨槑鐧芥庝箞鍘诲垱寤鸿嚜宸辩殑filters鍜宼ags浜.
To use the template system in Python code, just follow these two steps:
鎯宠鍦≒ython浠g爜涓娇鐢ㄦā鏉跨郴缁燂紝鍙渶閬靛惊涓嬮潰涓や釜姝ラ锛
Create a Template object by providing the raw template code as a string. Django also offers a way to create Template objects by designating the path to a template file on the filesystem; well examine that in a bit.
鍙互鐢ㄥ師濮嬬殑妯℃澘浠g爜瀛楃涓插垱寤轰竴涓 Template 瀵硅薄锛 Django鍚屾牱鏀寔鐢ㄦ寚瀹氭ā鏉挎枃浠惰矾寰勭殑鏂瑰紡鏉ュ垱寤 Template 瀵硅薄;
Call the render() method of the Template object with a given set of variables (i.e., the context). This returns a fully rendered template as a string, with all of the variables and block tags evaluated according to the context.
璋冪敤 Template 瀵硅薄鐨 render() 鏂规硶骞舵彁渚涚粰浠栧彉閲(i.e., 鍐呭). 瀹冨皢杩斿洖涓涓畬鏁寸殑妯℃澘瀛楃涓插唴瀹,鍖呭惈浜嗘墍鏈夋爣绛惧潡涓庡彉閲忚В鏋愬悗鐨勫唴瀹.
The following sections describe each step in more detail.
浠ヤ笅閮ㄥ垎閫愭鐨勮缁嗕粙缁
The easiest way to create a Template object is to instantiate it directly. The Template class lives in the django.template module, and the constructor takes one argument, the raw template code. Lets dip into the Python interactive interpreter to see how this works in code.
鍒涘缓涓涓 Template 瀵硅薄鏈绠鍗曠殑鏂规硶灏辨槸鐩存帴瀹炰緥鍖栧畠銆 Template 绫诲氨鍦 django.template 妯″潡涓紝鏋勯犲嚱鏁版帴鍙椾竴涓弬鏁帮紝鍘熷妯℃澘浠g爜銆傝鎴戜滑娣卞叆鎸栨帢涓涓 Python鐨勮В閲婂櫒鐪嬬湅瀹冩槸鎬庝箞宸ヤ綔鐨勩
Interactive Interpreter Examples
浜や簰寮忕ず渚
Throughout this book, we feature example Python interactive interpreter sessions. You can recognize these examples by the triple greater-than signs (>>> ), which designate the interpreters prompt. If youre copying examples from this book, dont copy those greater-than signs.
鍦ㄦ湰涔︿腑锛屾垜浠枩娆㈢敤鍜孭ython瑙i噴鍣ㄧ殑浜や簰鏉ヤ妇渚嬨 浣犲彲浠ラ氳繃涓変釜> ( >>> ) 璇嗗埆瀹冧滑锛屽畠浠浉褰撲簬Python瑙i噴鍣ㄧ殑鎻愮ず绗︺ 濡傛灉浣犺鎷疯礉渚嬪瓙锛岃涓嶈鎷疯礉杩3涓>瀛楃銆
Multiline statements in the interactive interpreter are padded with three dots (... ), for example:
澶氳璇彞鍒欏湪鍓嶉潰鍔犱簡3涓皬鏁扮偣(... )锛屼緥濡傦細
>>> print """This is a ... string that spans ... three lines.""" This is a string that spans three lines. >>> def my_function(value): ... print value >>> my_function('hello') hello
Those three dots at the start of the additional lines are inserted by the Python shelltheyre not part of our input. We include them here to be faithful to the actual output of the interpreter. If you copy our examples to follow along, dont copy those dots.
杩3涓偣鏄疨ython瑙i噴鍣ㄨ嚜鍔ㄥ姞鍏ョ殑锛屼笉闇瑕佷綘鐨勮緭鍏ャ傛垜浠寘鍚畠浠槸涓轰簡蹇犲疄鍛堢幇瑙i噴鍣ㄧ殑 鐪熷疄杈撳嚭銆傚悓鏍烽亾鐞嗭紝鎷疯礉鏃朵笉瑕佹嫹璐濊繖3涓皬鏁扮偣绗﹀彿銆
From within the project directory created by django-admin.py startproject (as covered in Chapter 2), type python manage.py shell to start the interactive interpreter. Heres a basic walk-through:
杞埌project鐩綍锛堝湪绗簩绔犵敱 django-admin.py startproject 鍛戒护鍒涘缓锛夛紝 杈撳叆鍛戒护 python manage.py shell 鍚姩浜や簰鐣岄潰銆備笅闈㈡槸涓浜涘熀鏈搷浣滐細
>>> from django.template import Template >>> t = Template("My name is {{ name }}.") >>> print t
If youre following along interactively, youll see something like this:
濡傛灉浣犺窡鎴戜滑涓璧峰仛锛屼綘灏嗕細鐪嬪埌涓嬮潰鐨勫唴瀹癸細
<django.template.Template object at 0xb7d5f24c>
That 0xb7d5f24c will be different every time, and it doesnt really matter; its simply the Python identity of the Template object.
0xb7d5f24c 姣忔閮戒細涓嶄竴鏍凤紝杩欐病浠涔堝叧绯伙紱杩欏彧鏄疨ython杩愯鏃 Template 瀵硅薄鐨処D銆
Django Settings
Django 璁剧疆
When using Django, you need to tell Django which settings to use. Interactively, this is typically done using python manage.py shell , but youve got a few other options described in Appendix E.
褰撲綘浣跨敤Django鏃讹紝浣犻渶瑕佸憡璇塂jango浣跨敤鍝釜閰嶇疆銆傚湪浜や簰妯″紡涓嬶紝閫氬父杩愯鍛戒护 python manage.py shell 鏉ュ仛杩欎釜锛岄檮褰旹閲岃繕鏈変竴浜涘叾浠栫殑涓浜涢夐」銆
When you create a Template object, the template system compiles the raw template code into an internal, optimized form, ready for rendering. But if your template code includes any syntax errors, the call to Template() will cause a TemplateSyntaxError exception:
褰撲綘鍒涘缓涓涓 Template 瀵硅薄锛屾ā鏉跨郴缁熷湪鍐呴儴缂栬瘧杩欎釜妯℃澘鍒板唴閮ㄦ牸寮忥紝骞跺仛浼樺寲锛屽仛濂 娓叉煋鐨勫噯澶囥傚鏋滀綘鐨勬ā鏉胯娉曟湁閿欒锛岄偅涔堝湪璋冪敤 Template() 鏃跺氨浼氭姏鍑 TemplateSyntaxError 寮傚父锛
>>> from django.template import Template >>> t = Template('{% notatag %} ') Traceback (most recent call last): File "<stdin>", line 1, in ? ... django.template.TemplateSyntaxError: Invalid block tag: 'notatag'
The system raises a TemplateSyntaxError exception for any of the following cases:
绯荤粺浼氬湪涓嬮潰鐨勬儏褰㈡姏鍑 TemplateSyntaxError 寮傚父锛
Invalid block tags
鏃犳晥鐨勫潡鏍囩
Invalid arguments to valid block tags
鏃犳晥鐨勫弬鏁
Invalid filters
鏃犳晥鐨勮繃婊ゅ櫒
Invalid arguments to valid filters
杩囨护鍣ㄧ殑鍙傛暟鏃犳晥
Invalid template syntax
鏃犳晥鐨勬ā鏉胯娉
Unclosed block tags (for block tags that require closing tags)
鏈皝闂殑鍧楁爣绛 锛堥拡瀵归渶瑕佸皝闂殑鍧楁爣绛撅級
Once you have a Template object, you can pass it data by giving it a context . A context is simply a set of variables and their associated values. A template uses this to populate its variable tags and evaluate its block tags.
涓鏃︿綘鍒涘缓涓涓 Template 瀵硅薄锛屼綘鍙互鐢 context 鏉ヤ紶閫掓暟鎹粰瀹冦 涓涓猚ontext鏄竴绯诲垪鍙橀噺鍜屽畠浠肩殑闆嗗悎銆傛ā鏉夸娇鐢ㄥ畠鏉ヨ祴鍊兼ā鏉垮彉閲忔爣绛惧拰 鎵ц鍧楁爣绛俱
A context is represented in Django by the Context class, which lives in the django.template module. Its constructor takes one optional argument: a dictionary mapping variable names to variable values. Call the Template objects render() method with the context to fill the template:
context鍦―jango閲岃〃鐜颁负 Context 绫伙紝鍦 django.template 妯″潡閲屻 瀹冩瀯閫犳槸鏈変竴涓彲閫夊弬鏁帮細涓涓瓧鍏告槧灏勫彉閲忓拰瀹冧滑鐨勫笺傝皟鐢 Template 瀵硅薄 鐨 render() 鏂规硶骞朵紶閫抍ontext鏉ュ~鍏呮ā鏉匡細
>>> from django.template import Context, Template >>> t = Template("My name is {{ name }}.") >>> c = Context({"name": "Stephane"}) >>> t.render(c) 'My name is Stephane.'
Dictionaries and Contexts
瀛楀吀鍜孋ontexts
A Python dictionary is a mapping between known keys and variable values. A Context is similar to a dictionary, but a Context provides additional functionality, as covered in Chapter 10.
Python鐨勫瓧鍏告暟鎹被鍨嬪氨鏄叧閿瓧鍜屽畠浠肩殑涓涓槧灏勩 Context 鍜屽瓧鍏稿緢绫讳技锛 Context 杩樻彁渚涙洿澶氱殑鍔熻兘锛岃鐪嬬鍗佺珷銆
Variable names must begin with a letter (A-Z or a-z) and may contain digits, underscores, and dots. (Dots are a special case well get to in a moment.) Variable names are case sensitive.
鍙橀噺鍚嶅繀椤荤敱鑻辨枃瀛楃寮濮 锛圓-Z鎴朼-z锛夊苟鍙互鍖呭惈鏁板瓧瀛楃銆佷笅鍒掔嚎鍜屽皬鏁扮偣銆 锛堝皬鏁扮偣鍦ㄨ繖閲屾湁鐗瑰埆鐨勭敤閫旓紝绋嶅悗鎴戜滑浼氳鍒帮級鍙橀噺鏄ぇ灏忓啓鏁忔劅鐨勩
Heres an example of template compilation and rendering, using the sample template from the beginning of this chapter:
涓嬮潰鏄紪鍐欐ā鏉垮苟娓叉煋鐨勭ず渚嬶細
>>> from django.template import Template, Context >>> raw_template = """<p>Dear {{ person_name }},</p> ... ... <p>Thanks for ordering {{ product }} from {{ company }}. It's scheduled ... to ship on {{ ship_date|date:"F j, Y" }}.</p> ... ... {% if ordered_warranty %} ... <p>Your warranty information will be included in the packaging.</p> ... {% endif %} ... ... <p>Sincerely,<br />{{ company }}</p>""" >>> t = Template(raw_template) >>> import datetime >>> c = Context({'person_name': 'John Smith', ... 'product': 'Super Lawn Mower', ... 'company': 'Outdoor Equipment', ... 'ship_date': datetime.date(2009, 4, 2), ... 'ordered_warranty': True}) >>> t.render(c) "<p>Dear John Smith,</p>\n\n<p>Thanks for ordering Super Lawn Mower from Outdoor Equipment. It's scheduled \nto ship on April 2, 2009.</p>\n\n\n <p>Your warranty information will be included in the packaging.</p>\n\n\n <p>Sincerely,<br />Outdoor Equipment</p>"
Lets step through this code one statement at a time:
璁╂垜浠愬彞鐪嬬湅杩欐浠g爜锛
First, we import the classes Template and Context , which both live in the module django.template .
棣栧厛鎴戜滑瀵煎叆 锛坕mport锛夌被 Template 鍜 Context 锛屽畠浠兘鍦ㄦā鍧 django.template 閲屻
We save the raw text of our template into the variable raw_template . Note that we use triple quote marks to designate the string, because it wraps over multiple lines; in Python codde, strings designated with single quote marks cannot be wrapped over multiple lines.
鎴戜滑鎶婃ā鏉垮師濮嬫枃鏈繚瀛樺埌鍙橀噺 raw_template 銆傛敞鎰忓埌鎴戜滑浣跨敤浜嗕笁涓紩鍙锋潵 鏍囪瘑杩欎簺鏂囨湰锛屽洜涓鸿繖鏍峰彲浠ュ寘鍚琛屻傝繖鏄疨ython鐨勪竴涓娉曘
Next, we create a template object, t , by passing raw_template to the Template class constructor.
鎺ヤ笅鏉ワ紝鎴戜滑鍒涘缓浜嗕竴涓ā鏉垮璞 t 锛屾妸 raw_template 浣滀负 Template 绫 鐨勬瀯閫犵殑鍙傛暟銆
We import the datetime module from Pythons standard library, because well need it in the following statement.
鎴戜滑浠嶱ython鐨勬爣鍑嗗簱瀵煎叆 datetime 妯″潡锛屼互鍚庢垜浠皢浼氫娇鐢ㄥ畠銆
Then, we create a Context object, c . The Context constructor takes a Python dictionary, which maps variable names to values. Here, for example, we specify that the person_name is 'John Smith' , product is 'Super Lawn Mower' , and so forth.
鐒跺悗锛屾垜浠垱寤轰竴涓 Context 瀵硅薄锛 c 銆 Context 鏋勯犵殑鍙傛暟鏄疨ython 瀛楀吀鏁版嵁绫诲瀷锛屽湪杩欓噷锛屾垜浠粰鐨勫弬鏁版槸 person_name 鍊间负 'John Smith' , product 鍊间负 'Super Lawn Mower' 锛岀瓑绛夈
Finally, we call the render() method on our template object, passing it the context. This returns the rendered templatethat is, it replaces template variables with the actual values of the variables, and it executes any block tags.
鏈鍚庯紝鎴戜滑鍦ㄦā鏉垮璞′笂璋冪敤 render() 鏂规硶锛屼紶閫 context鍙傛暟缁欏畠銆 杩欐槸杩斿洖娓叉煋鍚庣殑妯℃澘鐨勬柟娉曪紝瀹冧細鏇挎崲妯℃澘鍙橀噺涓虹湡瀹炵殑鍊煎拰鎵ц鍧楁爣绛俱
Note that the warranty paragraph was displayed because the ordered_warranty variable evaluated to True . Also note the date, April 2, 2009 , which is displayed according to the format string 'F j, Y' . (We explain format strings for the date filter shortly.)
娉ㄦ剰锛寃arranty paragraph鏄剧ず鏄洜涓 ordered_warranty 鐨勫间负 True . 娉ㄦ剰鏃堕棿鐨勬樉绀猴紝 April 2, 2009 , 瀹冩槸鎸 'F j, Y' 鏍煎紡鏄剧ず鐨勩 锛堟垜浠緢蹇氨浼氬湪 date 杩囨护鍣ㄨВ閲婅繖浜涙牸寮忥級
If youre new to Python, you may wonder why this output includes newline characters ('\n' ) rather than displaying the line breaks. Thats happening because of a subtlety in the Python interactive interpreter: the call to t.render(c) returns a string, and by default the interactive interpreter displays the representation of the string, rather than the printed value of the string. If you want to see the string with line breaks displayed as true line breaks rather than '\n' characters, use the print statement: print t.render(c) .
濡傛灉浣犳槸Python鍒濆鑰咃紝浣犲彲鑳藉湪鎯充负浠涔堣緭鍑洪噷鏈夊洖杞︽崲琛岀殑瀛楃('\n' )鑰屼笉鏄 鏄剧ず鍥炶溅鎹㈣锛熷洜涓鸿繖鏄疨ython浜や簰瑙i噴鍣ㄧ殑缂樻晠锛氳皟鐢 t.render(c) 杩斿洖瀛楃涓诧紝 瑙i噴鍣ㄧ己鐪佹樉绀鸿繖浜涘瓧绗︿覆鐨 鐪熷疄鍐呭鍛堢幇 锛岃屼笉鏄墦鍗拌繖涓彉閲忕殑鍊笺 瑕佹樉绀烘崲琛岃屼笉鏄 '\n' 锛屼娇鐢 print 璇彞锛 print t.render(c) 銆
Those are the fundamentals of using the Django template system: just write a template, create a Template object, create a Context , and call the render() method.
杩欏氨鏄娇鐢―jango妯℃澘绯荤粺鐨勫熀鏈鍒欙細鍐欐ā鏉匡紝鍒涘缓 Template 瀵硅薄锛屽垱寤 Context 锛 璋冪敤 render() 鏂规硶銆
Once you have a Template object, you can render multiple contexts through it, for example:
涓鏃︽湁浜 妯℃澘 瀵硅薄锛屼綘灏卞彲浠ラ氳繃瀹冩覆鏌撳涓儗鏅紙context锛夛紝渚嬪锛
>>> from django.template import Template, Context >>> t = Template('Hello, {{ name }}') >>> print t.render(Context({'name': 'John'})) Hello, John >>> print t.render(Context({'name': 'Julie'})) Hello, Julie >>> print t.render(Context({'name': 'Pat'})) Hello, Pat
Whenever youre using the same template source to render multiple contexts like this, its more efficient to create the Template object once , and then call render() on it multiple times:
鏃犺浣曟椂鍍忚繖鏍蜂娇鐢ㄥ悓涓妯℃澘婧愭覆鏌撳涓儗鏅紝鍙垱寤 涓娆 妯℃澘 瀵硅薄锛岀劧鍚庡瀹冨娆¤皟鐢 render() 灏嗕細鏇村姞楂樻晥銆
# Bad for name in ('John', 'Julie', 'Pat'): t = Template('Hello, {{ name }}') print t.render(Context({'name': name})) # Good t = Template('Hello, {{ name }}') for name in ('John', 'Julie', 'Pat'): print t.render(Context({'name': name}))
Djangos template parsing is quite fast. Behind the scenes, most of the parsing happens via a single call to a short regular expression. This is in stark contrast to XML-based template engines, which incur the overhead of an XML parser and tend to be orders of magnitude slower than Djangos template rendering engine.
Django 妯℃澘瑙f瀽闈炲父蹇嵎銆傚ぇ閮ㄥ垎鐨勮В鏋愬伐浣滈兘鏄湪鍚庡彴閫氳繃瀵圭畝鐭鍒欒〃杈惧紡涓娆℃ц皟鐢ㄦ潵瀹屾垚銆傝繖鍜屽熀浜 XML 鐨勬ā鏉垮紩鎿庡舰鎴愰矞鏄庡姣旓紝閭d簺寮曟搸鎵挎媴浜 XML 瑙f瀽鍣ㄧ殑寮閿锛屼笖寰寰姣 Django 妯℃澘娓叉煋寮曟搸瑕佹參涓婂嚑涓暟閲忕骇銆
In the examples so far, weve passed simple values in the contextsmostly strings, plus a datetime.date example. However, the template system elegantly handles more complex data structures, such as lists, dictionaries, and custom objects.
鍦ㄥ埌鐩墠涓烘鐨勪緥瀛愪腑锛屾垜浠氳繃 context 浼犻掔殑绠鍗曞弬鏁板间富瑕佹槸瀛楃涓诧紝杩樻湁涓涓 datetime.date 鑼冧緥銆傜劧鑰岋紝妯℃澘绯荤粺鑳藉闈炲父绠娲佸湴澶勭悊鏇村姞澶嶆潅鐨勬暟鎹粨鏋勶紝渚嬪list銆乨ictionary鍜岃嚜瀹氫箟鐨勫璞°
The key to traversing complex data structures in Django templates is the dot character (. ). Use a dot to access dictionary keys, attributes, indices, or methods of an object.
鍦 Django 妯℃澘涓亶鍘嗗鏉傛暟鎹粨鏋勭殑鍏抽敭鏄彞鐐瑰瓧绗 (.)銆備娇鐢ㄥ彞鐐瑰彲浠ヨ闂瓧鍏哥殑閿笺佸睘鎬с佺储寮曞拰瀵硅薄鐨勬柟娉曘
This is best illustrated with a few examples. For instance, suppose youre passing a Python dictionary to a template. To access the values of that dictionary by dictionary key, use a dot:
鏈濂芥槸鐢ㄥ嚑涓緥瀛愭潵璇存槑涓涓嬨傛瘮濡傦紝鍋囪浣犺鍚戞ā鏉夸紶閫掍竴涓 Python 瀛楀吀銆傝閫氳繃瀛楀吀閿闂瀛楀吀鐨勫硷紝鍙娇鐢ㄤ竴涓彞鐐癸細
>>> from django.template import Template, Context >>> person = {'name': 'Sally', 'age': '43'} >>> t = Template('{{ person.name }} is {{ person.age }} years old.') >>> c = Context({'person': person}) >>> t.render(c) 'Sally is 43 years old.'
Similarly, dots also allow access of object attributes. For example, a Python datetime.date object has year , month , and day attributes, and you can use a dot to access those attributes in a Django template:
鍚屾牱锛屼篃鍙互閫氳繃鍙ョ偣鏉ヨ闂璞$殑灞炴с傛瘮鏂硅锛 Python 鐨 datetime.date 瀵硅薄鏈 year 銆 month 鍜 day 鍑犱釜灞炴э紝浣犲悓鏍峰彲浠ュ湪妯℃澘涓娇鐢ㄥ彞鐐规潵璁块棶杩欎簺灞炴э細
>>> from django.template import Template, Context >>> import datetime >>> d = datetime.date(1993, 5, 2) >>> d.year 1993 >>> d.month 5 >>> d.day 2 >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.') >>> c = Context({'date': d}) >>> t.render(c) 'The month is 5 and the year is 1993.'
This example uses a custom class:
涓嬩緥浣跨敤浜嗕竴涓嚜瀹氫箟绫伙細
>>> from django.template import Template, Context >>> class Person(object): ... def __init__(self, first_name, last_name): ... self.first_name, self.last_name = first_name, last_name >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.') >>> c = Context({'person': Person('John', 'Smith')}) >>> t.render(c) 'Hello, John Smith.'
Dots are also used to call methods on objects. For example, each Python string has the methods upper() and isdigit() , and you can call those in Django templates using the same dot syntax:
鍙ョ偣杩樼敤浜庤皟鐢ㄥ璞$殑鏂规硶銆備緥濡傦紝姣忎釜 Python 瀛楃涓查兘鏈 upper() 鍜 isdigit() 鏂规硶锛屼綘鍦ㄦā鏉夸腑鍙互浣跨敤鍚屾牱鐨勫彞鐐硅娉曟潵璋冪敤瀹冧滑锛
>>> from django.template import Template, Context >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}') >>> t.render(Context({'var': 'hello'})) 'hello -- HELLO -- False' >>> t.render(Context({'var': '123'})) '123 -- 123 -- True'
Note that you dont include parentheses in the method calls. Also, its not possible to pass arguments to the methods; you can only call methods that have no required arguments. (We explain this philosophy later in this chapter.)
娉ㄦ剰浣犱笉鑳藉湪鏂规硶璋冪敤涓娇鐢ㄥ渾鎷彿銆傝屼笖涔熸棤娉曠粰璇ユ柟娉曚紶閫掑弬鏁帮紱浣犲彧鑳借皟鐢ㄤ笉闇鍙傛暟鐨勬柟娉曘傦紙鎴戜滑灏嗗湪鏈珷绋嶅悗閮ㄥ垎瑙i噴璇ヨ璁¤銆傦級
Finally, dots are also used to access list indices, for example:
鏈鍚庯紝鍙ョ偣涔熷彲鐢ㄤ簬璁块棶鍒楄〃绱㈠紩锛屼緥濡傦細
>>> from django.template import Template, Context >>> t = Template('Item 2 is {{ items.2 }}.') >>> c = Context({'items': ['apples', 'bananas', 'carrots']}) >>> t.render(c) 'Item 2 is carrots.'
Negative list indices are not allowed. For example, the template variable {{ items.-1 }} would cause a TemplateSyntaxError .
TemplateSyntaxError 寮傚父銆
Python Lists
Python 鍒楄〃绫诲瀷
Python lists have 0-based indices so that the first item is at index 0, the second is at index 1, and so on.
Python鍒楄〃绫诲瀷鐨勭储寮曟槸浠0寮濮嬬殑锛岀涓涓厓绱犵殑绱㈠紩鏄0锛岀浜屼釜鏄1锛屼互姝ょ被鎺ㄣ
The dot lookups can be summarized like this: when the template system encounters a dot in a variable name, it tries the following lookups, in this order:
鍙ョ偣鏌ユ壘瑙勫垯鍙鎷负锛氬綋妯℃澘绯荤粺鍦ㄥ彉閲忓悕涓亣鍒扮偣鏃讹紝鎸夌収浠ヤ笅椤哄簭灏濊瘯杩涜鏌ユ壘锛
Dictionary lookup (e.e., foo["bar"] )
瀛楀吀鏌ユ壘 锛堟瘮濡 foo["bar"] )
Attribute lookup (e.g., foo.bar )
灞炴ф煡鎵 (姣斿 foo.bar )
Method call (e.g., foo.bar() )
鏂规硶璋冪敤 锛堟瘮濡 foo.bar() )
List-index lookup (e.g., foo[bar] )
鍒楄〃绫诲瀷绱㈠紩鏌ユ壘 (姣斿 foo[bar] )
The system uses the first lookup type that works. Its short-circuit logic.
绯荤粺浣跨敤鎵鎵惧埌鐨勭涓涓湁鏁堢被鍨嬨傝繖鏄竴绉嶇煭璺昏緫銆
Dot lookups can be nested multiple levels deep. For instance, the following example uses {{ person.name.upper }} , which translates into a dictionary lookup (person['name'] ) and then a method call (upper() ):
鍙ョ偣鏌ユ壘鍙互澶氱骇娣卞害宓屽銆備緥濡傚湪涓嬮潰杩欎釜渚嬪瓙涓 {{person.name.upper}} 浼氳浆鎹㈡垚瀛楀吀绫诲瀷鏌ユ壘锛 person['name'] ) 鐒跺悗鏄柟娉曡皟鐢紙 upper() ):
>>> from django.template import Template, Context >>> person = {'name': 'Sally', 'age': '43'} >>> t = Template('{{ person.name.upper }} is {{ person.age }} years old.') >>> c = Context({'person': person}) >>> t.render(c) 'SALLY is 43 years old.'
Method calls are slightly more complex than the other lookup types. Here are some things to keep in mind:
鏂规硶璋冪敤姣斿叾浠栫被鍨嬬殑鏌ユ壘鐣ヤ负澶嶆潅涓鐐广備互涓嬫槸涓浜涙敞鎰忎簨椤癸細
If, during the method lookup, a method raises an exception, the exception will be propagated, unless the exception has an attribute silent_variable_failure whose value is True . If the exception does have a silent_variable_failure attribute, the variable will render as an empty string, for example:
鍦ㄦ柟娉曟煡鎵捐繃绋嬩腑锛屽鏋滄煇鏂规硶鎶涘嚭涓涓紓甯革紝闄ら潪璇ュ紓甯告湁涓涓 silent_variable_failure 灞炴у苟涓斿间负 True 锛屽惁鍒欑殑璇濆畠灏嗚浼犳挱銆傚鏋滆寮傚父 纭湁 灞炴 silent_variable_failure 锛岄偅涔堬紙鎵鏌ユ壘锛夊彉閲忓皢琚覆鏌撲负绌哄瓧绗︿覆锛屼緥濡傦細
>>> t = Template("My name is {{ person.first_name }}.") >>> class PersonClass3: ... def first_name(self): ... raise AssertionError, "foo" >>> p = PersonClass3() >>> t.render(Context({"person": p})) Traceback (most recent call last): ... AssertionError: foo >>> class SilentAssertionError(AssertionError): ... silent_variable_failure = True >>> class PersonClass4: ... def first_name(self): ... raise SilentAssertionError >>> p = PersonClass4() >>> t.render(Context({"person": p})) "My name is ."
A method call will only work if the method has no required arguments. Otherwise, the system will move to the next lookup type (list-index lookup).
浠呭湪鏂规硶鏃犻渶浼犲叆鍙傛暟鏃讹紝鍏惰皟鐢ㄦ墠鏈夋晥銆傚惁鍒欙紝绯荤粺灏嗕細杞Щ鍒颁笅涓涓煡鎵剧被鍨嬶紙鍒楄〃绱㈠紩鏌ユ壘锛夈
Obviously, some methods have side effects, and it would be foolish at best, and possibly even a security hole, to allow the template system to access them.
鏄剧劧锛屾湁浜涙柟娉曟槸鏈夊壇浣滅敤鐨勶紝濂界殑鎯呭喌涓嬪厑璁告ā鏉跨郴缁熻闂畠浠彲鑳藉彧鏄共浠惰牏浜嬶紝鍧忕殑鎯呭喌涓嬬敋鑷充細寮曞彂瀹夊叏婕忔礊銆
Say, for instance, you have a BankAccount object that has a delete() method. A template shouldnt be allowed to include something like {{ account.delete }} .
渚嬪锛屼綘鐨勪竴涓 BankAccount 瀵硅薄鏈変竴涓 delete() 鏂规硶銆備笉搴旇鍏佽妯℃澘鍖呭惈鍍 {{account.delete}} 杩欐牱鐨勬柟娉曡皟鐢ㄣ
To prevent this, set the function attribute alters_data on the method:
瑕侀槻姝㈣繖鏍风殑浜嬫儏鍙戠敓锛屽繀椤昏缃鏂规硶鐨 alters_data 鍑芥暟灞炴э細
def delete(self): # Delete the account delete.alters_data = True
The template system wont execute any method marked in this way. In other words, if a template includes {{ account.delete }} , that tag will not execute the delete() method. It will fail silently.
妯℃澘绯荤粺涓嶄細鎵ц浠讳綍浠ヨ鏂瑰紡杩涜鏍囪鐨勬柟娉曘備篃灏辨槸璇达紝濡傛灉妯℃澘鍖呭惈浜 {{account.delete}} ,璇ユ爣绛句笉浼氳皟鐢 delete() 鏂规硶銆傚畠鍙細瀹夐潤鍦板け璐ワ紙骞朵笉浼氬紩鍙戝紓甯革級銆
By default, if a variable doesnt exist, the template system renders it as an empty string, failing silently, for example:
榛樿鎯呭喌涓嬶紝濡傛灉涓涓彉閲忎笉瀛樺湪锛屾ā鏉跨郴缁熶細鎶婂畠灞曠ず涓虹┖瀛楃涓诧紝涓嶅仛浠讳綍浜嬫儏鍦拌〃绀哄け璐ワ紝渚嬪锛
>>> from django.template import Template, Context >>> t = Template('Your name is {{ name }}.') >>> t.render(Context()) 'Your name is .' >>> t.render(Context({'var': 'hello'})) 'Your name is .' >>> t.render(Context({'NAME': 'hello'})) 'Your name is .' >>> t.render(Context({'Name': 'hello'})) 'Your name is .'
The system fails silently rather than raising an exception because its intended to be resilient to human error. In this case, all of the lookups failed because variable names have the wrong case or name. In the real world, its unacceptable for a Web site to become inaccessible due to a small template syntax error.
绯荤粺闈欐倓鎮勫湴琛ㄧず澶辫触锛岃屼笉鏄紩鍙戜竴涓紓甯革紝鍥犱负杩欓氬父鏄汉涓洪敊璇犳垚鐨勩傝繖绉嶆儏鍐典笅锛屽洜涓哄彉閲忓悕鏈夐敊璇殑鐘跺喌鎴栧悕绉帮紝 鎵鏈夌殑鏌ヨ閮戒細澶辫触銆傜幇瀹炰笘鐣屼腑锛屽浜庝竴涓獁eb绔欑偣鏉ヨ锛屽鏋滀粎浠呭洜涓轰竴涓皬鐨勬ā鏉胯娉曢敊璇岄犳垚鏃犳硶璁块棶锛岃繖鏄笉鍙帴鍙楃殑銆
Note that its possible to change Djangos default behavior in this regard, by tweaking a setting in your Django configuration. We discuss this further in Chapter 10.
娉ㄦ剰锛屾垜浠槸鍙互鏈夋満浼氶氳繃鏇存敼Django鐨勯厤缃互鍦ㄨ繖鐐逛笂鏀瑰彉Django鐨勯粯璁よ涓虹殑銆 鎴戜滑浼氬湪绗10绔犺繘琛岃繘涓姝ョ殑璁ㄨ鐨勩
Most of the time, youll instantiate Context objects by passing in a fully populated dictionary to Context() . But you can add and delete items from a Context object once its been instantiated, too, using standard Python dictionary syntax:
澶氭暟鏃堕棿锛屼綘鍙互閫氳繃浼犻掍竴涓畬鍏ㄥ~鍏(full populated)鐨勫瓧鍏哥粰 Context() 鏉ュ垵濮嬪寲 涓婁笅鏂(Context) 銆 浣嗘槸鍒濆鍖栦互鍚庯紝浣犱篃鍙互浠巂`涓婁笅鏂(Context)`` 瀵硅薄娣诲姞鎴栬呭垹闄ゆ潯鐩紝浣跨敤鏍囧噯鐨凱ython瀛楀吀璇硶(syntax):
>>> from django.template import Context >>> c = Context({"foo": "bar"}) >>> c['foo'] 'bar' >>> del c['foo'] >>> c['foo'] '' >>> c['newvariable'] = 'hello' >>> c['newvariable'] 'hello'
As weve mentioned already, the template system ships with built-in tags and filters. The sections that follow provide a rundown of the most common tags and filters.
鍍忔垜浠互鍓嶆彁鍒拌繃鐨勶紝妯℃澘绯荤粺甯︽湁鍐呯疆鐨勬爣绛惧拰杩囨护鍣ㄣ 涓嬮潰鐨勭珷鑺傛彁渚涗簡涓涓鏁伴氱敤鏍囩鍜岃繃婊ゅ櫒鐨勭畝瑕佽鏄庛
The {% if %} tag evaluates a variable, and if that variable is true (i.e., it exists, is not empty, and is not a false Boolean value), the system will display everything between {% if %} and {% endif %} , for example:
{% if %} 鏍囩妫鏌(evaluate)涓涓彉閲忥紝濡傛灉杩欎釜鍙橀噺涓虹湡锛堝嵆锛屽彉閲忓瓨鍦紝闈炵┖锛屼笉鏄竷灏斿煎亣锛夛紝绯荤粺浼氭樉绀哄湪 {% if %} 鍜 {% endif %} 涔嬮棿鐨勪换浣曞唴瀹癸紝渚嬪锛
{% if today_is_weekend %} <p>Welcome to the weekend!</p> {% endif %}
An {% else %} tag is optional:
{% else %} 鏍囩鏄彲閫夌殑锛
{% if today_is_weekend %} <p>Welcome to the weekend!</p> {% else %} <p>Get back to work.</p> {% endif %}
Python Truthiness
Python 鐨勨滅湡鍊尖
In Python, the empty list ([] ), tuple (() ), dictionary ({} ), string ('' ), zero (0 ), and the special object None are False in a Boolean context. Everything else is True .
鍦╬ython涓┖鐨勫垪琛 ( [] )锛宼uple( () )锛屽瓧鍏( {} )锛屽瓧绗︿覆( '' )锛岄浂( 0 )锛岃繕鏈 None 瀵硅薄锛屽湪閫昏緫鍒ゆ柇涓兘涓哄亣锛屽叾浠栫殑鎯呭喌閮戒负鐪熴
The {% if %} tag accepts and , or , or not for testing multiple variables, or to negate a given variable. For example:
{% if %} 鏍囩鎺ュ彈 and 锛 or 鎴栬 not 鍏抽敭瀛楁潵瀵瑰涓彉閲忓仛鍒ゆ柇 锛屾垨鑰呭鍙橀噺鍙栧弽锛 not )锛屼緥濡傦細
{% if athlete_list and coach_list %} Both athletes and coaches are available. {% endif %} {% if not athlete_list %} There are no athletes. {% endif %} {% if athlete_list or coach_list %} There are some athletes or some coaches. {% endif %} {% if not athlete_list or coach_list %} There are no athletes or there are some coaches. (OK, so writing English translations of Boolean logic sounds stupid; it's not our fault.) {% endif %} {% if athlete_list and not coach_list %} There are some athletes and absolutely no coaches. {% endif %}
{% if %} tags dont allow and and or clauses within the same tag, because the order of logic would be ambiguous. For example, this is invalid:
{% if %} 鏍囩涓嶅厑璁稿湪鍚屼竴涓爣绛句腑鍚屾椂浣跨敤 and 鍜 or 锛屽洜涓洪昏緫涓婂彲鑳芥ā绯婄殑锛屼緥濡傦紝濡備笅绀轰緥鏄敊璇殑锛
{% if athlete_list and coach_list or cheerleader_list %}
The use of parentheses for controlling order of operations is not supported. If you find yourself needing parentheses, consider performing logic in the view code in order to simplify the templates. Even so, if you need to combine and and or to do advanced logic, just use nested {% if %} tags, for example:
绯荤粺涓嶆敮鎸佺敤鍦嗘嫭鍙锋潵缁勫悎姣旇緝鎿嶄綔銆傚鏋滀綘鍙戠幇闇瑕佺粍鍚堟搷浣滐紝浣犲彲浠ヨ冭檻鐢ㄩ昏緫璇彞鏉ョ畝鍖 妯℃澘鐨勫鐞嗐備緥濡傦紝浣犻渶瑕佺粍鍚 and 鍜 or 鍋氫簺澶嶆潅閫昏緫鍒ゆ柇锛屽彲浠ヤ娇鐢ㄥ祵濂楃殑 {% if %} 鏍囩锛岀ず渚嬪涓嬶細
{% if athlete_list %} {% if coach_list or cheerleader_list %} We have athletes, and either coaches or cheerleaders! {% endif %} {% endif %}
Multiple uses of the same logical operator are fine, but you cant combine different operators. For example, this is valid:
澶氭浣跨敤鍚屼竴涓昏緫鎿嶄綔绗︽槸娌℃湁闂鐨勶紝浣嗘槸鎴戜滑涓嶈兘鎶婁笉鍚岀殑鎿嶄綔绗︾粍鍚堣捣鏉ャ傛瘮濡傝繖鏍风殑浠g爜鏄病闂鐨勶細
{% if athlete_list or coach_list or parent_list or teacher_list %}
There is no {% elif %} tag. Use nested {% if %} tags to accomplish the same thing:
骞舵病鏈 {% elif %} 鏍囩锛岃浣跨敤宓屽鐨 {% if %} 鏍囩鏉ヨ揪鎴愬悓鏍风殑鏁堟灉锛
{% if athlete_list %} <p>Here are the athletes: {{ athlete_list }}.</p> {% else %} <p>No athletes are available.</p> {% if coach_list %} <p>Here are the coaches: {{ coach_list }}.</p> {% endif %} {% endif %}
Make sure to close each {% if %} with an {% endif %} . Otherwise, Django will throw a TemplateSyntaxError .
涓瀹氳鐢 {% endif %} 鍏抽棴姣忎竴涓 {% if %} 鏍囩銆傚惁鍒橠jango浼氭姏鍑 TemplateSyntaxError 銆
The {% for %} tag allows you to loop over each item in a sequence. As in Pythons for statement, the syntax is for X in Y , where Y is the sequence to loop over and X is the name of the variable to use for a particular cycle of the loop. Each time through the loop, the template system will render everything between {% for %} and {% endfor %} .
{% for %} 鍏佽鎴戜滑鍦ㄤ竴涓簭鍒椾笂杩唬銆備笌Python鐨 for 璇彞鐨勬儏褰㈢被浼硷紝寰幆璇硶鏄 for X in Y 锛孻鏄杩唬鐨勫簭鍒楄孹鏄湪姣忎竴涓壒瀹氱殑寰幆涓娇鐢ㄧ殑鍙橀噺鍚嶇О銆傛瘡涓娆″惊鐜腑锛屾ā鏉跨郴缁熶細娓叉煋鍦 {% for %} 鍜 {% endfor %} 涔嬮棿鐨勬墍鏈夊唴瀹广
For example, you could use the following to display a list of athletes given a variable athlete_list :
渚嬪锛岀粰瀹氫竴涓繍鍔ㄥ憳鍒楄〃 athlete_list 鍙橀噺锛屾垜浠彲浠ヤ娇鐢ㄤ笅闈㈢殑浠g爜鏉ユ樉绀鸿繖涓垪琛細
<ul> {% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% endfor %} </ul>
Add reversed to the tag to loop over the list in reverse:
缁欐爣绛惧鍔犱竴涓 reversed 浣垮緱璇ュ垪琛ㄨ鍙嶅悜杩唬锛
{% for athlete in athlete_list reversed %} ... {% endfor %}
Its possible to nest {% for %} tags:
鍙互宓屽浣跨敤 {% for %} 鏍囩锛
{% for country in countries %} <h1>{{ country.name }}</h1> <ul> {% for city in country.city_list %} <li>{{ city }}</li> {% endfor %} </ul> {% endfor %}
There is no support for breaking out of a loop before the loop is finished. If you want to accomplish this, change the variable youre looping over so that it includes only the values you want to loop over. Similarly, there is no support for a continue statement that would instruct the loop processor to return immediately to the front of the loop. (See the section Philosophies and Limitations later in this chapter for the reasoning behind this design decision.)
Django涓嶆敮鎸侀鍑哄惊鐜搷浣溿傚鏋滄垜浠兂閫鍑哄惊鐜紝鍙互鏀瑰彉姝e湪杩唬鐨勫彉閲忥紝璁╁叾浠呬粎鍖呭惈闇瑕佽凯浠g殑椤圭洰銆傚悓鐞嗭紝Django涔熶笉鏀寔continue璇彞锛屾垜浠棤娉曡褰撳墠杩唬鎿嶄綔璺冲洖鍒板惊鐜ご閮ㄣ傦紙璇峰弬鐪嬫湰绔犵◢鍚庣殑鐞嗗康鍜岄檺鍒跺皬鑺傦紝浜嗚В涓嬪喅瀹氳繖涓璁$殑鑳屽悗鍘熷洜锛
The {% for %} tag sets a magic forloop template variable within the loop. This variable has a few attributes that give you information about the progress of the loop:
{% for %} 鏍囩鍦ㄥ惊鐜腑璁剧疆浜嗕竴涓壒娈婄殑 forloop 妯℃澘鍙橀噺銆傝繖涓彉閲忚兘鎻愪緵涓浜涘綋鍓嶅惊鐜繘灞曠殑淇℃伅锛
forloop.counter is always set to an integer representing the number of times the loop has been entered. This is one-indexed, so the first time through the loop, forloop.counter will be set to 1 . Heres an example:
forloop.counter 鎬绘槸涓涓〃绀哄綋鍓嶅惊鐜殑鎵ц娆℃暟鐨勬暣鏁拌鏁板櫒銆傝繖涓鏁板櫒鏄粠1寮濮嬬殑锛屾墍浠ュ湪绗竴娆″惊鐜椂 forloop.counter 灏嗕細琚缃负1銆備緥瀛愬涓嬶細
{% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %}
forloop.counter0 is like forloop.counter , except its zero-indexed. Its value will be set to 0 the first time through the loop.
forloop.counter0 绫讳技浜 forloop.counter 锛屼絾鏄畠鏄粠0璁℃暟鐨勩傜涓娆℃墽琛屽惊鐜椂杩欎釜鍙橀噺浼氳璁剧疆涓0銆
forloop.revcounter is always set to an integer representing the number of remaining items in the loop. The first time through the loop, forloop.revcounter will be set to the total number of items in the sequence youre traversing. The last time through the loop, forloop.revcounter will be set to 1 .
forloop.revcounter 鏄〃绀哄惊鐜腑鍓╀綑椤圭殑鏁村瀷鍙橀噺銆傚湪寰幆鍒濇鎵ц鏃 forloop.revcounter 灏嗚璁剧疆涓哄簭鍒椾腑椤圭殑鎬绘暟銆傛渶鍚庝竴娆″惊鐜墽琛屼腑锛岃繖涓彉閲忓皢琚疆1銆
forloop.revcounter0 is like forloop.revcounter , except its zero-indexed. The first time through the loop, forloop.revcounter0 will be set to the number of elements in the sequence minus 1. The last time through the loop, it will be set to 0 .
forloop.revcounter0 绫讳技浜 forloop.revcounter 锛屼絾瀹冧互0鍋氫负缁撴潫绱㈠紩銆傚湪绗竴娆℃墽琛屽惊鐜椂锛岃鍙橀噺浼氳缃负搴忓垪鐨勯」鐨勪釜鏁板噺1銆傚湪鏈鍚庝竴娆¤凯浠f椂锛岃鍙橀噺涓0銆
forloop.first is a Boolean value set to True if this is the first time through the loop. This is convenient for special casing:
forloop.first 鏄竴涓竷灏斿笺傚湪绗竴娆℃墽琛屽惊鐜椂璇ュ彉閲忎负True锛屽湪涓嬮潰鐨勬儏褰腑杩欎釜鍙橀噺鏄緢鏈夌敤鐨勩
{% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %}
forloop.last is a Boolean value set to True if this is the last time through the loop. A common use for this is to put pipe characters between a list of links:
forloop.last 鏄竴涓竷灏斿硷紱鍦ㄦ渶鍚庝竴娆℃墽琛屽惊鐜椂琚疆涓篢rue銆備竴涓父瑙佺殑鐢ㄦ硶鏄湪涓绯诲垪鐨勯摼鎺ヤ箣闂存斁缃閬撶锛坾锛
{% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %} The above template code might output something like this:: Link1 | Link2 | Link3 | Link4
forloop.parentloop is a reference to the forloop object for the parent loop, in case of nested loops. Heres an example:
forloop.parentloop 鏄竴涓寚鍚戝綋鍓嶅惊鐜殑涓婁竴绾у惊鐜殑 forloop 瀵硅薄鐨勫紩鐢紙鍦ㄥ祵濂楀惊鐜殑鎯呭喌涓嬶級銆備緥瀛愬湪姝わ細
{% for country in countries %} <table> {% for city in country.city_list %} <tr> <td>Country #{{ forloop.parentloop.counter }}</td> <td>City #{{ forloop.counter }}</td> <td>{{ city }}</td> </tr> {% endfor %} </table> {% endfor %}
The magic forloop variable is only available within loops. After the template parser has reached {% endfor %} , forloop disappears.
forloop 鍙橀噺浠呬粎鑳藉鍦ㄥ惊鐜腑浣跨敤锛屽湪妯℃澘瑙f瀽鍣ㄧ鍒 {% endfor %} 鏍囩鏃讹紝 forloop 灏变笉鍙闂簡銆
Context and the forloop Variable
Context鍜宖orloop鍙橀噺
Inside the {% for %} block, the existing variables are moved out of the way to avoid overwriting the magic forloop variable. Django exposes this moved context in forloop.parentloop . You generally dont need to worry about this, but if you supply a template variable named forloop (though we advise against it), it will be named forloop.parentloop while inside the {% for %} block.
鍦ㄤ竴涓 {% for %} 鍧椾腑锛屽凡瀛樺湪鐨勫彉閲忎細琚Щ闄わ紝浠ラ伩鍏 forloop 鍙橀噺琚鐩栥侱jango浼氭妸杩欎釜鍙橀噺绉诲姩鍒 forloop.parentloop 涓傞氬父鎴戜滑涓嶇敤鎷呭績杩欎釜闂锛屼絾鏄竴鏃︽垜浠湪妯℃澘涓畾涔変簡 forloop 杩欎釜鍙橀噺锛堝綋鐒舵垜浠弽瀵硅繖鏍峰仛锛夛紝鍦 {% for %} 鍧椾腑瀹冧細鍦 forloop.parentloop 琚噸鏂板懡鍚嶃
The Django template system deliberately is not a full-fledged programming language and thus does not allow you to execute arbitrary Python statements. (More on this idea in the section Philosophies and Limitations.) However, its quite a common template requirement to compare two values and display something if theyre equaland Django provides an {% ifequal %} tag for that purpose.
Django妯℃澘绯荤粺鍘嬫牴鍎垮氨娌℃兂杩囧疄鐜颁竴涓叏鍔熻兘鐨勭紪绋嬭瑷锛屾墍浠ュ畠涓嶅厑璁告垜浠湪妯℃澘涓墽琛孭ython鐨勮鍙ワ紙杩樻槸閭e彞璇濓紝瑕佷簡瑙f洿澶氳鍙傜湅鐞嗗康鍜岄檺鍒跺皬鑺傦級銆備絾鏄瘮杈冧袱涓彉閲忕殑鍊煎苟涓旀樉绀轰竴浜涚粨鏋滃疄鍦ㄦ槸涓お甯歌鐨勯渶姹備簡锛屾墍浠jango鎻愪緵浜 {% ifequal %} 鏍囩渚涙垜浠娇鐢ㄣ
The {% ifequal %} tag compares two values and displays everything between {% ifequal %} and {% endifequal %} if the values are equal.
{% ifequal %} 鏍囩姣旇緝涓や釜鍊硷紝褰撲粬浠浉鍚屾椂锛屾樉绀哄湪 {% ifequal %} 鍜 {% endifequal %} 涔嬩腑鎵鏈夌殑鍊笺
This example compares the template variables user and currentuser :
涓嬮潰鐨勪緥瀛愭瘮杈冧袱涓ā鏉垮彉閲 user 鍜 currentuser :
{% ifequal user currentuser %} <h1>Welcome!</h1> {% endifequal %}
The arguments can be hard-coded strings, with either single or double quotes, so the following is valid:
鍙傛暟鍙互鏄‖缂栫爜鐨勫瓧绗︿覆锛岄殢渚跨敤鍗曞紩鍙锋垨鑰呭弻寮曞彿寮曡捣鏉ワ紝鎵浠ヤ笅鍒椾唬鐮侀兘鏄纭殑锛
{% ifequal section 'sitenews' %} <h1>Site News</h1> {% endifequal %} {% ifequal section "community" %} <h1>Community</h1> {% endifequal %}
Just like {% if %} , the {% ifequal %} tag supports an optional {% else %} :
鍜 {% if %} 绫讳技锛 {% ifequal %} 鏀寔鍙夌殑 {% else%} 鏍囩锛
{% ifequal section 'sitenews' %} <h1>Site News</h1> {% else %} <h1>No News Here</h1> {% endifequal %}
Only template variables, strings, integers, and decimal numbers are allowed as arguments to {% ifequal %} . These are valid examples:
鍙湁妯℃澘鍙橀噺锛屽瓧绗︿覆锛屾暣鏁板拰灏忔暟鍙互浣滀负 {% ifequal %} 鏍囩鐨勫弬鏁般傝繖浜涙槸姝g‘鐨勪緥瀛愶細
{% ifequal variable 1 %} {% ifequal variable 1.23 %} {% ifequal variable 'foo' %} {% ifequal variable "foo" %}
Any other types of variables, such as Python dictionaries, lists, or Booleans, cant be hard-coded in {% ifequal %} . These are invalid examples:
鍏朵粬鐨勪竴浜涚被鍨嬶紝渚嬪Python鐨勫瓧鍏哥被鍨嬨佸垪琛ㄧ被鍨嬨佸竷灏旂被鍨嬶紝涓嶈兘鐢ㄥ湪 {% ifequal %} 涓 涓嬮潰鏄簺閿欒鐨勪緥瀛愶細
{% ifequal variable True %} {% ifequal variable [1, 2, 3] %} {% ifequal variable {'key': 'value'} %}
If you need to test whether something is true or false, use the {% if %} tags instead of {% ifequal %} .
濡傛灉浣犻渶瑕佸垽鏂彉閲忔槸鐪熻繕鏄亣锛岃浣跨敤 {% if %} 鏉ユ浛浠 {% ifequal %} 銆
Just as in HTML or in a programming language such as Python, the Django template language allows for comments. To designate a comment, use {# #} :
璞TML鍜屽叾浠栫殑璇█渚嬪python涓鏍凤紝Django妯℃澘绯荤粺涔熷厑璁告敞閲娿 娉ㄩ噴浣跨敤 {# #} 锛
{# This is a comment #}
The comment will not be output when the template is rendered.
娉ㄩ噴鐨勫唴瀹逛笉浼氬湪妯℃澘娓叉煋鏃惰緭鍑恒
A comment cannot span multiple lines. This limitation improves template parsing performance. In the following template, the rendered output will look exactly the same as the template (i.e., the comment tag will not be parsed as a comment):
娉ㄩ噴涓嶈兘璺ㄥ琛屻傝繖涓檺鍒舵槸涓轰簡鎻愰珮妯℃澘瑙f瀽鐨勬ц兘銆傚湪涓嬮潰杩欎釜妯℃澘涓紝杈撳嚭缁撴灉鍜屾ā鏉挎湰韬槸 瀹屽叏涓鏍风殑锛堜篃灏辨槸璇达紝娉ㄩ噴鏍囩骞舵病鏈夎瑙f瀽涓烘敞閲婏級锛
This is a {# this is not a comment #} test.
As explained earlier in this chapter, template filters are simple ways of altering the value of variables before theyre displayed. Filters look like this:
灏辫薄鏈珷鍓嶉潰鎻愬埌鐨勪竴鏍凤紝妯℃澘杩囨护鍣ㄦ槸鍦ㄥ彉閲忚鏄剧ず鍓嶄慨鏀瑰畠鐨勫肩殑涓涓畝鍗曟柟娉曘 杩囨护鍣ㄧ湅璧锋潵鏄繖鏍风殑锛
{{ name|lower }}
This displays the value of the {{ name }} variable after being filtered through the lower filter, which converts text to lowercase. Use a pipe (| ) to apply a filter.
鏄剧ず鐨勫唴瀹规槸鍙橀噺 {{ name }} 琚繃婊ゅ櫒 lower 澶勭悊鍚庣殑缁撴灉锛屽畠鍔熻兘鏄浆鎹㈡枃鏈负灏忓啓銆 浣跨敤 | 鏉ュ簲鐢ㄨ繃婊ゅ櫒銆
Filters can be chained that is, the output of one filter is applied to the next. Heres a common idiom for escaping text contents, and then converting line breaks to <p> tags:
杩囨护鍣ㄥ彲浠ヨ 涓茶仈 ,灏辨槸璇翠竴涓繃婊ゅ櫒鐨勮緭鍑哄彲浠ヨ杈撳叆鍒颁笅涓涓繃婊ゅ櫒銆傝繖閲屾湁涓涓父鐢ㄧ殑 闇姹傦紝鍏堣浆涔夋枃鏈埌HTML锛屽啀杞崲姣忚鍒 <p> 鏍囩锛
{{ my_text|escape|linebreaks }}
Some filters take arguments. A filter argument looks like this:
鏈変簺杩囨护鍣ㄦ湁鍙傛暟銆傝繃婊ゅ櫒鍙傛暟鐪嬭捣鏉ユ槸杩欐牱鐨勶細
{{ bio|truncatewords:"30" }}
This displays the first 30 words of the bio variable. Filter arguments are always in double quotes.
杩欎釜灏嗘樉绀哄彉閲 bio 鐨勫墠30涓瘝銆傝繃婊ゅ櫒鍙傛暟鎬绘槸浣跨敤鍙屽紩鍙锋爣璇嗐
The following are a few of the most important filters; Appendix F covers the rest.
涓嬮潰鏄竴浜涙渶閲嶈鐨勮繃婊ゅ櫒锛涢檮褰旻鏈夊畬鏁寸殑杩囨护鍣ㄥ垪琛ㄣ
addslashes : Adds a backslash before any backslash, single quote, or double quote. This is useful if the produced text is included in a JavaScript string.
addslashes : 娣诲姞鍙嶆枩鏉犲埌浠讳綍鍙嶆枩鏉犮佸崟寮曞彿鎴栬呭弻寮曞彿鍓嶉潰銆 杩欏湪澶勭悊鍖呭惈JavaScript鐨勬枃鏈椂鏄潪甯告湁鐢ㄧ殑銆
date : Formats a date or datetime object according to a format string given in the parameter, for example:
date : 鎸夋寚瀹氱殑鏍煎紡瀛楃涓插弬鏁版牸寮忓寲 date 鎴栬 datetime 瀵硅薄锛 鑼冧緥锛
{{ pub_date|date:"F j, Y" }}
Format strings are defined in Appendix F.
鏍煎紡鍙傛暟鐨勫畾涔夊湪闄勫綍F涓
escape : Escapes ampersands, quotes, and angle brackets in the given string. This is useful for sanitizing user-submitted data and for ensuring data is valid XML or XHTML. Specifically, escape makes these conversions:
escape : 杞箟 &绗﹀彿锛屽紩鍙凤紝<锛> 绗﹀彿銆 杩欏湪纭繚鐢ㄦ埛鎻愪氦鐨勬暟鎹槸鏈夋晥鐨刋ML鎴朮HTML鏃舵槸闈炲父鏈夌敤鐨勩 鍏蜂綋涓婏紝 escape 鍋氫笅闈㈣繖浜涜浆鎹:
Converts & to &
escape : 杞箟 &绗﹀彿锛屽紩鍙凤紝<锛> 绗﹀彿銆 杩欏湪纭繚鐢ㄦ埛鎻愪氦鐨勬暟鎹槸鏈夋晥鐨刋ML鎴朮HTML鏃舵槸闈炲父鏈夌敤鐨勩 鍏蜂綋涓婏紝 escape 鍋氫笅闈㈣繖浜涜浆鎹:
Converts < to <
杞崲 < 鍒 <
Converts > to >
杞崲 > 鍒 >
Converts " (double quote) to "
杞崲 " (鍙屽紩鍙) 鍒 "
Converts ' (single quote) to '
杞崲 ' (鍗曞紩鍙) 鍒 '
length : Returns the length of the value. You can use this on a list or a string, or any Python object that knows how to determine its length (i.e., any object that has a __len__() method).
length : 杩斿洖鍙橀噺鐨勯暱搴︺備綘鍙互瀵瑰垪琛ㄦ垨鑰呭瓧绗︿覆锛屾垨鑰呬换浣曠煡閬撴庝箞娴嬪畾闀垮害鐨凱ython 瀵硅薄浣跨敤杩欎釜鏂规硶锛堜篃灏辨槸璇达紝鏈 __len__() 鏂规硶鐨勫璞★級銆
Now that youve gotten a feel for the Django template language, we should point out some of its intentional limitations, along with some philosophies behind why it works the way it works.
鐜板湪浣犲凡缁忓Django鐨勬ā鏉胯瑷鏈変竴浜涜璇嗕簡锛屾垜浠皢鎸囧嚭涓浜涚壒鎰忚缃殑闄愬埗鍜屼负浠涔堣杩欐牱鍋 鑳屽悗鐨勪竴浜涜璁″摬瀛︺
More than any other component of Web applications, programmer opinions on template systems vary wildly. The fact that Python alone has dozens, if not hundreds, of open source template-language implementations supports this point. Each was likely created because its developer deemed all existing template languages inadequate. (In fact, it is said to be a rite of passage for a Python developer to write his or her own template language! If you havent done this yet, consider it. Its a fun exercise.)
鐩稿Web搴旂敤涓殑鍏朵粬缁勪欢锛岀▼搴忓憳浠妯℃澘绯荤粺鐨勫垎姝ф槸鏈澶х殑銆備簨瀹炰笂锛孭ython鏈夋垚鍗佷笂鐧剧殑 寮鏀炬簮鐮佺殑妯℃澘璇█瀹炵幇銆傛瘡涓疄鐜伴兘鏄洜涓哄紑鍙戣呰涓虹幇瀛樼殑妯℃澘璇█涓嶅鐢ㄣ傦紙浜嬪疄涓婏紝瀵逛竴涓 Python寮鍙戣呮潵璇达紝鍐欎竴涓嚜宸辩殑妯℃澘璇█灏辫薄鏄煇绉嶁滄垚浜虹ぜ鈥濅竴鏍凤紒濡傛灉浣犺繕娌℃湁瀹屾垚涓涓嚜宸辩殑 妯℃澘璇█锛屽ソ濂借冭檻鍐欎竴涓紝杩欐槸涓涓潪甯告湁瓒g殑閿荤偧銆傦級
With that in mind, you might be interested to know that Django doesnt require that you use its template language. Because Django is intended to be a full-stack Web framework that provides all the pieces necessary for Web developers to be productive, many times its more convenient to use Djangos template system than other Python template libraries, but its not a strict requirement in any sense. As youll see in the upcoming section Using Templates in Views, its very easy to use another template language with Django.
鏄庣櫧浜嗚繖涓紝浣犱篃璁告湁鍏磋叮鐭ラ亾浜嬪疄涓奃jango骞朵笉寮哄埗瑕佹眰浣犲繀椤讳娇鐢ㄥ畠鐨勬ā鏉胯瑷銆傚洜涓篋jango 铏界劧琚璁℃垚涓涓狥ULL-Stack鐨刉eb妗嗘灦锛屽畠鎻愪緵浜嗗紑鍙戣呮墍蹇呴渶鐨勬墍鏈夌粍浠讹紝鑰屼笖鍦ㄥぇ澶氭暟鎯呭喌 浣跨敤Django妯℃澘绯荤粺浼氭瘮鍏朵粬鐨凱ython妯℃澘搴撹 鏇存柟渚 涓鐐癸紝浣嗘槸骞朵笉鏄弗鏍艰姹備綘蹇呴』浣跨敤 瀹冦傚氨璞′綘灏嗗湪鍚庣画鐨勭珷鑺備腑鐪嬪埌鐨勪竴鏍凤紝浣犱篃鍙互闈炲父瀹规槗鐨勫湪Django涓娇鐢ㄥ叾浠栫殑妯℃澘璇█銆
Still, its clear we have a strong preference for the way Djangos template language works. The template system has roots in how Web development is done at World Online and the combined experience of Djangos creators. Here are a few of those philosophies:
铏界劧濡傛锛屽緢鏄庢樉锛屾垜浠Django妯℃澘璇█鐨勫伐浣滄柟寮忔湁鐫寮虹儓鐨勫亸鐖便傝繖涓ā鏉胯瑷鏉ユ簮浜嶹orld Online鐨勫紑鍙戠粡楠屽拰Django鍒涢犺呬滑闆嗕綋鏅烘収鐨勭粨鏅躲備笅闈㈡槸鍏充簬瀹冪殑涓浜涜璁″摬瀛︾悊蹇碉細
Business logic should be separated from presentation logic . We see a template system as a tool that controls presentation and presentation-related logicand thats it. The template system shouldnt support functionality that goes beyond this basic goal.
涓氬姟閫昏緫搴旇鍜岃〃鐜伴昏緫鐩稿鍒嗗紑 銆傛垜浠皢妯℃澘绯荤粺瑙嗕负鎺у埗琛ㄧ幇鍙婅〃鐜扮浉鍏抽昏緫鐨勫伐鍏凤紝浠呮鑰屽凡銆傛ā鏉跨郴缁熶笉搴旀彁渚涜秴鍑烘鍩烘湰鐩爣鐨勫姛鑳姐
For that reason, its impossible to call Python code directly within Django templates. All programming is fundamentally limited to the scope of what template tags can do. It is possible to write custom template tags that do arbitrary things, but the out-of-the-box Django template tags intentionally do not allow for arbitrary Python code execution.
鍑轰簬杩欎釜鍘熷洜锛屽湪 Django 妯℃澘涓槸涓嶅彲鑳界洿鎺ヨ皟鐢 Python 浠g爜鐨勩傛墍鏈夌殑缂栫▼宸ヤ綔鍩烘湰涓婇兘琚眬闄愪簬妯℃澘鏍囩鐨勮兘鍔涜寖鍥淬傚綋鐒讹紝 鏄 鏈夊彲鑳藉啓鍑鸿嚜瀹氫箟鐨勬ā鏉挎爣绛炬潵瀹屾垚浠绘剰宸ヤ綔锛屼絾杩欎簺鈥滆秴鑼冨洿鈥濈殑 Django 妯℃澘鏍囩鏈夋剰鍦颁笉鍏佽鎵ц浠讳綍 Python 浠g爜銆
Syntax should be decoupled from HTML/XML . Although Djangos template system is used primarily to produce HTML, its intended to be just as usable for non-HTML formats, such as plain text. Some other template languages are XML based, placing all template logic within XML tags or attributes, but Django deliberately avoids this limitation. Requiring valid XML to write templates introduces a world of human mistakes and hard-to-understand error messages, and using an XML engine to parse templates incurs an unacceptable level of overhead in template processing.
璇硶涓嶅簲鍙楀埌 HTML/XML 鐨勬潫缂 銆傚敖绠 Django 妯℃澘绯荤粺涓昏鐢ㄤ簬鐢熸垚 HTML锛屽畠杩樻槸琚湁鎰忓湴璁捐涓哄彲鐢熸垚闈 HTML 鏍煎紡锛屽绾枃鏈備竴浜涘叾瀹冪殑妯℃澘璇█鏄熀浜 XML 鐨勶紝灏嗘墍鏈夌殑妯℃澘閫昏緫缃簬 XML 鏍囩涓庡睘鎬т箣涓紝鑰 Django 鏈夋剰鍦伴伩寮浜嗚繖绉嶉檺鍒躲傚己鍒惰姹備娇鐢ㄦ湁鏁 XML 缂栧啓妯℃澘灏嗕細寮曞彂澶ч噺鐨勪汉涓洪敊璇拰闅句互鐞嗚В鐨勯敊璇俊鎭紝鑰屼笖浣跨敤 XML 寮曟搸瑙f瀽妯℃澘涔熶細瀵艰嚧浠や汉鏃犳硶瀹瑰繊鐨勬ā鏉垮鐞嗗紑閿銆
Designers are assumed to be comfortable with HTML code . The template system isnt designed so that templates necessarily are displayed nicely in WYSIWYG editors such as Dreamweaver. That is too severe a limitation and wouldnt allow the syntax to be as nice as it is. Django expects template authors to be comfortable editing HTML directly.
鍋囧畾璁捐甯堢簿閫 HTML 缂栫爜 銆傛ā鏉跨郴缁熺殑璁捐鎰忓浘骞朵笉鏄负浜嗚妯℃澘涓瀹氳兘澶熷緢濂藉湴鏄剧ず鍦 Dreamweaver 杩欐牱鐨勬墍瑙佸嵆鎵寰楃紪杈戝櫒涓傝繖绉嶉檺鍒惰繃浜庤嫑鍒伙紝鑰屼笖浼氫娇寰楄娉曚笉鑳藉儚鐩墠杩欐牱鐨勫畬缇庛侱jango 瑕佹眰妯℃澘鍒涗綔浜哄憳瀵圭洿鎺ョ紪杈 HTML 闈炲父鐔熸倝銆
Designers are assumed not to be Python programmers . The template system authors recognize that Web page templates are most often written by designers , not programmers , and therefore should not assume Python knowledge.
鍋囧畾璁捐甯堜笉鏄 Python 绋嬪簭鍛 銆傛ā鏉跨郴缁熷紑鍙戜汉鍛樿涓猴細缃戦〉妯℃澘閫氬父鐢 璁捐甯 鑰屼笉鏄 绋嬪簭鍛 缂栧啓锛屽洜鑰屽亣瀹氳繖浜涗汉骞朵笉鎺屾彙 Python 鐩稿叧鐭ヨ瘑銆
However, the system also intends to accommodate small teams in which the templates are created by Python programmers. It offers a way to extend the systems syntax by writing raw Python code. (More on this in Chapter 10.)
褰撶劧锛岀郴缁熷悓鏍蜂篃鐗规剰鍦版彁渚涗簡瀵归偅浜 鐢 Python 绋嬪簭鍛樿繘琛屾ā鏉垮埗浣滅殑灏忓瀷鍥㈤槦鐨勬敮鎸併傚畠鎻愪緵浜嗕竴绉嶅伐浣滄ā寮忥紝鍏佽閫氳繃缂栧啓鍘熺敓 Python 浠g爜杩涜绯荤粺璇硶鎷撳睍銆傦紙璇﹁绗崄绔狅級
The goal is not to invent a programming language . The goal is to offer just enough programming-esque functionality, such as branching and looping, that is essential for making presentation-related decisions.
鐩爣骞朵笉鏄鍙戞槑涓绉嶇紪绋嬭瑷 銆傜洰鏍囨槸鎭板埌濂藉鍦版彁渚涘鍒嗘敮鍜屽惊鐜繖涓绫荤紪绋嬪紡鍔熻兘锛岃繖鏄繘琛屼笌琛ㄧ幇鐩稿叧鍒ゆ柇鐨勫熀纭銆
As a result of these design philosophies, the Django template language has the following limitations:
閲囩敤杩欎簺璁捐鐞嗗康鐨勭粨鏋滄槸瀵艰嚧 Django 妯℃澘璇█鏈変互涓嬪嚑鐐归檺鍒讹細
A template cannot set a variable or change the value of a variable . Its possible to write custom template tags that accomplish these goals (see Chapter 10), but the stock Django template tags do not allow it.
妯℃澘涓笉鑳借缃彉閲忓拰鏀瑰彉鍙橀噺鐨勫 銆傚彲浠ラ氳繃缂栧啓鑷畾涔夋ā鏉挎爣绛惧仛鍒拌繖涓鐐癸紙鍙傝绗崄绔狅級锛屼絾姝e畻鐨 Django 妯℃澘鏍囩鍋氫笉鍒般
A template cannot call raw Python code . Theres no way to drop into Python mode or use raw Python constructs. Again, its possible to write custom template tags to do this, but the stock Django template tags dont allow it.
妯℃澘涓笉鑳借皟鐢ㄤ换浣曠殑Python浠g爜 銆備笉瀛樺湪杞叆 Python 妯″紡鎴栦娇鐢ㄥ師鐢 Python 鏁版嵁缁撴瀯鐨勬柟娉曘傚拰鍓嶉潰涓鏍凤紝鍙互缂栧啓鑷畾涔夋ā鏉挎爣绛炬潵瀹炵幇杩欎釜鐩爣锛屼絾姝g当鐨 Django 妯℃澘鏍囩鍋氫笉鍒般
Youve learned the basics of using the template system; now lets use this knowledge to create a view. Recall the current_datetime view in mysite.views , which we started in the previous chapter. Heres what it looks like:
鍦ㄥ涔犱簡妯℃澘绯荤粺鐨勫熀纭涔嬪悗锛岀幇鍦ㄨ鎴戜滑浣跨敤鐩稿叧鐭ヨ瘑鏉ュ垱寤鸿鍥俱傞噸鏂版墦寮鎴戜滑鍦ㄥ墠涓绔犲湪 mysite.views 涓垱寤虹殑 current_datetime 瑙嗗浘銆備互涓嬫槸鍏跺唴瀹癸細
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 change this view to use Djangos template system. At first, you might think to do something like this:
璁╂垜浠敤 Django 妯℃澘绯荤粺鏉ヤ慨鏀硅瑙嗗浘銆傜涓姝ワ紝浣犲彲鑳藉凡缁忔兂鍒颁簡瑕佸仛涓嬮潰杩欐牱鐨勪慨鏀癸細
from django.template import Template, Context from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() t = Template("<html><body>It is now {{ current_date }}.</body></html>") html = t.render(Context({'current_date': now})) return HttpResponse(html)
Sure, that uses the template system, but it doesnt solve the problems we pointed out in the introduction of this chapter. Namely, the template is still embedded in the Python code. Lets fix that by putting the template in a separate file , which this view will load.
娌¢敊锛屽畠纭疄浣跨敤浜嗘ā鏉跨郴缁燂紝浣嗘槸骞舵病鏈夎В鍐虫垜浠湪鏈珷寮澶存墍鎸囧嚭鐨勯棶棰樸備篃灏辨槸璇达紝妯℃澘渚濈劧鍐呭祵鍦 Python 浠g爜涔嬩腑銆傝鎴戜滑灏嗘ā鏉跨疆浜庝竴涓 鍗曠嫭鐨勬枃浠 涓紝骞朵笖璁╄鍥惧姞杞借鏂囦欢鏉ヨВ鍐虫闂銆
You might first consider saving your template somewhere on your filesystem and using Pythons built-in file-opening functionality to read the contents of the template. Heres what that might look like, assuming the template was saved as the file /home/djangouser/templates/mytemplate.html :
浣犲彲鑳介鍏堣冭檻鎶婃ā鏉夸繚瀛樺湪鏂囦欢绯荤粺鐨勬煇涓綅缃苟鐢 Python 鍐呭缓鐨勬枃浠舵搷浣滃嚱鏁版潵璇诲彇鏂囦欢鍐呭銆傚亣璁炬枃浠朵繚瀛樺湪 /home/djangouser/templates/mytemplate.html 涓殑璇濓紝浠g爜灏变細鍍忎笅闈㈣繖鏍:
from django.template import Template, Context from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() # Simple way of using templates from the filesystem. # This doesn't account for missing files! fp = open('/home/djangouser/templates/mytemplate.html') t = Template(fp.read()) fp.close() html = t.render(Context({'current_date': now})) return HttpResponse(html)
This approach, however, is inelegant for these reasons:
鐒惰岋紝鍩轰簬浠ヤ笅鍑犱釜鍘熷洜锛岃鏂规硶杩樼畻涓嶄笂绠娲侊細
It doesnt handle the case of a missing file. If the file mytemplate.html doesnt exist or isnt readable, the open() call will raise an IOError exception.
瀹冩病鏈夊鏂囦欢涓㈠け鐨勬儏鍐靛仛鍑哄鐞嗐傚鏋滄枃浠 mytemplate.html 涓嶅瓨鍦ㄦ垨鑰呬笉鍙锛 open() 鍑芥暟璋冪敤灏嗕細寮曞彂 IOError 寮傚父銆
It hard-codes your template location. If you were to use this technique for every view function, youd be duplicating the template locations. Not to mention it involves a lot of typing!
杩欓噷瀵规ā鏉挎枃浠剁殑浣嶇疆杩涜浜嗙‖缂栫爜銆傚鏋滀綘鍦ㄦ瘡涓鍥惧嚱鏁伴兘鐢ㄨ鎶鏈紝灏辫涓嶆柇澶嶅埗杩欎簺妯℃澘鐨勪綅缃傛洿涓嶇敤璇磋繕瑕佸甫鏉ュぇ閲忕殑杈撳叆宸ヤ綔锛
It includes a lot of boring boilerplate code. Youve got better things to do than to write calls to open() , fp.read() , and fp.close() each time you load a template.
瀹冨寘鍚簡澶ч噺浠や汉鐢熷帉鐨勯噸澶嶄唬鐮併備笌鍏跺湪姣忔鍔犺浇妯℃澘鏃堕兘璋冪敤 open() 銆 fp.read() 鍜 fp.close() 锛岃繕涓嶅鍋氬嚭鏇翠匠閫夋嫨銆
To solve these issues, well use template loading and template directories , both of which are described in the sections that follow.
瑕佽В鍐虫闂锛屾垜浠皢浣跨敤 妯℃澘鍔犺浇 鍜 妯℃澘鐩綍 锛岃繖鏄垜浠湪鎺ヤ笅鏉ョ殑绔犺妭涓璁ㄨ鐨勪袱涓瘽棰樸
Django provides a convenient and powerful API for loading templates from disk, with the goal of removing redundancy both in your template-loading calls and in your templates themselves.
涓轰簡鍑忓皯妯℃澘鍔犺浇璋冪敤杩囩▼鍙婃ā鏉挎湰韬殑鍐椾綑浠g爜锛孌jango 鎻愪緵浜嗕竴绉嶄娇鐢ㄦ柟渚夸笖鍔熻兘寮哄ぇ鐨 API 锛岀敤浜庝粠纾佺洏涓姞杞芥ā鏉匡紝
In order to use this template-loading API, first youll need to tell the framework where you store your templates. The place to do this is in your settings file .
瑕佷娇鐢ㄦ妯℃澘鍔犺浇API锛岄鍏堜綘蹇呴』灏嗘ā鏉跨殑淇濆瓨浣嶇疆鍛婅瘔妗嗘灦銆傝椤瑰伐浣滃湪 璁剧疆鏂囦欢 涓畬鎴愩
A Django settings file is the place to put configuration for your Django instance (aka your Django project). Its a simple Python module with module-level variables, one for each setting.
Django 璁剧疆鏂囦欢鏄瓨鏀 Django 瀹炰緥锛堜篃灏辨槸 Django 椤圭洰锛夐厤缃殑鍦版柟銆傚畠鏄竴涓畝鍗曠殑 Python 妯″潡锛屽叾涓寘鍚簡涓浜涙ā鍧楃骇鍙橀噺锛屾瘡涓兘鏄竴椤硅缃
When you ran django-admin.py startproject mysite in Chapter 2, the script created a default settings file for you, aptly named settings.py . Have a look at the files contents. It contains variables that look like this (though not necessarily in this order):
绗簩绔犱腑鎵ц django-admin.py startproject mysite 鍛戒护鏃讹紝瀹冧负浣犲垱寤轰簡涓涓殑缂虹渷閰嶇疆鏂囦欢锛屽苟鎭板鍏跺垎鍦板皢鍏跺悕涓 settings.py 銆傛煡鐪嬩竴涓嬭鏂囦欢鍐呭銆傚叾涓寘鍚涓嬪彉閲忥紙浣嗗苟涓嶄竴瀹氭槸杩欎釜椤哄簭锛夛細
DEBUG = True TIME_ZONE = 'America/Chicago' USE_I18N = True ROOT_URLCONF = 'mysite.urls'
This is pretty self-explanatory; the settings and their respective values are simple Python variables. And because the settings file is just a plain Python module, you can do dynamic things such as checking the value of one variable before setting another. (This also means that you should avoid Python syntax errors in your settings file.)
杩欓噷鏃犻渶鏇村璇犻噴锛涜缃」涓庡煎潎涓虹畝鍗曠殑 Python 鍙橀噺銆傚悓鏃剁敱浜庨厤缃枃浠跺彧涓嶈繃鏄函 Python 妯″潡锛屼綘鍙互瀹屾垚涓浜涘姩鎬佸伐浣滐紝姣斿鍦ㄨ缃煇鍙橀噺涔嬪墠妫鏌ュ彟涓鍙橀噺鐨勫笺傦紙杩欎篃鎰忓懗鐫浣犲繀椤婚伩鍏嶉厤缃枃浠跺嚭鐜 Python 璇硶閿欒銆傦級
Well cover settings files in depth in Appendix E, but for now, have a look at the TEMPLATE_DIRS setting. This setting tells Djangos template-loading mechanism where to look for templates. By default, its an empty tuple. Pick a directory where youd like to store your templates and add it to TEMPLATE_DIRS , like so:
鎴戜滑灏嗗湪闄勫綍 E 涓杩伴厤缃枃浠讹紝鐩墠鑰岃█锛屼粎闇鍏虫敞 TEMPLATE_DIRS 璁剧疆銆傝璁剧疆鍛婅瘔 Django 鐨勬ā鏉垮姞杞芥満鍒跺湪鍝噷鏌ユ壘妯℃澘銆傜己鐪佹儏鍐典笅锛岃璁剧疆鐨勫兼槸涓涓┖鐨勫厓缁勩傞夋嫨涓涓洰褰曠敤浜庡瓨鏀炬ā鏉垮苟灏嗗叾娣诲姞鍒 TEMPLATE_DIRS 涓細
TEMPLATE_DIRS = ( '/home/django/mysite/templates', )
There are a few things to note:
涓嬮潰鏄竴浜涙敞鎰忎簨椤癸細
You can specify any directory you want, as long as the directory and templates within that directory are readable by the user account under which your Web server runs. If you cant think of an appropriate place to put your templates, we recommend creating a templates directory within your Django project (i.e., within the mysite directory you created in Chapter 2, if youve been following along with this books examples).
浣犲彲浠ヤ换鎰忔寚瀹氭兂瑕佺殑鐩綍锛屽彧瑕佽繍琛 Web 鏈嶅姟鍣ㄧ殑鐢ㄦ埛璐﹀彿鍙互璇诲彇璇ョ洰褰曠殑瀛愮洰褰曞拰妯℃澘鏂囦欢銆傚鏋滃疄鍦ㄦ兂涓嶅嚭鍚堥傜殑浣嶇疆鏉ユ斁缃ā鏉匡紝鎴戜滑寤鸿鍦 Django 椤圭洰涓垱寤轰竴涓 templates 鐩綍锛堜篃灏辨槸璇达紝濡傛灉浣犱竴鐩撮兘鎸夋湰涔︾殑鑼冧緥鎿嶄綔鐨勮瘽锛屽湪绗簩绔犲垱寤虹殑 mysite 鐩綍涓級銆
Dont forget the comma at the end of the template directory string! Python requires commas within single-element tuples to disambiguate the tuple from a parenthetical expression. This is a common newbie gotcha.
涓嶈蹇樿妯℃澘鐩綍瀛楃涓插熬閮ㄧ殑閫楀彿锛丳ython 瑕佹眰鍗曞厓绱犲厓缁勪腑蹇呴』浣跨敤閫楀彿锛屼互姝ゆ秷闄や笌鍦嗘嫭鍙疯〃杈惧紡涔嬮棿鐨勬涔夈傝繖鏄柊鎵嬪父鐘殑閿欒銆
If you want to avoid this error, you can make TEMPLATE_DIRS a list instead of a tuple, because single-element lists dont require a trailing comma:
鎯抽伩鍏嶆閿欒鐨勮瘽锛屼綘鍙互灏嗗垪琛ㄨ屼笉鏄厓缁勭敤浣 TEMPLATE_DIRS 锛屽洜涓哄崟鍏冪礌鍒楄〃骞朵笉寮哄埗瑕佹眰浠ラ楀彿鏀跺熬锛
TEMPLATE_DIRS = [ '/home/django/mysite/templates' ]
A tuple is slightly more semantically correct than a list (tuples cannot be changed after being created, and nothing should be changing settings once theyve been read), so we recommend using a tuple for your TEMPLATE_DIRS setting.
浠庤涔変笂鐪嬶紝鍏冪粍姣斿垪琛ㄧ暐鏄惧悎閫傦紙鍏冪粍鍦ㄥ垱寤轰箣鍚庡氨涓嶈兘淇敼锛岃岄厤缃璇诲彇浠ュ悗灏变笉搴旇鏈変换浣曚慨鏀癸級銆傚洜姝わ紝鎴戜滑鎺ㄨ崘瀵 TEMPLATE_DIRS 璁剧疆浣跨敤鍏冪粍銆
If youre on Windows, include your drive letter and use Unix-style forward slashes rather than backslashes, as follows:
濡傛灉浣跨敤鐨勬槸 Windows 骞冲彴锛岃鍖呭惈椹卞姩鍣ㄧ鍙峰苟浣跨敤Unix椋庢牸鐨勬枩鏉狅紙/锛夎屼笉鏄弽鏂滄潬锛圽锛,灏卞儚涓嬮潰杩欐牱锛
TEMPLATE_DIRS = ( 'C:/www/django/templates', )
Its simplest to use absolute paths (i.e., directory paths that start at the root of the filesystem). If you want to be a bit more flexible and decoupled, though, you can take advantage of the fact that Django settings files are just Python code by constructing the contents of TEMPLATE_DIRS dynamically, for example:
鏈鐪佷簨鐨勬柟寮忔槸浣跨敤缁濆璺緞锛堝嵆浠庢枃浠剁郴缁熸牴鐩綍寮濮嬬殑鐩綍璺緞锛夈傚鏋滄兂瑕佹洿鐏垫椿涓鐐瑰苟鍑忓皯涓浜涜礋闈㈠共鎵帮紝鍙埄鐢 Django 閰嶇疆鏂囦欢灏辨槸 Python 浠g爜杩欎竴鐐规潵鍔ㄦ佹瀯寤 TEMPLATE_DIRS 鐨勫唴瀹癸紝濡傦細
import os.path TEMPLATE_DIRS = ( os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'), )
This example uses the magic Python variable __file__ , which is automatically set to the file name of the Python module in which the code lives.
杩欎釜渚嬪瓙浣跨敤浜嗙濂囩殑 Python 鍐呴儴鍙橀噺 __file__ 锛岃鍙橀噺琚嚜鍔ㄨ缃负浠g爜鎵鍦ㄧ殑 Python 妯″潡鏂囦欢鍚嶃
With TEMPLATE_DIRS set, the next step is to change the view code to use Djangos template-loading functionality rather than hard-coding the template paths. Returning to our current_datetime view, lets change it like so:
瀹屾垚 TEMPLATE_DIRS 璁剧疆鍚庯紝涓嬩竴姝ュ氨鏄慨鏀硅鍥句唬鐮侊紝璁╁畠浣跨敤 Django 妯℃澘鍔犺浇鍔熻兘鑰屼笉鏄妯℃澘璺緞纭紪鐮併傝繑鍥 current_datetime 瑙嗗浘锛岃繘琛屽涓嬩慨鏀癸細
from django.template.loader import get_template from django.template import Context from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() t = get_template('current_datetime.html') html = t.render(Context({'current_date': now})) return HttpResponse(html)
In this example, were using the function django.template.loader.get_template() rather than loading the template from the filesystem manually. The get_template() function takes a template name as its argument, figures out where the template lives on the filesystem, opens that file, and returns a compiled Template object.
姝よ寖渚嬩腑锛屾垜浠娇鐢ㄤ簡鍑芥暟 django.template.loader.get_template() 锛岃屼笉鏄墜鍔ㄤ粠鏂囦欢绯荤粺鍔犺浇妯℃澘銆傝 get_template() 鍑芥暟浠ユā鏉垮悕绉颁负鍙傛暟锛屽湪鏂囦欢绯荤粺涓壘鍑烘ā鍧楃殑浣嶇疆锛屾墦寮鏂囦欢骞惰繑鍥炰竴涓紪璇戝ソ鐨 Template 瀵硅薄銆
If get_template() cannot find the template with the given name, it raises a TemplateDoesNotExist exception. To see what that looks like, fire up the Django development server again, as in Chapter 3, by running python manage.py runserver within your Django projects directory. Then, point your browser at the page that activates the current_datetime view (e.g., http://127.0.0.1:8000/time/ ). Assuming your DEBUG setting is set to True and you havent yet created a current_datetime.html template, you should see a Django error page highlighting the TemplateDoesNotExist error.
濡傛灉 get_template() 鎵句笉鍒扮粰瀹氬悕绉扮殑妯℃澘锛屽皢浼氬紩鍙戜竴涓 TemplateDoesNotExist 寮傚父銆傝浜嗚В绌剁珶浼氬彂鐢熶粈涔堬紝璁╂垜浠寜鐓х涓夌珷鍐呭锛屽湪 Django 椤圭洰鐩綍涓繍琛 python manage.py runserver 鍛戒护锛屽啀娆″惎鍔―jango寮鍙戞湇鍔″櫒銆傘傜劧鍚庯紝鐢ㄦ祻瑙堝櫒璁块棶椤甸潰锛堝锛 http://127.0.0.1:8000/time/ ) 婵娲 current_datetime 瑙嗗浘銆傚亣濡 DEBUG 璁剧疆涓 True 鑰屽張鏈垱寤 current_datetime.html 妯℃澘锛屼綘灏嗕細鐪嬪埌 TemplateDoesNotExist 閿欒淇℃伅椤甸潰銆
Figure 4-1: The error page shown when a template cannot be found.
鍥 4-1: 鏃犳硶鎵惧埌妯℃澘鏃剁殑鍑洪敊椤甸潰
This error page is similar to the one we explained in Chapter 3, with one additional piece of debugging information: a Template-loader postmortem section. This section tells you which templates Django tried to load, along with the reason each attempt failed (e.g., File does not exist). This information is invaluable when youre trying to debug template-loading errors.
璇ラ〉闈笌鎴戜滑鍦ㄧ涓夌珷瑙i噴杩囩殑閿欒椤甸潰鐩镐技锛屽彧涓嶈繃澶氫簡涓鍧楄皟璇曚俊鎭尯锛氭ā鏉垮姞杞藉櫒浜嬪悗妫鏌ュ尯銆傝鍖哄煙鏄剧ず Django 瑕佸姞杞藉摢涓ā鏉裤佹瘡娆″皾璇曞嚭閿欑殑鍘熷洜锛堝锛氭枃浠朵笉瀛樺湪绛夛級銆傚湪璋冭瘯妯℃澘鍔犺浇閿欒鏃讹紝杩欎簺淇℃伅鐨勪环鍊兼槸涓嶅彲浼伴噺鐨勩
As you can probably tell from the error messages found in the Figure 4-1, Django attempted to find the template by combining the directory in the TEMPLATE_DIRS setting with the template name passed to get_template() . So if your TEMPLATE_DIRS contains '/home/django/templates' , Django looks for the file '/home/django/templates/current_datetime.html' . If TEMPLATE_DIRS contains more than one directory, each is checked until the template is found or theyve all been checked.
姝e浣犱粠鍥 4-1 涓殑閿欒淇℃伅涓墍鐪嬪埌锛孌jango 灏濊瘯閫氳繃缁勫悎 TEMPLATE_DIRS 璁剧疆浠ュ強浼犻掔粰 get_template() 鐨勬ā鏉垮悕绉版潵鏌ユ壘妯℃澘銆傚洜姝ゅ鏋 TEMPLATE_DIRS 涓 '/home/django/templates' 锛孌jango 灏嗕細 鏌ユ壘 '/home/django/templates/current_datetime.html' 銆傚鏋 TEMPLATE_DIRS 鍖呭惈澶氫釜鐩綍锛屽畠灏嗕細鏌ユ壘姣忎釜鐩綍鐩磋嚦鎵惧埌妯℃澘鎴栨壘閬嶆墍鏈夌洰褰曘
Moving along, create the current_datetime.html file within your template directory using the following template code:
鎺ヤ笅鏉ワ紝鍦ㄦā鏉跨洰褰曚腑鍒涘缓鍖呮嫭浠ヤ笅妯℃澘浠g爜 current_datetime.html 鏂囦欢锛
<html><body>It is now {{ current_date }}.</body></html>
Refresh the page in your Web browser, and you should see the fully rendered page.
鍦ㄧ綉椤垫祻瑙堝櫒涓埛鏂拌椤碉紝浣犲皢浼氱湅鍒板畬鏁磋В鏋愬悗鐨勯〉闈€
Because its such a common idiom to load a template, fill a Context , and return an HttpResponse object with the result of the rendered template, Django provides a shortcut that lets you do those things in one line of code. This shortcut is a function called render_to_response() , which lives in the module django.shortcuts . Most of the time, youll be using render_to_response() rather than loading templates and creating Context and HttpResponse objects manually.
鐢变簬鍔犺浇妯℃澘銆佸~鍏 context 銆佸皢缁忚В鏋愮殑妯℃澘缁撴灉杩斿洖涓 HttpResponse 瀵硅薄杩欎竴绯诲垪鎿嶄綔瀹炲湪澶父鐢ㄤ簡锛孌jango 鎻愪緵浜嗕竴鏉′粎鐢ㄤ竴琛屼唬鐮佸氨瀹屾垚鎵鏈夎繖浜涘伐浣滅殑鎹峰緞銆傝鎹峰緞灏辨槸浣嶄簬 django.shortcuts 妯″潡涓悕涓 render_to_response() 鐨勫嚱鏁般傚ぇ澶氭暟鏃跺欙紝浣犲皢浣跨敤 render_to_response() 锛岃屼笉鏄墜鍔ㄥ姞杞芥ā鏉裤佸垱寤 Context 鍜 HttpResponse 瀵硅薄銆
Heres the ongoing current_datetime example rewritten to use render_to_response() :
涓嬮潰灏辨槸浣跨敤 render_to_response() 閲嶆柊缂栧啓杩囩殑 current_datetime 鑼冧緥銆
from django.shortcuts import render_to_response import datetime def current_datetime(request): now = datetime.datetime.now() return render_to_response('current_datetime.html', {'current_date': now})
What a difference! Lets step through the code changes:
澶у彉鏍蜂簡锛佽鎴戜滑閫愬彞鐪嬬湅浠g爜鍙戠敓鐨勫彉鍖栵細
We no longer have to import get_template , Template , Context , or HttpResponse . Instead, we import django.shortcuts.render_to_response . The import datetime remains.
鎴戜滑涓嶅啀闇瑕佸鍏 get_template 銆 Template 銆 Context 鍜 HttpResponse 銆傜浉鍙嶏紝鎴戜滑瀵煎叆 django.shortcuts.render_to_response 銆 import datetime 缁х画淇濈暀.
Within the current_datetime function, we still calculate now , but the template loading, context creation, template rendering, and HttpResponse creation is all taken care of by the render_to_response() call. Because render_to_response() returns an HttpResponse object, we can simply return that value in the view.
鍦 current_datetime 鍑芥暟涓紝鎴戜滑浠嶇劧杩涜 now 璁$畻锛屼絾妯℃澘鍔犺浇銆佷笂涓嬫枃鍒涘缓銆佹ā鏉胯В鏋愬拰 HttpResponse 鍒涘缓宸ヤ綔鍧囧湪瀵 render_to_response() 鐨勮皟鐢ㄤ腑瀹屾垚浜嗐傜敱浜 render_to_response() 杩斿洖 HttpResponse 瀵硅薄锛屽洜姝ゆ垜浠粎闇鍦ㄨ鍥句腑 return 璇ュ笺
The first argument to render_to_response() should be the name of the template to use. The second argument, if given, should be a dictionary to use in creating a Context for that template. If you dont provide a second argument, render_to_response() will use an empty dictionary.
render_to_response() 鐨勭涓涓弬鏁板繀椤绘槸瑕佷娇鐢ㄧ殑妯℃澘鍚嶇О銆傚鏋滆缁欏畾绗簩涓弬鏁帮紝閭d箞璇ュ弬鏁板繀椤绘槸涓鸿妯℃澘鍒涘缓 Context 鏃舵墍浣跨敤鐨勫瓧鍏搞傚鏋滀笉鎻愪緵绗簩涓弬鏁帮紝 render_to_response() 浣跨敤涓涓┖瀛楀吀銆
Consider our latest incarnation of current_datetime :
鎬濊冧竴涓嬫垜浠 current_datetime 鐨勬渶鍚庝竴娆¤祴鍊:
def current_datetime(request): now = datetime.datetime.now() return render_to_response('current_datetime.html', {'current_date': now})
Many times, as in this example, youll find yourself calculating some values, storing them in variables (e.g., now in the preceding code), and sending those variables to the template. Particularly lazy programmers should note that its slightly redundant to have to give names for temporary variables and give names for the template variables. Not only is it redundant, but also its extra typing.
寰堝鏃跺欙紝灏卞儚鍦ㄨ繖涓寖渚嬩腑閭f牱锛屼綘鍙戠幇鑷繁涓鐩村湪璁$畻鏌愪釜鍙橀噺锛屼繚瀛樼粨鏋滃埌鍙橀噺涓紙姣斿锛氬墠闈唬鐮佷腑鐨 now 锛夛紝鐒跺悗灏嗚繖浜涘彉閲忓彂閫佺粰妯℃澘銆傜壒鍒噿鐨勭▼搴忓憳鍙兘娉ㄦ剰鍒扮粰杩欎簺涓存椂鍙橀噺 鍜 妯℃澘鍙橀噺鍛藉悕鏄惧緱鏈夌偣澶氫綑銆備笉浣嗗浣欙紝鑰屼笖杩樿杩涜棰濆鐨勯敭鐩樿緭鍏ャ
So if youre one of those lazy programmers and you like keeping code particularly concise, you can take advantage of a built-in Python function called locals() . It returns a dictionary mapping all local variable names to their values. Thus, the preceding view could be rewritten like so:
濡傛灉浣犳槸涓枩娆㈠伔鎳掔殑绋嬪簭鍛樺苟鎯宠浠g爜鐪嬭捣鏉ユ洿鍔犵畝鏄庯紝鍙互鍒╃敤 Python 鐨勫唴寤哄嚱鏁 locals() 銆傚畠杩斿洖鐨勫瓧鍏稿鎵鏈夊眬閮ㄥ彉閲忕殑鍚嶇О涓庡艰繘琛屾槧灏勩傚洜姝わ紝鍓嶉潰鐨勮鍥惧彲浠ラ噸鍐欐垚涓嬮潰杩欎釜鏍峰瓙锛
def current_datetime(request): current_date = datetime.datetime.now() return render_to_response('current_datetime.html', locals())
Here, instead of manually specifying the context dictionary as before, we pass the value of locals() , which will include all variables defined at that point in the functions execution. As a consequence, weve renamed the now variable to current_date , because thats the variable name that the template expects. In this example, locals() doesnt offer a huge improvement, but this technique can save you some typing if you have several template variables to defineor if youre lazy.
鍦ㄦ锛屾垜浠病鏈夊儚涔嬪墠閭f牱鎵嬪伐鎸囧畾 context 瀛楀吀锛岃屾槸浼犲叆浜 locals() 鐨勫硷紝瀹冨泭鎷簡鍑芥暟鎵ц鍒拌鏃堕棿鐐规椂鎵瀹氫箟鐨勪竴鍒囧彉閲忋傚洜姝わ紝鎴戜滑灏 now 鍙橀噺閲嶅懡鍚嶄负 current_date 锛屽洜涓洪偅鎵嶆槸妯℃澘鎵棰勬湡鐨勫彉閲忓悕绉般傚湪鏈緥涓紝 locals() 骞舵病鏈夊甫鏉ュ 澶 鐨勬敼杩涳紝浣嗘槸濡傛灉鏈夊涓ā鏉垮彉閲忚鐣屽畾鑰屼綘鍙堟兂鍋锋噿锛岃繖绉嶆妧鏈彲浠ュ噺灏戜竴浜涢敭鐩樿緭鍏ャ
One thing to watch out for when using locals() is that it includes every local variable, which may comprise more variables than you actually want your template to have access to. In the previous example, locals() will also include request . Whether this matters to you depends on your application.
浣跨敤 locals() 鏃惰娉ㄦ剰鏄畠灏嗗寘鎷 鎵鏈 鐨勫眬閮ㄥ彉閲忥紝缁勬垚瀹冪殑鍙橀噺鍙兘姣斾綘鎯宠妯℃澘璁块棶鐨勮澶氥傚湪鍓嶄緥涓紝 locals() 杩樺寘鍚簡 request 銆傚姝ゅ浣曞彇鑸嶅彇鍐充綘鐨勫簲鐢ㄧ▼搴忋
A final thing to consider is that locals() incurs a small bit of overhead, because when you call it, Python has to create the dictionary dynamically. If you specify the context dictionary manually, you avoid this overhead.
鏈鍚庤鑰冭檻鐨勬槸鍦ㄤ綘璋冪敤 locals() 鏃讹紝Python 蹇呴』寰楀姩鎬佸垱寤哄瓧鍏革紝鍥犳瀹冧細甯︽潵涓鐐归澶栫殑寮閿銆傚鏋滄墜鍔ㄦ寚瀹 context 瀛楀吀锛屽垯鍙互閬垮厤杩欑寮閿銆
It can get unwieldy to store all of your templates in a single directory. You might like to store templates in subdirectories of your template directory, and thats fine. In fact, we recommend doing so; some more advanced Django features (such as the generic views system, which we cover in Chapter 9) expect this template layout as a default convention.
鎶婃墍鏈夌殑妯℃澘閮藉瓨鏀惧湪涓涓洰褰曚笅鍙兘浼氳浜嬫儏鍙樺緱闅句互鎺屾帶銆備綘鍙兘浼氳冭檻鎶婃ā鏉垮瓨鏀惧湪浣犳ā鏉跨洰褰曠殑瀛愮洰褰曚腑锛岃繖闈炲父濂姐備簨瀹炰笂锛屾垜浠帹鑽愯繖鏍峰仛锛涗竴浜汥jango鐨勯珮绾х壒鎬э紙渚嬪灏嗗湪绗節绔犺鍒扮殑閫氱敤瑙嗗浘绯荤粺锛夌殑缂虹渷绾﹀畾灏辨槸鏈熸湜浣跨敤杩欑妯℃澘甯冨眬銆
Storing templates in subdirectories of your template directory is easy. In your calls to get_template() , just include the subdirectory name and a slash before the template name, like so:
鎶婃ā鏉垮瓨鏀句簬妯℃澘鐩綍鐨勫瓙鐩綍涓槸浠跺緢杞绘澗鐨勪簨鎯呫傚彧闇鍦ㄨ皟鐢 get_template() 鏃讹紝鎶婂瓙鐩綍鍚嶅拰涓鏉℃枩鏉犳坊鍔犲埌妯℃澘鍚嶇О涔嬪墠锛屽锛
t = get_template('dateapp/current_datetime.html')
Because render_to_response() is a small wrapper around get_template() , you can do the same thing with the first argument to render_to_response() .
鐢变簬 render_to_response() 鍙槸瀵 get_template() 鐨勭畝鍗曞皝瑁咃紝 浣犲彲浠ュ render_to_response() 鐨勭涓涓弬鏁板仛鐩稿悓澶勭悊銆
Theres no limit to the depth of your subdirectory tree. Feel free to use as many as you like.
瀵瑰瓙鐩綍鏍戠殑娣卞害娌℃湁闄愬埗锛屼綘鎯宠澶氬皯灞傞兘鍙互銆
Note
娉ㄦ剰
Windows users, be sure to use forward slashes rather than backslashes. get_template() assumes a Unix-style file name designation.
Windows鐢ㄦ埛蹇呴』浣跨敤鏂滄潬鑰屼笉鏄弽鏂滄潬銆 get_template() 鍋囧畾鐨勬槸 Unix 椋庢牸鐨勬枃浠跺悕绗﹀彿绾﹀畾銆
Now that weve covered the template-loading mechanism, we can introduce a built-in template tag that takes advantage of it: {% include %} . This tag allows you to include the contents of another template. The argument to the tag should be the name of the template to include, and the template name can be either a variable or a hard-coded (quoted) string, in either single or double quotes. Anytime you have the same code in multiple templates, consider using an {% include %} to remove the duplication.
鍦ㄨ瑙d簡妯℃澘鍔犺浇鏈哄埗涔嬪悗锛屾垜浠啀浠嬬粛涓涓埄鐢ㄨ鏈哄埗鐨勫唴寤烘ā鏉挎爣绛撅細 {% include %} 銆傝鏍囩鍏佽鍦紙妯℃澘涓級鍖呭惈鍏跺畠鐨勬ā鏉跨殑鍐呭銆傛爣绛剧殑鍙傛暟鏄墍瑕佸寘鍚殑妯℃澘鍚嶇О锛屽彲浠ユ槸涓涓彉閲忥紝涔熷彲浠ユ槸鐢ㄥ崟/鍙屽紩鍙风‖缂栫爜鐨勫瓧绗︿覆銆傛瘡褰撳湪澶氫釜妯℃澘涓嚭鐜扮浉鍚岀殑浠g爜鏃讹紝灏卞簲璇ヨ冭檻鏄惁瑕佷娇鐢 {% include %} 鏉ュ噺灏戦噸澶嶃
These two examples include the contents of the template nav.html . The examples are equivalent and illustrate that either single or double quotes are allowed:
涓嬮潰杩欎袱涓緥瀛愰兘鍖呭惈浜 nav.html 妯℃澘銆備袱涓緥瀛愮殑浣滅敤瀹屽叏鐩稿悓锛屽彧涓嶈繃鏄负浜嗚鏄庡崟銆佸弻寮曞彿閮藉彲浠ラ氱敤銆
{% include 'nav.html' %} {% include "nav.html" %}
This example includes the contents of the template includes/nav.html :
涓嬮潰鐨勪緥瀛愬寘鍚簡 includes/nav.html 妯℃澘鐨勫唴瀹:
{% include 'includes/nav.html' %}
This example includes the contents of the template whose name is contained in the variable template_name :
涓嬮潰鐨勪緥瀛愬寘鍚簡浠ュ彉閲 template_name 鐨勫间负鍚嶇О鐨勬ā鏉垮唴瀹癸細
{% include template_name %}
As in get_template() , the file name of the template is determined by adding the template directory from TEMPLATE_DIRS to the requested template name.
鍜屽湪 get_template() 涓竴鏍凤紝 瀵规ā鏉跨殑鏂囦欢鍚嶈繘琛屽垽鏂椂浼氬湪鎵璋冨彇鐨勬ā鏉垮悕绉颁箣鍓嶅姞涓婃潵鑷 TEMPLATE_DIRS 鐨勬ā鏉跨洰褰曘
Included templates are evaluated with the context of the template thats including them.
鎵鍖呭惈鐨勬ā鏉挎墽琛屾椂鐨 context 鍜屽寘鍚畠浠殑妯℃澘鏄竴鏍风殑銆
If a template with the given name isnt found, Django will do one of two things:
濡傛灉鏈壘鍒扮粰瀹氬悕绉扮殑妯℃澘鏂囦欢锛孌jango 浼氫粠浠ヤ笅涓や欢浜嬫儏涓嫨涓鑰屼负涔嬶細
If DEBUG is set to True , youll see the TemplateDoesNotExist exception on a Django error page.
濡傛灉 DEBUG 璁剧疆涓 True 锛屼綘灏嗕細鍦 Django 閿欒淇℃伅椤甸潰鐪嬪埌 TemplateDoesNotExist 寮傚父銆
If DEBUG is set to False , the tag will fail silently, displaying nothing in the place of the tag.
濡傛灉 DEBUG 璁剧疆涓 False 锛岃鏍囩涓嶄細寮曞彂閿欒淇℃伅锛屽湪鏍囩浣嶇疆涓嶆樉绀轰换浣曚笢瑗裤
Our template examples so far have been tiny HTML snippets, but in the real world, youll be using Djangos template system to create entire HTML pages. This leads to a common Web development problem: across a Web site, how does one reduce the duplication and redundancy of common page areas, such as sitewide navigation?
鍒扮洰鍓嶄负姝紝鎴戜滑鐨勬ā鏉胯寖渚嬮兘鍙槸浜涢浂鏄熺殑 HTML 鐗囨锛屼絾鍦ㄥ疄闄呭簲鐢ㄤ腑锛屼綘灏嗙敤 Django 妯℃澘绯荤粺鏉ュ垱寤烘暣涓 HTML 椤甸潰銆傝繖灏卞甫鏉ヤ竴涓父瑙佺殑 Web 寮鍙戦棶棰橈細鍦ㄦ暣涓綉绔欎腑锛屽浣曞噺灏戝叡鐢ㄩ〉闈㈠尯鍩燂紙姣斿绔欑偣瀵艰埅锛夋墍寮曡捣鐨勯噸澶嶅拰鍐椾綑浠g爜锛
A classic way of solving this problem is to use server-side includes , directives you can embed within your HTML pages to include one Web page inside another. Indeed, Django supports that approach, with the {% include %} template tag just described. But the preferred way of solving this problem with Django is to use a more elegant strategy called template inheritance .
瑙e喅璇ラ棶棰樼殑浼犵粺鍋氭硶鏄娇鐢 鏈嶅姟鍣ㄧ鐨 includes 锛屼綘鍙互鍦 HTML 椤甸潰涓娇鐢ㄨ鎸囦护灏嗕竴涓綉椤靛祵鍏ュ埌鍙︿竴涓腑銆備簨瀹炰笂锛 Django 閫氳繃鍒氭墠璁茶堪鐨 {% include %} 鏀寔浜嗚繖绉嶆柟娉曘備絾鏄敤 Django 瑙e喅姝ょ被闂鐨勯閫夋柟娉曟槸浣跨敤鏇村姞绠娲佺殑绛栫暐鈥斺 妯℃澘缁ф壙 銆
In essence, template inheritance lets you build a base skeleton template that contains all the common parts of your site and defines blocks that child templates can override.
鏈川涓婃潵璇达紝妯℃澘缁ф壙灏辨槸鍏堟瀯閫犱竴涓熀纭妗嗘灦妯℃澘锛岃屽悗鍦ㄥ叾瀛愭ā鏉夸腑瀵瑰畠鎵鍖呭惈绔欑偣鍏敤閮ㄥ垎鍜屽畾涔夊潡杩涜閲嶈浇銆
Lets see an example of this by creating a more complete template for our current_datetime view, by editing the current_datetime.html file:
璁╂垜浠氳繃淇敼 current_datetime.html 鏂囦欢锛屼负 current_datetime 鍒涘缓涓涓洿鍔犲畬鏁寸殑妯℃澘鏉ヤ綋浼氫竴涓嬭繖绉嶅仛娉曪細
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> <title>The current time</title> </head> <body> <h1>My helpful timestamp site</h1> <p>It is now {{ current_date }}.</p> <hr> <p>Thanks for visiting my site.</p> </body> </html>
That looks just fine, but what happens when we want to create a template for another viewsay, the hours_ahead view from Chapter 3? If we want again to make a nice, valid, full HTML template, wed create something like:
杩欑湅璧锋潵寰堟锛屼絾濡傛灉鎴戜滑瑕佷负绗笁绔犵殑 hours_ahead 瑙嗗浘鍒涘缓鍙︿竴涓ā鏉夸細鍙戠敓浠涔堜簨鎯呭憿锛熷鏋滄垜浠啀娆″垱寤轰竴涓紓浜佹湁鏁堜笖瀹屾暣鐨 HTML 妯℃澘锛屾垜浠彲鑳戒細鍒涘缓鍑轰笅闈㈣繖鏍风殑涓滆タ锛
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> <title>Future time</title> </head> <body> <h1>My helpful timestamp site</h1> <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p> <hr> <p>Thanks for visiting my site.</p> </body> </html>
Clearly, weve just duplicated a lot of HTML. Imagine if we had a more typical site, including a navigation bar, a few style sheets, perhaps some JavaScriptwed end up putting all sorts of redundant HTML into each template.
寰堟槑鏄撅紝鎴戜滑鍒氭墠閲嶅浜嗗ぇ閲忕殑 HTML 浠g爜銆傛兂璞′竴涓嬶紝濡傛灉鏈変竴涓洿鍏稿瀷鐨勭綉绔欙紝瀹冩湁瀵艰埅鏉°佹牱寮忚〃锛屽彲鑳借繕鏈変竴浜 JavaScript 浠g爜锛屼簨鎯呭繀灏嗕互鍚戞瘡涓ā鏉垮~鍏呭悇绉嶅啑浣欑殑 HTML 鑰屽憡缁堛
The server-side include solution to this problem is to factor out the common bits in both templates and save them in separate template snippets, which are then included in each template. Perhaps youd store the top bit of the template in a file called header.html :
瑙e喅杩欎釜闂鐨勬湇鍔″櫒绔 include 鏂规鏄壘鍑轰袱涓ā鏉夸腑鐨勫叡鍚岄儴鍒嗭紝灏嗗叾淇濆瓨涓轰笉鍚岀殑妯℃澘鐗囨锛岀劧鍚庡湪姣忎釜妯℃澘涓繘琛 include銆備篃璁镐綘浼氭妸妯℃澘澶撮儴鐨勪竴浜涗唬鐮佷繚瀛樹负 header.html 鏂囦欢锛
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head>
And perhaps youd store the bottom bit in a file called footer.html :
浣犲彲鑳戒細鎶婂簳閮ㄤ繚瀛樺埌鏂囦欢 footer.html :
<hr> <p>Thanks for visiting my site.</p> </body> </html>
With an include-based strategy, headers and footers are easy. Its the middle ground thats messy. In this example, both pages feature a title <h1>My helpful timestamp site</h1> but that title cant fit into header.html because the <title> on both pages is different. If we included the <h1> in the header, wed have to include the <title> , which wouldnt allow us to customize it per page. See where this is going?
瀵瑰熀浜 include 鐨勭瓥鐣ワ紝澶撮儴鍜屽簳閮ㄧ殑鍖呭惈寰堢畝鍗曘傞夯鐑︾殑鏄腑闂撮儴鍒嗐傚湪姝よ寖渚嬩腑锛屾瘡涓〉闈㈤兘鏈変竴涓 <h1>My helpful timestamp site</h1> 鏍囬锛屼絾鏄繖涓爣棰樹笉鑳芥斁鍦 header.html 涓紝鍥犱负姣忎釜椤甸潰鐨 <title> 鏄笉鍚岀殑銆傚鏋滄垜浠皢 <h1> 鍖呭惈鍦ㄥご閮紝鎴戜滑灏变笉寰椾笉鍖呭惈 <title> 锛屼絾杩欐牱鍙堜笉鍏佽鍦ㄦ瘡涓〉闈㈠瀹冭繘琛屽畾鍒躲備綍鍘讳綍浠庡憿锛
Djangos template inheritance system solves these problems. You can think of it as an inside-out version of server-side includes. Instead of defining the snippets that are common , you define the snippets that are different .
Django 鐨勬ā鏉跨户鎵跨郴缁熻В鍐充簡杩欎簺闂銆備綘鍙互灏嗗叾瑙嗕负鏈嶅姟鍣ㄧ include 鐨勯嗗悜鎬濈淮鐗堟湰銆備綘鍙互瀵归偅浜 涓嶅悓 鐨勪唬鐮佹杩涜瀹氫箟锛岃屼笉鏄 鍏卞悓 浠g爜娈点
The first step is to define a base template a skeleton of your page that child templates will later fill in. Heres a base template for our ongoing example:
绗竴姝ユ槸瀹氫箟 鍩虹妯℃澘 锛 璇ユ鏋朵箣鍚庡皢鐢 瀛愭ā鏉 鎵缁ф壙銆備互涓嬫槸鎴戜滑鐩墠鎵璁茶堪鑼冧緥鐨勫熀纭妯℃澘锛
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> <title>{% block title %}{% endblock %}</title> </head> <body> <h1>My helpful timestamp site</h1> {% block content %}{% endblock %} {% block footer %} <hr> <p>Thanks for visiting my site.</p> {% endblock %} </body> </html>
This template, which well call base.html , defines a simple HTML skeleton document that well use for all the pages on the site. Its the job of child templates to override, or add to, or leave alone the contents of the blocks. (If youre following along at home, save this file to your template directory.)
杩欎釜鍙仛 base.html 鐨勬ā鏉垮畾涔変簡涓涓畝鍗曠殑 HTML 妗嗘灦鏂囨。锛屾垜浠皢鍦ㄦ湰绔欑偣鐨勬墍鏈夐〉闈腑浣跨敤銆傚瓙妯℃澘鐨勪綔鐢ㄥ氨鏄噸杞姐佹坊鍔犳垨淇濈暀閭d簺鍧楃殑鍐呭銆傦紙濡傛灉涓鐩存寜鎴戜滑鐨勮寖渚嬪仛璇濓紝璇峰皢姝ゆ枃浠朵繚瀛樺埌妯℃澘鐩綍銆傦級
Were using a template tag here that you havent seen before: the {% block %} tag. All the {% block %} tags do is tell the template engine that a child template may override those portions of the template.
鎴戜滑浣跨敤涓涓互鍓嶆病鏈夎杩囩殑妯℃澘鏍囩锛 {% block %} 銆 鎵鏈夌殑 {% block %} 鏍囩鍛婅瘔妯℃澘寮曟搸锛屽瓙妯℃澘鍙互閲嶈浇杩欎簺閮ㄥ垎銆
Now that we have this base template, we can modify our existing current_datetime.html template to use it:
鐜板湪鎴戜滑宸茬粡鏈変簡涓涓熀鏈ā鏉匡紝鎴戜滑鍙互淇敼 current_datetime.html 妯℃澘鏉 浣跨敤瀹冿細
{% extends "base.html" %} {% block title %}The current time{% endblock %} {% block content %} <p>It is now {{ current_date }}.</p> {% endblock %}
While were at it, lets create a template for the hours_ahead view from Chapter 3. (If youre following along with code, well leave it up to you to change hours_ahead to use the template system.) Heres what that would look like:
鍐嶄负 hours_ahead 瑙嗗浘鍒涘缓涓涓ā鏉匡紝鐪嬭捣鏉ユ槸杩欐牱鐨勶細
{% extends "base.html" %} {% block title %}Future time{% endblock %} {% block content %} <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p> {% endblock %}
Isnt this beautiful? Each template contains only the code thats unique to that template. No redundancy needed. If you need to make a site-wide design change, just make the change to base.html , and all of the other templates will immediately reflect the change.
鐪嬭捣鏉ュ緢婕備寒鏄笉鏄紵姣忎釜妯℃澘鍙寘鍚鑷繁鑰岃█ 鐙竴鏃犱簩 鐨勪唬鐮併傛棤闇澶氫綑鐨勯儴鍒嗐傚鏋滄兂杩涜绔欑偣绾х殑璁捐淇敼锛屼粎闇淇敼 base.html 锛屾墍鏈夊叾瀹冩ā鏉夸細绔嬪嵆鍙嶆槧鍑烘墍浣滀慨鏀广
Heres how it works. When you load the template current_datetime.html , the template engine sees the {% extends %} tag, noting that this template is a child template. The engine immediately loads the parent templatein this case, base.html .
浠ヤ笅鏄叾宸ヤ綔鏂瑰紡銆傚湪鍔犺浇 current_datetime.html 妯℃澘鏃讹紝妯℃澘寮曟搸鍙戠幇浜 {% extends %} 鏍囩锛 娉ㄦ剰鍒拌妯℃澘鏄竴涓瓙妯℃澘銆傛ā鏉垮紩鎿庣珛鍗宠杞藉叾鐖舵ā鏉匡紝鍗虫湰渚嬩腑鐨 base.html 銆
At that point, the template engine notices the three {% block %} tags in base.html and replaces those blocks with the contents of the child template. So, the title weve defined in {% block title %} will be used, as will the {% block content %} .
姝ゆ椂锛屾ā鏉垮紩鎿庢敞鎰忓埌 base.html 涓殑涓変釜 {% block %} 鏍囩锛屽苟鐢ㄥ瓙妯℃澘鐨勫唴瀹规浛鎹㈣繖浜 block 銆傚洜姝わ紝寮曟搸灏嗕細浣跨敤鎴戜滑鍦 { block title %} 涓畾涔夌殑鏍囬锛屽 {% block content %} 涔熸槸濡傛銆
Note that since the child template doesnt define the footer block, the template system uses the value from the parent template instead. Content within a {% block %} tag in a parent template is always used as a fallback.
娉ㄦ剰鐢变簬瀛愭ā鏉垮苟娌℃湁瀹氫箟 footer 鍧楋紝妯℃澘绯荤粺灏嗕娇鐢ㄥ湪鐖舵ā鏉夸腑瀹氫箟鐨勫笺傜埗妯℃澘 {% block %} 鏍囩涓殑鍐呭鎬绘槸琚綋浣滀竴鏉¢璺
Inheritance doesnt affect the way the context works, and you can use as many levels of inheritance as needed. One common way of using inheritance is the following three-level approach:
缁ф壙骞朵笉鏀瑰彉 context 鐨勫伐浣滄柟寮忥紝鑰屼笖浣犲彲浠ユ寜鐓ч渶瑕佷娇鐢ㄥ灞傜户鎵裤備娇鐢ㄧ户鎵跨殑涓绉嶅父瑙佹柟寮忔槸涓嬮潰鐨勪笁灞傛硶锛
Create a base.html template that holds the main look and feel of your site. This is the stuff that rarely, if ever, changes.
鍒涘缓 base.html 妯℃澘锛屽湪鍏朵腑瀹氫箟绔欑偣鐨勪富瑕佸瑙傛劅鍙椼傝繖浜涢兘鏄笉甯镐慨鏀圭敋鑷充粠涓嶄慨鏀圭殑閮ㄥ垎銆
Create a base_SECTION.html template for each section of your site (e.g., base_photos.html and base_forum.html ). These templates extend base.html and include section-specific styles/design.
涓虹綉绔欑殑姣忎釜鍖哄煙鍒涘缓 base_SECTION.html 妯℃澘(渚嬪, base_photos.html 鍜 base_forum.html )銆傝繖浜涙ā鏉垮 base.html 杩涜鎷撳睍锛屽苟鍖呭惈鍖哄煙鐗瑰畾鐨勯鏍间笌璁捐銆
Create individual templates for each type of page, such as a forum page or a photo gallery. These templates extend the appropriate section template.
涓烘瘡绉嶇被鍨嬬殑椤甸潰鍒涘缓鐙珛鐨勬ā鏉匡紝渚嬪璁哄潧椤甸潰鎴栬呭浘鐗囧簱銆傝繖浜涙ā鏉挎嫇灞曠浉搴旂殑鍖哄煙妯℃澘銆
This approach maximizes code reuse and makes it easy to add items to shared areas, such as section-wide navigation.
杩欎釜鏂规硶鍙渶澶ч檺搴﹀湴閲嶇敤浠g爜锛屽苟浣垮緱鍚戝叕鍏卞尯鍩燂紙濡傚尯鍩熺骇鐨勫鑸級娣诲姞鍐呭鎴愪负涓浠惰交鏉剧殑宸ヤ綔銆
Here are some tips for working with template inheritance:
浠ヤ笅鏄娇鐢ㄦā鏉跨户鎵跨殑涓浜涜瘈绐嶏細
If you use {% extends %} in a template, it must be the first template tag in that template. Otherwise, template inheritance wont work.
濡傛灉鍦ㄦā鏉夸腑浣跨敤 {% extends %} 锛屽繀椤讳繚璇佸叾涓烘ā鏉夸腑鐨勭涓涓ā鏉挎爣璁般傚惁鍒欙紝妯℃澘缁ф壙灏嗕笉璧蜂綔鐢ㄣ
Generally, the more {% block %} tags in your base templates, the better. Remember, child templates dont have to define all parent blocks, so you can fill in reasonable defaults in a number of blocks, and then define only the ones you need in the child templates. Its better to have more hooks than fewer hooks.
涓鑸潵璇达紝鍩虹妯℃澘涓殑 {% block %} 鏍囩瓒婂瓒婂ソ銆傝浣忥紝瀛愭ā鏉夸笉蹇呭畾涔夌埗妯℃澘涓墍鏈夌殑浠g爜鍧楋紝鍥犳浣犲彲浠ョ敤鍚堢悊鐨勭己鐪佸煎涓浜涗唬鐮佸潡杩涜濉厖锛岀劧鍚庡彧瀵瑰瓙妯℃澘鎵闇鐨勪唬鐮佸潡杩涜锛堥噸锛夊畾涔夈備織璇濊锛岄挬瀛愯秺澶氳秺濂姐
If you find yourself duplicating code in a number of templates, it probably means you should move that code to a {% block %} in a parent template.
濡傛灉鍙戣鑷繁鍦ㄥ涓ā鏉夸箣闂存嫹璐濅唬鐮侊紝浣犲簲璇ヨ冭檻灏嗚浠g爜娈垫斁缃埌鐖舵ā鏉跨殑鏌愪釜 {% block %} 涓
If you need to get the content of the block from the parent template, the {{ block.super }} variable will do the trick. This is useful if you want to add to the contents of a parent block instead of completely overriding it.
濡傛灉闇瑕佽幏寰楃埗妯℃澘涓唬鐮佸潡鐨勫唴瀹癸紝鍙互浣跨敤 {{ block.super }} 鍙橀噺銆傚鏋滃彧鎯冲湪涓婄骇浠g爜鍧楀熀纭涓婃坊鍔犲唴瀹癸紝鑰屼笉鏄叏閮ㄩ噸杞斤紝璇ュ彉閲忓氨鏄惧緱闈炲父鏈夌敤浜嗐
You may not define multiple {% block %} tags with the same name in the same template. This limitation exists because a block tag works in both directions. That is, a block tag doesnt just provide a hole to fill, it also defines the content that fills the hole in the parent . If there were two similarly named {% block %} tags in a template, that templates parent wouldnt know which one of the blocks content to use.
涓嶅彲鍚屼竴涓ā鏉夸腑瀹氫箟澶氫釜鍚屽悕鐨 {% block %} 銆傚瓨鍦ㄨ繖鏍风殑闄愬埗鏄洜涓篵lock 鏍囩鐨勫伐浣滄柟寮忔槸鍙屽悜鐨勩備篃灏辨槸璇达紝block 鏍囩涓嶄粎鎸栦簡涓涓濉殑鍧戯紝涔熷畾涔変簡鍦 鐖 妯℃澘涓繖涓潙鎵濉厖鐨勫唴瀹广傚鏋滄ā鏉夸腑鍑虹幇浜嗕袱涓浉鍚屽悕绉扮殑 {% block %} 鏍囩锛岀埗妯℃澘灏嗘棤浠庡緱鐭ヨ浣跨敤鍝釜鍧楃殑鍐呭銆
The template name you pass to {% extends %} is loaded using the same method that get_template() uses. That is, the template name is appended to your TEMPLATE_DIRS setting.
{% extends %} 瀵规墍浼犲叆妯℃澘鍚嶇О浣跨敤鐨勫姞杞芥柟娉曞拰 get_template() 鐩稿悓銆備篃灏辨槸璇达紝浼氬皢妯℃澘鍚嶇О琚坊鍔犲埌 TEMPLATE_DIRS 璁剧疆涔嬪悗銆
In most cases, the argument to {% extends %} will be a string, but it can also be a variable, if you dont know the name of the parent template until runtime. This lets you do some cool, dynamic stuff.
澶氭暟鎯呭喌涓嬶紝 {% extends %} 鐨勫弬鏁板簲璇ユ槸瀛楃涓诧紝浣嗘槸濡傛灉鐩村埌杩愯鏃舵柟鑳界‘瀹氱埗妯℃澘鍚嶏紝杩欎釜鍙傛暟涔熷彲浠ユ槸涓彉閲忋傝繖浣垮緱浣犺兘澶熷疄鐜颁竴浜涘緢閰风殑鍔ㄦ佸姛鑳姐
Most modern Web sites are database-driven : the content of the Web site is stored in a relational database. This allows a clean separate of data and logic (in the same way views and templates allow the separation of logic and display.)
鏃朵笅澶у鏁扮綉绔欓兘鏄 鏁版嵁搴撻┍鍔 鐨勶細缃戠珯鐨勫唴瀹归兘鏄瓨鍌ㄥ湪鍏崇郴鍨嬫暟鎹簱涓傝繖浣垮緱鏁版嵁鍜岄昏緫鑳藉褰诲簳鍦板垎寮锛堣鍥惧拰妯℃澘涔熶互鍚屾牱鏂瑰紡瀵归昏緫鍜屾樉绀鸿繘琛屼簡鍒嗛殧銆傦級
The next chapter covers the tools Django gives you to interact with a database.
鍦ㄤ笅涓绔犻噷灏嗚杩 Django 鎻愪緵鐨勬暟鎹簱浜や簰宸ュ叿銆
鍏充簬鏈瘎娉ㄧ郴缁
鏈珯浣跨敤涓婁笅鏂囧叧鑱旂殑璇勬敞绯荤粺鏉ユ敹闆嗗弽棣堜俊鎭備笉鍚屼簬涓鑸鏁寸珷鍋氳瘎娉ㄧ殑鍋氭硶锛 鎴戜滑鍏佽浣犲姣忎竴涓嫭绔嬬殑鈥滄枃鏈潡鈥濆仛璇勬敞銆備竴涓滄枃鏈潡鈥濈湅璧锋潵鏄繖鏍风殑锛
涓涓滄枃鏈潡鈥濇槸涓涓钀斤紝涓涓垪琛ㄩ」锛屼竴娈典唬鐮侊紝鎴栬呭叾浠栦竴灏忔鍐呭銆 浣犻変腑瀹冧細楂樹寒搴︽樉绀:
瑕佸鏂囨湰鍧楀仛璇勬敞锛屼綘鍙渶瑕佺偣鍑诲畠鏃佽竟鐨勬爣璇嗗潡:
鎴戜滑浼氫粩缁嗛槄璇绘瘡涓瘎璁猴紝濡傛灉鍙兘鐨勮瘽鎴戜滑涔熶細鎶婅瘎娉ㄨ冭檻鍒版湭鏉ョ殑鐗堟湰涓幓:
濡傛灉浣犳効鎰忎綘鐨勮瘎娉ㄨ閲囩敤锛岃纭繚鐣欎笅浣犵殑鍏ㄥ悕 (娉ㄦ剰涓嶆槸鏄电О鎴栫畝绉帮級
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.