The Django Book

Chapter 10: Extending the Template Engine

绗崄绔: 娣卞叆妯℃澘寮曟搸

Although most of your interactions with Djangos template language will be in the role of template author, you may want to customize and extend the template engine either to make it do something it doesnt already do, or to make your job easier in some other way.

WJmyEN <a href=”http://shdawlkicouq.com/“>shdawlkicouq</a>, [url=http://xhmwoyqzgfmc.com/]xhmwoyqzgfmc[/url], [link=http://ulwsjkuwztds.com/]ulwsjkuwztds[/link], http://zozblfuuryro.com/

This chapter delves deep into the guts of Djangos template system. It covers what you need to know if you plan to extend the system or if youre just curious about how it works.

鏈珷娣卞叆閽荤爺Django鐨勬ā鏉跨郴缁熴傚鏋滀綘鎯虫墿灞曟ā鏉跨郴缁熸垨鑰呭彧鏄瀹冪殑宸ヤ綔鍘熺悊鎰熻鍒板ソ濂囷紝鏈珷娑夊強浜嗕綘闇瑕佷簡瑙g殑涓滆タ.

If youre looking to use the Django template system as part of another application (i.e., without the rest of the framework), make sure to read the Configuring the Template System in Standalone Mode section later in the chapter.

濡傛灉浣犳兂鎶奃jango鐨勬ā鐗堢郴缁熶綔涓哄彟澶栦竴涓簲鐢ㄧ▼搴忕殑涓閮ㄥ垎锛堟瘮濡傦紝浠呬娇鐢╠jango鐨勬ā鏉跨郴缁熻屼笉浣跨敤Django妗嗘灦鐨勫叾浠栭儴鍒嗭級锛岄偅浣犱竴瀹氳璇讳竴涓嬧滈厤缃嫭绔嬫ā寮忎笅鐨勬ā鐗堢郴缁熲濊繖涓鑺傘

Template Language Review

MaxVAp <a href=”http://xsivwbewqmrn.com/“>xsivwbewqmrn</a>, [url=http://gncxzntjqedq.com/]gncxzntjqedq[/url], [link=http://fxbofzrzfowj.com/]fxbofzrzfowj[/link], http://mxccahhxsvoy.com/

First, lets quickly review a number of terms introduced in Chapter 4:

棣栧厛锛岃鎴戜滑蹇熷洖椤句竴涓嬬鍥涚珷浠嬬粛鐨勮嫢骞蹭笓涓氭湳璇

A template is a text document, or a normal Python string, that is marked up using the Django template language. A template can contain block tags and variables.

妯℃澘 鏄竴涓函鏂囨湰鏂囦欢锛屾垨鏄竴涓敤Django妯℃澘璇█鏍囪杩囩殑鏅氱殑Python瀛楃涓诧紝涓涓ā鏉垮彲浠ュ寘鍚尯鍧楁爣绛惧拰鍙橀噺銆

A block tag is a symbol within a template that does something. This definition is deliberately vague. For example, a block tag can produce content, serve as a control structure (an if statement or for loop), grab content from a database, or enable access to other template tags.

鍖哄潡鏍囩 鏄湪涓涓ā鏉块噷闈㈣捣浣滅敤鐨勭殑鏍囪锛岃繖涓畾涔夋晠鎰忚鐨勫緢鍚硦锛屾瘮濡傦紝涓涓 鍖哄潡鏍囩鍙互鐢熸垚鍐呭锛屽彲浠ヤ綔涓轰竴涓帶鍒剁粨鏋勶紙 if 璇彞鎴 for 寰幆锛夛紝 鍙互鑾峰彇鏁版嵁搴撳唴瀹癸紝鎴栬呰闂叾浠栫殑妯℃澘鏍囩銆

Block tags are surrounded by {% and %} :

鍖哄潡鏍囩琚 {%%} 鍖呭惈锛

{% if is_logged_in %}
  Thanks for logging in!
{% else %}
  Please log in.
{% endif %}

A variable is a symbol within a template that outputs a value.

鍙橀噺 鏄竴涓湪妯℃澘閲岀敤鏉ヨ緭鍑哄肩殑鏍囪銆

Variable tags are surrounded by {{ and }} :

636Md6 <a href=”http://htvhlhufywbg.com/“>htvhlhufywbg</a>, [url=http://xborgohwkwvg.com/]xborgohwkwvg[/url], [link=http://wdnbqpxfpopl.com/]wdnbqpxfpopl[/link], http://lmksosgzadaw.com/

My first name is {{ first_name }}. My last name is {{ last_name }}.

A context is a name -> value mapping (similar to a Python dictionary) that is passed to a template.

context 鏄竴涓紶閫掔粰妯℃澘鐨勫悕绉板埌鍊肩殑鏄犲皠锛堢被浼糚ython瀛楀吀锛夈

A template renders a context by replacing the variable holes with values from the context and executing all block tags.

KeBCRa <a href=”http://samdayfjlhom.com/“>samdayfjlhom</a>, [url=http://tqpfosapplax.com/]tqpfosapplax[/url], [link=http://ttkbcaqikqzp.com/]ttkbcaqikqzp[/link], http://hdccvanbqbjx.com/

For more details about the basics of these terms, refer back to Chapter 4.

鍏充簬杩欎簺鍩烘湰姒傚康鏇磋缁嗙殑鍐呭锛岃鍙傝冪鍥涚珷銆

The rest of this chapter discusses ways of extending the template engine. First, though, lets take a quick look at a few internals left out of Chapter 4 for simplicity.

鏈珷鐨勫叾浣欓儴鍒嗚璁轰簡鎵╁睍妯℃澘寮曟搸鐨勬柟娉曘傞鍏堬紝鎴戜滑蹇熺殑鐪嬩竴涓嬬鍥涚珷閬楃暀鐨勫唴瀹广

RequestContext and Context Processors

RequestContext鍜孋ontext澶勭悊鍣

When rendering a template, you need a context. Usually this is an instance of django.template.Context , but Django also comes with a special subclass, django.template.RequestContext , that acts slightly differently. RequestContext adds a bunch of variables to your template context by default things like the HttpRequest object or information about the currently logged-in user.

浣犻渶瑕佷竴娈礳ontext鏉ヨВ鏋愭ā鏉裤備竴鑸儏鍐典笅锛岃繖鏄竴涓 django.template.Context 鐨勫疄渚嬶紝涓嶈繃鍦―jango涓繕鍙互鐢ㄤ竴涓壒娈婄殑瀛愮被锛 django.template.RequestContext 锛岃繖涓繍鐢ㄨ捣鏉ョ◢寰湁浜涗笉鍚屻 RequestContext 榛樿鍦板湪妯℃澘context涓姞鍏ヤ簡涓浜涘彉閲忥紝濡 HttpRequest 瀵硅薄鎴栧綋鍓嶇櫥褰曠敤鎴风殑鐩稿叧淇℃伅銆

Use RequestContext when you dont want to have to specify the same set of variables in a series of templates. For example, consider these four views:

褰撲綘涓嶆兂鍦ㄤ竴绯讳緥妯℃澘涓兘鏄庣‘鎸囧畾涓浜涚浉鍚岀殑鍙橀噺鏃讹紝浣犲簲璇ヤ娇鐢 RequestContext 銆備緥濡傦紝鐪嬩笅闈㈢殑鍥涗釜瑙嗗浘锛

from django.template import loader, Context

def view_1(request):
    # ...
    t = loader.get_template('template1.html')
    c = Context({
        'app': 'My app',
        'user': request.user,
        'ip_address': request.META['REMOTE_ADDR'],
        'message': 'I am view 1.'
    })
    return t.render(c)

def view_2(request):
    # ...
    t = loader.get_template('template2.html')
    c = Context({
        'app': 'My app',
        'user': request.user,
        'ip_address': request.META['REMOTE_ADDR'],
        'message': 'I am the second view.'
    })
    return t.render(c)

def view_3(request):
# ...
    t = loader.get_template('template3.html')
    c = Context({
        'app': 'My app',
        'user': request.user,
        'ip_address': request.META['REMOTE_ADDR'],
        'message': 'I am the third view.'
    })
    return t.render(c)

def view_4(request):
    # ...
    t = loader.get_template('template4.html')
    c = Context({
        'app': 'My app',
        'user': request.user,
        'ip_address': request.META['REMOTE_ADDR'],
        'message': 'I am the fourth view.'
    })
    return t.render(c)

(Note that were deliberately not using the render_to_response() shortcut in these examples were manually loading the templates, constructing the context objects and rendering the templates. Were spelling out all of the steps for the purpose of clarity.)

锛堟敞鎰忥紝鍦ㄨ繖浜涗緥瀛愪腑锛屾垜浠晠鎰 浣跨敤 render_to_response() 杩欎釜蹇嵎鏂规硶锛岃岄夋嫨鎵嬪姩杞藉叆妯℃澘锛屾墜鍔ㄦ瀯閫燾ontext瀵硅薄鐒跺悗娓叉煋妯℃澘銆傛槸涓轰簡鑳藉娓呮櫚鐨勮鏄庢墍鏈夋楠ゃ傦級

Each view passes the same three variables app , user and ip_address to its template. Wouldnt it be nice if we could remove that redundancy?

姣忎釜瑙嗗浘閮界粰妯℃澘浼犲叆浜嗕笁涓浉鍚岀殑鍙橀噺锛 appuserip_address 銆傚鏋滄垜浠兘鎶婅繖浜涘啑浣欏幓鎺変細涓嶄細鐪嬭捣鏉ユ洿濂斤紵

RequestContext and context processors were created to solve this problem. Context processors let you specify a number of variables that get set in each context automatically without you having to specify the variables in each render_to_response() call. The catch is that you have to use RequestContext instead of Context when you render a template.

鍒涘缓 RequestContextcontext澶勭悊鍣 灏辨槸涓轰簡瑙e喅杩欎釜闂銆侰ontext澶勭悊鍣ㄥ厑璁镐綘璁剧疆涓浜涘彉閲忥紝瀹冧滑浼氬湪姣忎釜context涓嚜鍔ㄨ璁剧疆濂斤紝鑰屼笉蹇呮瘡娆¤皟鐢 render_to_response() 鏃堕兘鎸囧畾銆傝鐐瑰氨鏄紝褰撲綘娓叉煋妯℃澘鏃讹紝浣犺鐢 RequestContext 鑰屼笉鏄 Context

The most low-level way of using context processors is to create some processors and pass them to RequestContext . Heres how the above example could be written with context processors:

鏈鐩存帴鐨勫仛娉曟槸鐢╟ontext澶勭悊鍣ㄦ潵鍒涘缓涓浜涘鐞嗗櫒骞朵紶閫掔粰 RequestContext 銆備笂闈㈢殑渚嬪瓙鍙互鐢╟ontext processors鏀瑰啓濡備笅锛

from django.template import loader, RequestContext

def custom_proc(request):
    "A context processor that provides 'app', 'user' and 'ip_address'."
    return {
        'app': 'My app',
        'user': request.user,
        'ip_address': request.META['REMOTE_ADDR']
    }

def view_1(request):
    # ...
    t = loader.get_template('template1.html')
    c = RequestContext(request, {'message': 'I am view 1.'},
            processors=[custom_proc])
    return t.render(c)

def view_2(request):
    # ...
    t = loader.get_template('template2.html')
    c = RequestContext(request, {'message': 'I am the second view.'},
            processors=[custom_proc])
    return t.render(c)

def view_3(request):
    # ...
    t = loader.get_template('template3.html')
    c = RequestContext(request, {'message': 'I am the third view.'},
            processors=[custom_proc])
    return t.render(c)

def view_4(request):
    # ...
    t = loader.get_template('template4.html')
    c = RequestContext(request, {'message': 'I am the fourth view.'},
            processors=[custom_proc])
    return t.render(c)

Lets step through this code:

鎴戜滑鏉ラ氳涓涓嬩唬鐮侊細

  • First, we define a function custom_proc . This is a context processor it takes an HttpRequest object and returns a dictionary of variables to use in the template context. Thats all it does.

  • 棣栧厛锛屾垜浠畾涔変竴涓嚱鏁 custom_proc 銆傝繖鏄竴涓猚ontext澶勭悊鍣紝瀹冩帴鏀朵竴涓 HttpRequest 瀵硅薄锛岀劧鍚庤繑鍥炰竴涓瓧鍏革紝杩欎釜瀛楀吀涓寘鍚簡鍙互鍦ㄦā鏉縞ontext涓娇鐢ㄧ殑鍙橀噺銆傚畠灏卞仛浜嗚繖涔堝銆

  • Weve changed the four view functions to use RequestContext instead of Context . There are two differences in how the context is constructed. One, RequestContext requires the first argument to be an HttpRequest object the one that was passed into the view function in the first place (request ). Two, RequestContext takes an optional processors argument, which is a list or tuple of context processor functions to use. Here, we pass in custom_proc , the custom processor we defined above.

  • 鎴戜滑鍦ㄨ繖鍥涗釜瑙嗗浘鍑芥暟涓敤 RequestContext 浠f浛浜 Context 銆傚湪context瀵硅薄鐨勬瀯寤轰笂鏈変袱涓笉鍚岀偣銆備竴锛 RequestContext 鐨勭涓涓弬鏁伴渶瑕佷紶閫掍竴涓 HttpRequest 瀵硅薄锛屽氨鏄紶閫掔粰瑙嗗浘鍑芥暟鐨勭涓涓弬鏁帮紙 request 锛夈備簩锛 RequestContext 鏈変竴涓彲閫夌殑鍙傛暟 processors 锛岃繖鏄竴涓寘鍚玞ontext澶勭悊鍣ㄥ嚱鏁扮殑list鎴栬卼uple銆傚湪杩欓噷锛屾垜浠紶閫掍簡鎴戜滑涔嬪墠瀹氫箟鐨勫嚱鏁 curstom_proc

  • Each view no longer has to include app , user or ip_address in its context construction, because those are provided by custom_proc .

  • 姣忎釜瑙嗗浘鐨刢ontext缁撴瀯閲屼笉鍐嶅寘鍚 appuserip_address 绛夊彉閲忥紝鍥犱负杩欎簺鐢 custom_proc 鍑芥暟鎻愪緵浜嗐

  • Each view still has the flexibility to introduce any custom template variables it might need. In this example, the message template variable is set differently in each view.

O5akXl <a href=”http://xrdylvofgyks.com/“>xrdylvofgyks</a>, [url=http://jpknyzrymcvm.com/]jpknyzrymcvm[/url], [link=http://kanomsrvtkmd.com/]kanomsrvtkmd[/link], http://avajxtraqqjg.com/

In Chapter 4, we introduced the render_to_response() shortcut, which saves you from having to call loader.get_template() , then create a Context , then call the render() method on the template. In order to demonstrate the lower-level workings of context processors, the above examples didnt use render_to_response() , . But its possible and preferable to use context processors with render_to_response() . Do this with the context_instance argument, like so:

鍦ㄧ鍥涚珷锛屾垜浠粙缁嶄簡 render_to_response() 杩欎釜蹇嵎鏂瑰紡锛屽畠鍙互鐪佹帀璋冪敤 loader.get_template() ,鐒跺悗鍒涘缓涓涓 Context 瀵硅薄锛屾渶鍚庡啀璋冪敤妯℃澘瀵硅薄鐨 render() 鏂规硶銆備负浜嗚瑙ontext澶勭悊鍣ㄥ簳灞傛槸濡備綍宸ヤ綔鐨勶紝鍦ㄤ笂闈㈢殑渚嬪瓙涓垜浠病鏈変娇鐢 render_to_response() 銆備絾鏄缓璁夋嫨 render_to_response() 浣滀负context鐨勫鐞嗗櫒銆傚儚杩欐牱锛屼娇鐢 context_instance 鍙傛暟锛

from django.shortcuts import render_to_response
from django.template import RequestContext

def custom_proc(request):
    "A context processor that provides 'app', 'user' and 'ip_address'."
    return {
        'app': 'My app',
        'user': request.user,
        'ip_address': request.META['REMOTE_ADDR']
    }

def view_1(request):
    # ...
    return render_to_response('template1.html',
        {'message': 'I am view 1.'},
        context_instance=RequestContext(request, processors=[custom_proc]))

def view_2(request):
    # ...
    return render_to_response('template2.html',
        {'message': 'I am the second view.'},
        context_instance=RequestContext(request, processors=[custom_proc]))

def view_3(request):
    # ...
    return render_to_response('template3.html',
        {'message': 'I am the third view.'},
        context_instance=RequestContext(request, processors=[custom_proc]))

def view_4(request):
    # ...
    return render_to_response('template4.html',
        {'message': 'I am the fourth view.'},
        context_instance=RequestContext(request, processors=[custom_proc]))

Here, weve trimmed down each views template rendering code to a single (wrapped) line.

鍦ㄨ繖锛屾垜浠皢姣忎釜瑙嗗浘鐨勬ā鏉挎覆鏌撲唬鐮佸啓鎴愪簡涓涓崟琛屻

This is an improvement, but, evaluating the conciseness of this code, we have to admit were now almost overdosing on the other end of the spectrum. Weve removed redundancy in data (our template variables) at the cost of adding redundancy in code (in the processors call). Using context processors doesnt save you much typing if you have to type processors all the time.

铏界劧杩欐槸涓绉嶆敼杩涳紝浣嗘槸锛岃鑰冭檻涓涓嬭繖娈典唬鐮佺殑绠娲佹э紝鎴戜滑鐜板湪涓嶅緱涓嶆壙璁ょ殑鏄湪 鍙﹀ 涓鏂归潰鏈変簺杩囧垎浜嗐傛垜浠互浠g爜鍐椾綑锛堝湪 processors 璋冪敤涓級鐨勪唬浠锋秷闄や簡鏁版嵁涓婄殑鍐椾綑锛堟垜浠殑妯℃澘鍙橀噺锛夈傜敱浜庝綘涓嶅緱涓嶄竴鐩撮敭鍏 processors 锛屾墍浠ヤ娇鐢╟ontext澶勭悊鍣ㄥ苟娌℃湁鍑忓皯澶鐨勬墦瀛楁鏁般

For that reason, Django provides support for global context processors. The TEMPLATE_CONTEXT_PROCESSORS setting designates which context processors should always be applied to RequestContext . This removes the need to specify processors each time you use RequestContext .

Django鍥犳鎻愪緵瀵 鍏ㄥ眬 context澶勭悊鍣ㄧ殑鏀寔銆 TEMPLATE_CONTEXT_PROCESSORS 鎸囧畾浜 鎬绘槸 浣跨敤鍝簺 context processors 銆傝繖鏍峰氨鐪佸幓浜嗘瘡娆′娇鐢 RequestContext 閮芥寚瀹 processors 鐨勯夯鐑_^銆

By default, TEMPLATE_CONTEXT_PROCESSORS is set to the following:

ilR94N <a href=”http://bxcyktdovtcx.com/“>bxcyktdovtcx</a>, [url=http://svkmchcyqtpi.com/]svkmchcyqtpi[/url], [link=http://orlgauoznlpg.com/]orlgauoznlpg[/link], http://hcmltazhxlgv.com/

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
)

This setting is a tuple of callables that use the same interface as our custom_proc function above functions that take a request object as their argument and return a dictionary of items to be merged into the context. Note that the values in TEMPLATE_CONTEXT_PROCESSORS are specified as strings , which means the processors are required to be somewhere on your Python path (so you can refer to them from the setting).

杩欎釜璁剧疆鏄竴涓彲璋冪敤鍑芥暟鐨凾uple锛屽叾涓殑姣忎釜鍑芥暟浣跨敤浜嗗拰涓婃枃涓垜浠殑 custom_proc 鐩稿悓鐨勬帴鍙o細鎺ユ敹涓涓猺equest瀵硅薄浣滀负鍙傛暟锛岃繑鍥炰竴涓寘鍚簡灏嗚鍚堝苟鍒癱ontext涓殑椤圭殑瀛楀吀銆傝娉ㄦ剰 TEMPLATE_CONTEXT_PROCESSORS 涓殑鍊兼槸浠 strings 鐨勫舰寮忕粰鍑虹殑锛岃繖鎰忓懗鐫杩欎簺澶勭悊鍣ㄥ繀椤诲湪浣犵殑python璺緞涓殑鏌愬锛堣繖鏍蜂綘鎵嶈兘鍦ㄨ缃腑寮曠敤瀹冧滑锛

Each processor is applied in order. That is, if one processor adds a variable to the context and a second processor adds a variable with the same name, the second will override the first.

RkbRhS <a href=”http://ssvglzgqktrs.com/“>ssvglzgqktrs</a>, [url=http://tzwexwjpftqx.com/]tzwexwjpftqx[/url], [link=http://siituwbkjtet.com/]siituwbkjtet[/link], http://nyplxetpyqkq.com/

Django provides a number of simple context processors, including the ones that are enabled by default:

Django鎻愪緵浜嗗嚑涓畝鍗曠殑context澶勭悊鍣紝鏈変簺鍦ㄩ粯璁ゆ儏鍐典笅琚惎鐢ㄧ殑銆

django.core.context_processors.auth

django.core.context_processors.auth

If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every RequestContext will contain these variables:

cZgBaF <a href=”http://wqijjqhtuafe.com/“>wqijjqhtuafe</a>, [url=http://ymyewzllgpwg.com/]ymyewzllgpwg[/url], [link=http://ynrosouewqcv.com/]ynrosouewqcv[/link], http://taptrifhfbme.com/

  • user : A django.contrib.auth.models.User instance representing the current logged-in user (or an AnonymousUser instance, if the client isnt logged in).

  • user 锛氫竴涓 django.contrib.auth.models.User 瀹炰緥锛屾弿杩颁簡褰撳墠鐧诲綍鐢ㄦ埛锛堟垨鑰呬竴涓 AnonymousUser 瀹炰緥锛屽鏋滃鎴风娌℃湁鐧诲綍锛夈

  • messages : A list of messages (as strings) for the current logged-in user. Behind the scenes, this variable calls request.user.get_and_delete_messages() for every request. That method collects the users messages and deletes them from the database.

  • messages 锛氫竴涓綋鍓嶇櫥褰曠敤鎴风殑娑堟伅鍒楄〃锛堝瓧绗︿覆锛夈傚湪鍚庡彴锛屽姣忎竴涓姹傝繖涓彉閲忛兘璋冪敤 request.user.get_and_delete_messages() 鏂规硶銆傝繖涓柟娉曟敹闆嗙敤鎴风殑娑堟伅鐒跺悗鎶婂畠浠粠鏁版嵁搴撲腑鍒犻櫎銆

  • perms : An instance of django.core.context_processors.PermWrapper , which represents the permissions the current logged-in user has.

  • permsdjango.core.context_processors.PermWrapper 鐨勪竴涓疄渚嬶紝鍖呭惈浜嗗綋鍓嶇櫥褰曠敤鎴锋湁鍝簺鏉冮檺銆

See Chapter 12 for more information on users, permissions, and messages.

鍏充簬users銆乸ermissions鍜宮essages鐨勬洿澶氬唴瀹硅鍙傝冪12绔犮

django.core.context_processors.debug

django.core.context_processors.debug

This processor pushes debugging information down to the template layer. If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every RequestContext will contain these variables:

ae2cpK <a href=”http://zekedeavaywg.com/“>zekedeavaywg</a>, [url=http://kqzsnzwpeoko.com/]kqzsnzwpeoko[/url], [link=http://ncoswfhxxpgm.com/]ncoswfhxxpgm[/link], http://vrswcfxjqbnl.com/

  • debug : The value of your DEBUG setting (either True or False ). You can use this variable in templates to test whether youre in debug mode.

  • debug 锛氫綘璁剧疆鐨 DEBUG 鐨勫硷紙 TrueFalse 锛夈備綘鍙互鍦ㄦā鏉块噷闈㈢敤杩欎釜鍙橀噺娴嬭瘯鏄惁澶勫湪debug妯″紡涓嬨

  • sql_queries : A list of {'sql': ..., 'time': ...} dictionaries representing every SQL query that has happened so far during the request and how long it took. The list is in the order in which the queries were issued.

  • sql_queries 锛氬寘鍚被浼间簬 {'sql': ..., 'time': ...} 鐨勫瓧鍏哥殑涓涓垪琛紝 璁板綍浜嗚繖涓姹傛湡闂寸殑姣忎釜SQL鏌ヨ浠ュ強鏌ヨ鎵鑰楄垂鐨勬椂闂淬傝繖涓垪琛ㄦ槸鎸夌収璇锋眰椤哄簭杩涜鎺掑垪鐨勩

Because debugging information is sensitive, this context processor will only add variables to the context if both of the following conditions are true:

鐢变簬璋冭瘯淇℃伅姣旇緝鏁忔劅锛屾墍浠ヨ繖涓猚ontext澶勭悊鍣ㄥ彧鏈夊綋鍚屾椂婊¤冻涓嬮潰涓や釜鏉′欢鐨勬椂鍊欐墠鏈夋晥锛

  • The DEBUG setting is True .

VB156E <a href=”http://xsstdaarnodo.com/“>xsstdaarnodo</a>, [url=http://sjvwzwjuntje.com/]sjvwzwjuntje[/url], [link=http://rllxfurtgmdb.com/]rllxfurtgmdb[/link], http://liaaqrivlsgl.com/

  • The request came from an IP address in the INTERNAL_IPS setting.

  • 璇锋眰鐨刬p搴旇鍖呭惈鍦 INTERNAL_IPS 鐨勮缃噷闈€

django.core.context_processors.i18n

django.core.context_processors.i18n

If this processor is enabled, every RequestContext will contain these variables:

濡傛灉杩欎釜澶勭悊鍣ㄥ惎鐢紝姣忎釜 RequestContext 灏嗗寘鍚笅闈㈢殑鍙橀噺锛

  • LANGUAGES : The value of the LANGUAGES setting.

  • LANGUAGESLANGUAGES 閫夐」鐨勫笺

  • LANGUAGE_CODE : request.LANGUAGE_CODE if it exists; otherwise, the value of the LANGUAGE_CODE setting.

  • LANGUAGE_CODE 锛氬鏋 request.LANGUAGE_CODE 瀛樺湪锛屽氨绛変簬瀹冿紱鍚﹀垯锛岀瓑鍚屼簬 LANGUAGE_CODE 璁剧疆銆

Appendix E provides more information about these two settings.

闄勫綍E鎻愪緵浜嗘湁鍏宠繖涓や釜璁剧疆鐨勬洿澶氱殑淇℃伅銆

django.core.context_processors.request

django.core.context_processors.request

If this processor is enabled, every RequestContext will contain a variable request , which is the current HttpRequest object. Note that this processor is not enabled by default; you have to activate it.

zEZko4 <a href=”http://davktzvegpga.com/“>davktzvegpga</a>, [url=http://dvvitkvkrqhj.com/]dvvitkvkrqhj[/url], [link=http://zmxecatgkrei.com/]zmxecatgkrei[/link], http://qxqjkagkmvbm.com/

Guidelines for Writing Your Own Context Processors

鍐機ontext澶勭悊鍣ㄧ殑涓浜涘缓璁

Here are a few tips for rolling your own:

缂栧啓澶勭悊鍣ㄧ殑涓浜涘缓璁細

  • Make each context processor responsible for the smallest subset of functionality possible. Its easy to use multiple processors, so you might as well split functionality into logical pieces for future reuse.

  • 浣挎瘡涓猚ontext澶勭悊鍣ㄥ畬鎴愬敖鍙兘灏忕殑鍔熻兘銆 浣跨敤澶氫釜澶勭悊鍣ㄦ槸寰堝鏄撶殑锛屾墍浠ヤ綘鍙互鏍规嵁閫昏緫鍧楁潵鍒嗚В鍔熻兘浠ヤ究灏嗘潵閲嶇敤銆

  • Keep in mind that any context processor in TEMPLATE_CONTEXT_PROCESSORS will be available in every template powered by that settings file, so try to pick variable names that are unlikely to conflict with variable names your templates might be using independently. As variable names are case-sensitive, its not a bad idea to use all caps for variables a processor provides.

  • 瑕佹敞鎰 TEMPLATE_CONTEXT_PROCESSORS 閲岀殑context processor 灏嗕細鍦 姣忎釜 妯℃澘涓湁鏁堬紝鎵浠ヨ鍙橀噺鐨勫懡鍚嶄笉瑕佸拰妯℃澘鐨勫彉閲忓啿绐併 鍙橀噺鍚嶆槸澶у皬鍐欐晱鎰熺殑锛屾墍浠rocessor鐨勫彉閲忓叏鐢ㄥぇ鍐欐槸涓笉閿欑殑涓绘剰銆

  • It doesnt matter where on the filesystem they live, as long as theyre on your Python path so you can point to them from the TEMPLATE_CONTEXT_PROCESSORS setting. With that said, the convention is to save them in a file called context_processors.py within your app or project.

  • 鍙瀹冧滑瀛樻斁鍦ㄤ綘鐨凱ython鐨勬悳绱㈣矾寰勪腑锛屽畠浠斁鍦ㄥ摢涓墿鐞嗚矾寰勫苟涓嶉噸瑕侊紝杩欐牱浣犲彲浠ュ湪 TEMPLATE_CONTEXT_PROCESSORS 璁剧疆閲屾寚鍚戝畠浠 涔熷氨鏄锛屼綘瑕佹妸瀹冧滑鏀惧湪app鎴栬卲roject鐩綍閲屽悕涓 context_processors.py 鐨勬枃浠躲

Inside Template Loading

妯℃澘鍔犺浇鐨勫唴骞

Generally, youll store templates in files on your filesystem, but you can use custom template loaders to load templates from other sources.

涓鑸鏉ワ紝浣犱細鎶婃ā鏉夸互鏂囦欢鐨勬柟寮忓瓨鍌ㄥ湪鏂囦欢绯荤粺涓紝浣嗘槸浣犱篃鍙互浣跨敤鑷畾涔夌殑 template loaders 浠庡叾浠栨潵婧愬姞杞芥ā鏉裤

Django has two ways to load templates:

Django鏈変袱绉嶆柟娉曞姞杞芥ā鏉

  • django.template.loader.get_template(template_name) : get_template returns the compiled template (a Template object) for the template with the given name. If the template doesnt exist, a TemplateDoesNotExist exception will be raised.

  • django.template.loader.get_template(template_name)get_template 鏍规嵁缁欏畾鐨勬ā鏉垮悕绉拌繑鍥炰竴涓凡缂栬瘧鐨勬ā鏉匡紙涓涓 Template 瀵硅薄锛夈傚鏋滄ā鏉夸笉瀛樺湪锛屽氨瑙﹀彂 TemplateDoesNotExist 鐨勫紓甯搞

  • django.template.loader.select_template(template_name_list) : select_template is just like get_template , except it takes a list of template names. Of the list, it returns the first template that exists. If none of the templates exist, a TemplateDoesNotExist exception will be raised.

  • django.template.loader.select_template(template_name_list)select_template 寰堝儚 get_template 锛屼笉杩囧畠鏄互妯℃澘鍚嶇О鐨勫垪琛ㄤ綔涓哄弬鏁扮殑锛屽苟涓斿畠杩斿洖绗竴涓瓨鍦ㄧ殑妯℃澘銆傚鏋滄ā鏉块兘涓嶅瓨鍦紝灏嗕細瑙﹀彂 TemplateDoesNotExist 寮傚父銆

As covered in Chapter 4, each of these functions by default uses your TEMPLATE_DIRS setting to load templates. Internally, however, these functions actually delegate to a template loader for the heavy lifting.

姝e鍦ㄧ鍥涚珷涓墍鎻愬埌鐨勶紝榛樿鎯呭喌涓嬭繖浜涘嚱鏁颁娇鐢 TEMPLATE_DIRS 鐨勮缃潵杞藉叆妯℃澘銆備絾鏄紝鍦ㄥ唴閮ㄨ繖浜涘嚱鏁板彲浠ユ寚瀹氫竴涓ā鏉垮姞杞藉櫒鏉ュ畬鎴愯繖浜涚箒閲嶇殑浠诲姟銆

Some of loaders are disabled by default, but you can activate them by editing the TEMPLATE_LOADERS setting. TEMPLATE_LOADERS should be a tuple of strings, where each string represents a template loader. These template loaders ship with Django:

涓浜涘姞杞藉櫒榛樿琚鐢紝浣嗘槸浣犲彲浠ラ氳繃缂栬緫 TEMPLATE_LOADERS 璁剧疆鏉ユ縺娲诲畠浠 TEMPLATE_LOADERS 搴斿綋鏄竴涓瓧绗︿覆鐨勫厓缁勶紝鍏朵腑姣忎釜瀛楃涓查兘琛ㄧず涓涓ā鏉垮姞杞藉櫒銆傝繖浜涙ā鏉垮姞杞藉櫒闅廌jango涓璧峰彂甯冦

django.template.loaders.filesystem.load_template_source : This loader loads templates from the filesystem, according to TEMPLATE_DIRS . It is enabled by default.

django.template.loaders.filesystem.load_template_source : 杩欎釜鍔犺浇鍣ㄦ牴鎹 TEMPLATE_DIRS 鐨勮缃粠鏂囦欢绯荤粺鍔犺浇妯℃澘銆傚湪榛樿鎯呭喌涓嬭繖涓姞杞藉櫒琚惎鐢.

django.template.loaders.app_directories.load_template_source : This loader loads templates from Django applications on the filesystem. For each application in INSTALLED_APPS , the loader looks for a templates subdirectory. If the directory exists, Django looks for templates there.

django.template.loaders.app_directories.load_template_source : 杩欎釜鍔 杞藉櫒浠庢枃浠剁郴缁熶笂鐨凞jango搴旂敤涓姞杞芥ā鏉裤傚 INSTALLED_APPS 涓殑姣忎釜搴旂敤锛岃繖涓姞 杞藉櫒浼氭煡鎵句竴涓 templates 瀛愮洰褰曘傚鏋滆繖涓洰褰曞瓨鍦紝Django灏卞湪閭i噷瀵绘壘妯℃澘銆

This means you can store templates with your individual applications, making it easy to distribute Django applications with default templates. For example, if INSTALLED_APPS contains ('myproject.polls', 'myproject.music') , then get_template('foo.html') will look for templates in this order:

杩欐剰鍛崇潃浣犲彲浠ユ妸妯℃澘鍜屼綘鐨勫簲鐢ㄤ竴璧蜂繚瀛橈紝浠庤屼娇寰桪jango搴旂敤鏇村鏄撳拰榛樿妯℃澘涓璧峰彂甯冦備緥濡傦紝濡傛灉 INSTALLED_APPS 鍖呭惈 ('myproject.polls','myproject.music') 锛岄偅涔 get_template('foo.html') 浼氭寜杩欎釜椤哄簭鏌ユ壘妯℃澘锛

  • /path/to/myproject/polls/templates/foo.html

  • /path/to/myproject/polls/templates/foo.html

  • /path/to/myproject/music/templates/foo.html

zS7gE0 <a href=”http://xihwijxziqzw.com/“>xihwijxziqzw</a>, [url=http://latxmxlseqcl.com/]latxmxlseqcl[/url], [link=http://fwlitcrfihxf.com/]fwlitcrfihxf[/link], http://yxtsdtenuwcv.com/

Note that the loader performs an optimization when it is first imported: it caches a list of which INSTALLED_APPS packages have a templates subdirectory.

璇锋敞鎰忓姞杞藉櫒鍦ㄩ娆¤瀵煎叆鐨勬椂鍊欎細鎵ц涓涓紭鍖栵細瀹冧細缂撳瓨涓涓垪琛紝杩欎釜鍒楄〃鍖呭惈浜 INSTALLED_APPS 涓甫鏈 templates 瀛愮洰褰曠殑鍖呫

This loader is enabled by default.

杩欎釜鍔犺浇鍣ㄩ粯璁ゅ惎鐢ㄣ

django.template.loaders.eggs.load_template_source : This loader is just like app_directories , except it loads templates from Python eggs rather than from the filesystem. This loader is disabled by default; youll need to enable it if youre using eggs to distribute your application.

django.template.loaders.eggs.load_template_source : 杩欎釜鍔犺浇鍣ㄧ被浼 app_directories 锛屽彧涓嶈繃瀹冧粠Python eggs鑰屼笉鏄枃浠剁郴缁熶腑鍔犺浇妯℃澘銆傝繖涓姞杞藉櫒榛樿琚鐢紱濡傛灉浣犱娇鐢╡ggs鏉ュ彂甯冧綘鐨勫簲鐢紝閭d箞浣犲氨闇瑕佸惎鐢ㄥ畠銆

Django uses the template loaders in order according to the TEMPLATE_LOADERS setting. It uses each loader until a loader finds a match.

Django鎸夌収 TEMPLATE_LOADERS 璁剧疆涓殑椤哄簭浣跨敤妯℃澘鍔犺浇鍣ㄣ傚畠閫愪釜浣跨敤姣忎釜鍔犺浇鍣ㄧ洿鑷虫壘鍒颁竴涓尮閰嶇殑妯℃澘銆

Extending the Template System

鎵╁睍妯℃澘绯荤粺

Now that you understand a bit more about the internals of the template system, lets look at how to extend the system with custom code.

鏃㈢劧浣犲凡缁忓妯℃澘绯荤粺鐨勫唴骞曚簡瑙e浜嗕竴浜涳紝璁╂垜浠潵鐪嬬湅濡備綍浣跨敤鑷畾涔夌殑浠g爜鏉ユ嫇灞曡繖涓郴缁熷惂銆

Most template customization comes in the form of custom template tags and/or filters. Although the Django template language comes with many built-in tags and filters, youll probably assemble your own libraries of tags and filters that fit your own needs. Fortunately, its quite easy to define your own functionality.

缁濆ぇ閮ㄥ垎鐨勬ā鏉垮畾鍒舵槸浠ヨ嚜瀹氫箟鏍囩/杩囨护鍣ㄧ殑鏂瑰紡鏉ュ畬鎴愮殑銆傚敖绠jango妯℃澘璇█鑷甫浜嗚澶氬唴寤烘爣绛惧拰杩囨护鍣紝浣嗘槸浣犲彲鑳借繕鏄渶瑕佺粍寤轰綘鑷繁鐨勬爣绛惧拰杩囨护鍣ㄥ簱鏉ユ弧瓒充綘鐨勯渶瑕併傚垢杩愮殑鏄紝瀹氫箟浣犺嚜宸辩殑鍔熻兘闈炲父瀹规槗銆

Creating a Template Library

鍒涘缓涓涓ā鏉垮簱

Whether youre writing custom tags or filters, the first thing to do is to create a template library a small bit of infrastructure Django can hook into.

涓嶇鏄啓鑷畾涔夋爣绛捐繕鏄繃婊ゅ櫒锛岀涓浠惰鍋氱殑浜嬫槸缁 template library 鍒涘缓浣緿jango鑳藉鍕惧叆鐨勬満鍒躲

Creating a template library is a two-step process:

鍒涘缓涓涓ā鏉垮簱鍒嗕袱姝ヨ蛋锛

First, decide which Django application should house the template library. If youve created an app via manage.py startapp , you can put it in there, or you can create another app solely for the template library.

绗竴锛屽喅瀹氬摢涓狣jango搴旂敤搴斿綋鎷ユ湁杩欎釜妯℃澘搴撱傚鏋滀綘閫氳繃 manage.py startapp 鍒涘缓浜嗕竴涓簲鐢紝浣犲彲浠ユ妸瀹冩斁鍦ㄩ偅閲岋紝鎴栬呬綘鍙互涓烘ā鏉垮簱鍗曠嫭鍒涘缓涓涓簲鐢ㄣ

Whichever route you take, make sure to add the app to your INSTALLED_APPS setting. Well explain this shortly.

鏃犺浣犻噰鐢ㄤ綍绉嶆柟寮忥紝璇风‘淇濇妸浣犵殑搴旂敤娣诲姞鍒 INSTALLED_APPS 涓傛垜浠◢鍚庝細瑙i噴杩欎竴鐐广

Second, create a templatetags directory in the appropriate Django applications package. It should be on the same level as models.py , views.py , and so forth. For example:

绗簩锛屽湪閫傚綋鐨凞jango搴旂敤鍖呴噷鍒涘缓涓涓 templatetags 鐩綍銆傝繖涓洰褰曞簲褰撳拰 models.pyviews.py 绛夊浜庡悓涓灞傛銆備緥濡傦細

books/
    __init__.py
    models.py
    templatetags/
    views.py

Create two empty files in the templatetags directory: an __init__.py file (to indicate to Python that this is a package containing Python code) and a file that will contain your custom tag/filter definitions. The name of the latter file is what youll use to load the tags later. For example, if your custom tags/filters are in a file called poll_extras.py , youd write the following in a template:

templatetags 涓垱寤轰袱涓┖鏂囦欢锛氫竴涓 __init__.py 锛堝憡璇塒ython杩欐槸 涓涓寘鍚簡Python浠g爜鐨勫寘锛夊拰涓涓敤鏉ュ瓨鏀句綘鑷畾涔夌殑鏍囩/杩囨护鍣ㄥ畾涔夌殑鏂囦欢銆傜浜屼釜鏂囦欢 鐨勫悕瀛楃◢鍚庡皢鐢ㄦ潵鍔犺浇鏍囩銆備緥濡傦紝濡傛灉浣犵殑鑷畾涔夋爣绛/杩囨护鍣ㄥ湪涓涓彨浣 poll_extras.py 鐨勬枃浠朵腑锛屼綘闇瑕佸湪妯℃澘涓啓鍏ュ涓嬪唴瀹癸細

{% load poll_extras %}

The {% load %} tag looks at your INSTALLED_APPS setting and only allows the loading of template libraries within installed Django applications. This is a security feature; it allows you to host Python code for many template libraries on a single computer without enabling access to all of them for every Django installation.

{% load %} 鏍囩妫鏌 INSTALLED_APPS 涓殑璁剧疆锛屼粎鍏佽鍔犺浇宸插畨瑁呯殑Django搴旂敤绋嬪簭涓殑妯℃澘搴撱傝繖鏄竴涓畨鍏ㄧ壒鎬с傚畠鍙互璁╀綘鍦ㄤ竴鍙扮數鑴戜笂閮ㄧ讲寰堝鐨勬ā鏉垮簱鐨勪唬鐮侊紝鑰屽張涓嶇敤鎶婂畠浠毚闇茬粰姣忎竴涓狣jango瀹夎銆

If you write a template library that isnt tied to any particular models/views, its valid and quite normal to have a Django application package that contains only a templatetags package. Theres no limit on how many modules you put in the templatetags package. Just keep in mind that a {% load %} statement will load tags/filters for the given Python module name, not the name of the application.

濡傛灉浣犲啓浜嗕竴涓笉鍜屼换浣曟ā鍨/瑙嗗浘鍏宠仈鐨勬ā鏉垮簱锛岄偅涔堝緱鍒颁竴涓粎鍖呭惈 templatetags 鍖呯殑Django搴旂敤绋嬪簭鍖呮槸瀹屽叏姝e父鐨勩傚浜庡湪 templatetags 鍖呬腑鏀剧疆澶氬皯涓ā鍧楁病鏈夊仛浠讳綍鐨勯檺鍒躲傞渶瑕佷簡瑙g殑鏄細 {% load %} 璇彞浼氫负鎸囧畾鐨凱ython妯″潡鍚嶏紙鑰岄潪搴旂敤绋嬪簭鍚嶏級鍔犺浇鏍囩鎴栬繃婊ゅ櫒銆

Once youve created that Python module, youll just have to write a bit of Python code, depending on whether youre writing filters or tags.

涓鏃﹀垱寤轰簡Python妯″潡锛屼綘鍙渶鏍规嵁鏄缂栧啓杩囨护鍣ㄨ繕鏄爣绛炬潵鐩稿簲鐨勭紪鍐欎竴浜汸ython浠g爜銆

To be a valid tag library, the module must contain a module-level variable named register that is a template.Library instance. This template.Library instance is the data structure in which all the tags and filters are registered. So, near the top of your module, insert the following:

瑕佹垚涓烘湁鏁堢殑鏍囩搴擄紝妯″潡蹇呴』鍖呭惈涓涓ā鍧楃骇鐨勫彉閲忥細 register 锛岃繖鏄竴涓 template.Library 鐨勫疄渚嬨傝繖涓 template.Library 瀹炰緥鏄寘鍚墍鏈夊凡娉ㄥ唽鐨勬爣绛惧強杩囨护鍣ㄧ殑鏁版嵁缁撴瀯銆傚洜姝わ紝鍦ㄦā鍧楃殑椤堕儴浣嶇疆鎻掑叆涓嬭堪浠g爜锛

from django import template

register = template.Library()

Note

澶囨敞

For a good number of examples, read the source code for Djangos default filters and tags. Theyre in django/template/defaultfilters.py and django/template/defaulttags.py , respectively. Some applications in django.contrib also contain template libraries.

璇烽槄璇籇jango榛樿鐨勮繃婊ゅ櫒鍜屾爣绛剧殑婧愮爜锛岄偅閲屾湁澶ч噺鐨勪緥瀛愩備粬浠垎鍒负锛 django/template/defaultfilters.pydjango/template/defaulttags.py 銆傛煇浜涘簲鐢ㄧ▼搴忓湪 django.contrib 涓篃鍖呭惈妯℃澘搴撱

Once youve created this register variable, youll use it to create template filters and tags.

鍒涘缓 register 鍙橀噺鍚庯紝浣犲氨鍙互浣跨敤瀹冩潵鍒涘缓妯℃澘鐨勮繃婊ゅ櫒鍜屾爣绛句簡銆

Writing Custom Template Filters

鑷畾涔夋ā鏉胯繃婊ゅ櫒

Custom filters are just Python functions that take one or two arguments:

鑷畾涔夎繃婊ゅ櫒灏辨槸鏈変竴涓垨涓や釜鍙傛暟鐨凱ython鍑芥暟:

  • The value of the variable (input)

  • (杈撳叆)鍙橀噺鐨勫

  • The value of the argument, which can have a default value or be left out altogether

  • 鍙傛暟鐨勫硷紝 鍙互鏄粯璁ゅ兼垨鑰呭畬鍏ㄧ暀绌

For example, in the filter {{ var|foo:"bar" }} , the filter foo would be passed the contents of the variable var and the argument "bar" .

渚嬪锛屽湪杩囨护鍣 {{ var|foo:"bar" }} 涓 锛岃繃婊ゅ櫒 foo 浼氳浼犲叆鍙橀噺 var 鍜屽弬鏁 bar 鐨勫唴瀹广

Filter functions should always return something. They shouldnt raise exceptions, and they should fail silently. If theres an error, they should return either the original input or an empty string, whichever makes more sense.

杩囨护鍣ㄥ嚱鏁板簲璇ユ绘湁杩斿洖鍊硷紝鑰屼笖涓嶈兘瑙﹀彂寮傚父锛屽畠浠兘搴旇闈欓潤鐨勫け璐ャ傚鏋滄湁涓涓敊璇彂鐢燂紝瀹冧滑瑕佷箞杩斿洖鍘熷鐨勮緭鍏ュ瓧绗︿覆锛岃涔堣繑鍥炵┖鐨勫瓧绗︿覆锛屾棤璁哄摢涓兘鍙互銆

Heres an example filter definition:

杩欓噷鏄竴浜涘畾涔夎繃婊ゅ櫒鐨勪緥瀛愶細

def cut(value, arg):
    "Removes all values of arg from the given string"
    return value.replace(arg, '')

And heres an example of how that filter would be used:

杩欓噷鏄竴浜涘浣曚娇鐢ㄨ繃婊ゅ櫒鐨勪緥瀛愶細

{{ somevariable|cut:"0" }}

Most filters dont take arguments. In this case, just leave the argument out of your function:

澶у鏁拌繃婊ゅ櫒骞朵笉闇瑕佸弬鏁般備笅闈㈢殑渚嬪瓙鎶婂弬鏁颁粠浣犵殑鍑芥暟涓嬁鎺変簡锛

def lower(value): # Only one argument.
    "Converts a string into all lowercase"
    return value.lower()

When youve written your filter definition, you need to register it with your Library instance, to make it available to Djangos template language:

褰撲綘鍦ㄥ畾涔変綘鐨勮繃婊ゅ櫒鏃讹紝浣犻渶瑕佺敤 Library 瀹炰緥鏉ユ敞鍐屽畠锛岃繖鏍峰氨鑳介氳繃Django鐨勬ā鏉胯瑷鏉ヤ娇鐢ㄤ簡锛

register.filter('cut', cut)
register.filter('lower', lower)

The Library.filter() method takes two arguments:

Library.filter() 鏂规硶闇瑕佷袱涓弬鏁帮細

  • The name of the filter (a string)

  • 杩囨护鍣ㄧ殑鍚嶇О锛堜竴涓瓧涓诧級

  • The filter function itself

  • 杩囨护鍣ㄥ嚱鏁版湰韬

If youre using Python 2.4 or above, you can use register.filter() as a decorator instead:

濡傛灉浣犱娇鐢ㄧ殑鏄疨ython 2.4鎴栨洿鏂帮紝浣犲彲浠ヤ娇鐢 register.filter() 浣滀负涓涓楗板櫒锛

@register.filter(name='cut')
def cut(value, arg):
    return value.replace(arg, '')

@register.filter
def lower(value):
    return value.lower()

If you leave off the name argument, as in the second example, Django will use the functions name as the filter name.

鍍忕浜屼釜渚嬪瓙涓紝濡傛灉浣犱笉浣跨敤 name 鍙傛暟锛岄偅涔圖jango灏嗕細浣跨敤鍑芥暟鍚嶄綔涓鸿繃婊ゅ櫒鐨勫悕瀛椼

Here, then, is a complete template library example, supplying the cut filter:

涓嬮潰鏄竴涓畬鏁寸殑妯℃澘搴撶殑渚嬪瓙锛屾彁渚涗簡涓涓 cut 杩囨护鍣細

from django import template

register = template.Library()

@register.filter(name='cut')
def cut(value, arg):
    return value.replace(arg, '')

Writing Custom Template Tags

鑷畾涔夋ā鏉挎爣绛

Tags are more complex than filters, because tags can do nearly anything.

鏍囩瑕佹瘮杩囨护鍣ㄥ鏉備簺锛屾爣绛惧嚑涔庤兘鍋氫换浣曚簨鎯呫

Chapter 4 describes how the template system works in a two-step process: compiling and rendering. To define a custom template tag, you need to tell Django how to manage both steps when it gets to your tag.

绗洓绔犳弿杩颁簡妯℃澘绯荤粺鐨勪袱姝ュ鐞嗚繃绋嬶細缂栬瘧鍜屽憟鐜般備负浜嗚嚜瀹氫箟涓涓繖鏍风殑妯℃澘鏍囩锛屼綘闇瑕佸憡璇塂jango褰撻亣鍒颁綘鐨勬爣绛炬椂鎬庢牱杩涜杩欒繃绋嬨

When Django compiles a template, it splits the raw template text into nodes . Each node is an instance of django.template.Node and has a render() method. Thus, a compiled template is simply a list of Node objects.

褰揇jango缂栬瘧涓涓ā鏉挎椂锛屽畠灏嗗師濮嬫ā鏉垮垎鎴愪竴涓釜 鑺傜偣 銆傛瘡涓妭鐐归兘鏄 django.template.Node 鐨勪竴涓疄渚嬶紝骞朵笖鍏峰 render() 鏂规硶銆備簬鏄紝涓涓凡缂栬瘧鐨勬ā鏉垮氨鏄 Node 瀵硅薄鐨勪竴涓垪琛ㄣ

When you call render() on a compiled template, the template calls render() on each Node in its node list, with the given context. The results are all concatenated together to form the output of the template. Thus, to define a custom template tag, you specify how the raw template tag is converted into a Node (the compilation function) and what the nodes render() method does.

褰撲綘璋冪敤涓涓凡缂栬瘧妯℃澘鐨 render() 鏂规硶鏃讹紝妯℃澘灏变細鐢ㄧ粰瀹氱殑context鏉ヨ皟鐢ㄦ瘡涓湪瀹冪殑鑺傜偣鍒楄〃涓婄殑鑺傜偣鐨 render() 鏂规硶銆傛墍浠ワ紝涓轰簡瀹氫箟涓涓嚜瀹氫箟鐨勬ā鏉挎爣绛撅紝浣犻渶瑕佹槑纭繖涓ā鏉挎爣绛捐浆鎹负涓涓 Node 锛堝凡缂栬瘧鐨勫嚱鏁帮級鍜岃繖涓猲ode鐨 render() 鏂规硶銆

In the sections that follow, we cover all the steps in writing a custom tag.

鍦ㄤ笅闈㈢殑绔犺妭涓紝鎴戜滑灏嗚缁嗚В璇村啓涓涓嚜瀹氫箟鏍囩鏃剁殑鎵鏈夋楠ゃ

Writing the Compilation Function
缂栧啓缂栬瘧鍑芥暟

For each template tag it encounters, the template parser calls a Python function with the tag contents and the parser object itself. This function is responsible for returning a Node instance based on the contents of the tag.

褰撻亣鍒颁竴涓ā鏉挎爣绛撅紙template tag锛夋椂锛屾ā鏉胯В鏋愬櫒灏变細鎶婃爣绛惧寘鍚殑鍐呭锛屼互鍙婃ā鏉胯В鏋愬櫒鑷繁浣滀负鍙傛暟璋冪敤涓涓猵ython鍑芥暟銆傝繖涓嚱鏁拌礋璐h繑鍥炰竴涓拰褰撳墠妯℃澘鏍囩鍐呭鐩稿搴旂殑鑺傜偣锛圢ode锛夌殑瀹炰緥銆

For example, lets write a template tag, {% current_time %} , that displays the current date/time, formatted according to a parameter given in the tag, in strftime syntax (see http://www.djangoproject.com/r/python/strftime/ ). Its a good idea to decide the tag syntax before anything else. In our case, lets say the tag should be used like this:

渚嬪锛屽啓涓涓樉绀哄綋鍓嶆棩鏈熺殑妯℃澘鏍囩锛歿% current_time %}锛岃鏍囩浼氭牴鎹弬鏁版寚瀹氱殑 strftime 鏍煎紡锛堝弬瑙侊細 http://www.djangoproject.com/r/python/strftime/ 锛夋樉绀哄綋鍓嶆椂闂淬傚湪缁х画鍋氬叾瀹冧簨鎯呬互鍓嶏紝鍏堝喅瀹氭爣绛剧殑璇硶鏄竴涓ソ涓绘剰銆傚湪鎴戜滑鐨勪緥瀛愰噷锛岃鏍囩灏嗕細鍍忚繖鏍疯浣跨敤锛

<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>

Note

澶囨敞

Yes, this template tag is redundantDjangos default {% now %} tag does the same task with simpler syntax. This template tag is presented here just for example purposes.

娌¢敊, 杩欎釜妯℃澘鏍囩鏄浣欑殑锛孌jango榛樿鐨 {% now %} 鐢ㄦ洿绠鍗曠殑璇硶瀹屾垚浜嗗悓鏍风殑宸ヤ綔銆傝繖涓ā鏉挎爣绛惧湪杩欓噷鍙槸浣滀负涓涓緥瀛愩

The parser for this function should grab the parameter and create a Node object:

杩欎釜鍑芥暟鐨勫垎鏋愬櫒浼氳幏鍙栧弬鏁板苟鍒涘缓涓涓 Node 瀵硅薄:

from django import template

def do_current_time(parser, token):
    try:
        # split_contents() knows not to split quoted strings.
        tag_name, format_string = token.split_contents()
    except ValueError:
        msg = '%r tag requires a single argument' % token.contents[0]
        raise template.TemplateSyntaxError(msg)
    return CurrentTimeNode(format_string[1:-1])

Theres actually a lot going here:

鍏跺疄杩欏効鍖呭惈浜嗕笉灏戜笢瑗匡細

  • parser is the template parser object. We dont need it in this example.

  • parser 鏄ā鏉垮垎鏋愬櫒瀵硅薄锛屽湪杩欎釜渚嬪瓙涓垜浠病鏈変娇鐢ㄥ畠銆

  • token.contents is a string of the raw contents of the tag. In our example, its 'current_time "%Y-%m-%d %I:%M %p"' .

  • token.contents 鏄寘鍚湁鏍囩鍘熷鍐呭鐨勫瓧绗︿覆銆傚湪鎴戜滑鐨勪緥瀛愪腑锛屽畠鏄 'current_time "%Y-%m-%d %I:%M %p"'

  • The token.split_contents() method separates the arguments on spaces while keeping quoted strings together. Avoid using token.contents.split() (which just uses Pythons standard string-splitting semantics). Its not as robust, as it naively splits on all spaces, including those within quoted strings.

  • token.split_contents() 鏂规硶鎸夌┖鏍兼媶鍒嗗弬鏁板悓鏃朵繚璇佸紩鍙蜂腑鐨勫瓧绗︿覆鍦ㄤ竴璧枫傚簲璇ラ伩鍏嶄娇鐢 token.contents.split() 锛堜粎鏄娇鐢≒ython鐨勬爣鍑嗗瓧绗︿覆鎷嗗垎锛夛紝瀹冧笉澶熷仴澹紝鍥犱负瀹冨彧鏄畝鍗曠殑鎸夌収 鎵鏈 绌烘牸杩涜鎷嗗垎锛屽寘鎷偅浜涘紩鍙峰紩璧锋潵鐨勫瓧绗︿覆涓殑绌烘牸銆

  • This function is responsible for raising django.template.TemplateSyntaxError , with helpful messages, for any syntax error.

  • 杩欎釜鍑芥暟璐熻矗鎶涘嚭 django.template.TemplateSyntaxError 锛屽悓鏃舵彁渚涙墍鏈夎娉曢敊璇殑鏈夌敤淇℃伅銆

  • Dont hard-code the tags name in your error messages, because that couples the tags name to your function. token.split_contents()[0] will always be the name of your tageven when the tag has no arguments.

  • 涓嶈鎶婃爣绛惧悕绉扮‖缂栫爜鍦ㄤ綘鐨勯敊璇俊鎭腑锛屽洜涓鸿繖鏍蜂細鎶婃爣绛惧悕绉板拰浣犵殑鍑芥暟鑰﹀悎鍦ㄤ竴璧枫 token.split_contents()[0] 鎬讳細鏄 鏄綘鐨勬爣绛剧殑鍚嶇О锛屽嵆浣挎爣绛炬病鏈夊弬鏁般

  • The function returns a CurrentTimeNode (which well create shortly) containing everything the node needs to know about this tag. In this case, it just passes the argument "%Y-%m-%d %I:%M %p" . The leading and trailing quotes from the template tag are removed with format_string[1:-1] .

  • 杩欎釜鍑芥暟杩斿洖涓涓 CurrentTimeNode 锛堢◢鍚庢垜浠皢鍒涘缓瀹冿級锛屽畠鍖呭惈浜嗚妭鐐归渶瑕佺煡閬撶殑鍏充簬杩欎釜鏍囩鐨勫叏閮ㄤ俊鎭傚湪杩欎釜渚嬪瓙涓紝瀹冨彧鏄紶閫掍簡鍙傛暟 "%Y-%m-%d %I:%M %p" 銆傛ā鏉挎爣绛惧紑澶村拰缁撳熬鐨勫紩鍙蜂娇鐢 format_string[1:-1] 闄ゅ幓銆

  • Template tag compilation functions must return a Node subclass; any other return value is an error.

  • 妯℃澘鏍囩缂栬瘧鍑芥暟 蹇呴』 杩斿洖涓涓 Node 瀛愮被锛岃繑鍥炲叾瀹冨奸兘鏄敊鐨勩

Writing the Template Node
缂栧啓妯℃澘鑺傜偣

The second step in writing custom tags is to define a Node subclass that has a render() method. Continuing the preceding example, we need to define CurrentTimeNode :

缂栧啓鑷畾涔夋爣绛剧殑绗簩姝ュ氨鏄畾涔変竴涓嫢鏈 render() 鏂规硶鐨 Node 瀛愮被銆傜户缁墠闈㈢殑渚嬪瓙锛屾垜浠渶瑕佸畾涔 CurrentTimeNode

import datetime

class CurrentTimeNode(template.Node):

    def __init__(self, format_string):
        self.format_string = format_string

    def render(self, context):
        now = datetime.datetime.now()
        return now.strftime(self.format_string)

These two functions (__init__ and render ) map directly to the two steps in template processing (compilation and rendering). Thus, the initialization function only needs to store the format string for later use, and the render() function does the real work.

杩欎袱涓嚱鏁帮紙 __init__render 锛変笌妯℃澘澶勭悊涓殑涓ゆ锛堢紪璇戜笌娓叉煋锛夌洿鎺ュ搴斻傝繖鏍凤紝鍒濆鍖栧嚱鏁颁粎浠呴渶瑕佸瓨鍌ㄥ悗闈㈣鐢ㄥ埌鐨勬牸寮忓瓧绗︿覆锛岃 render() 鍑芥暟鎵嶅仛鐪熸鐨勫伐浣溿

Like template filters, these rendering functions should fail silently instead of raising errors. The only time that template tags are allowed to raise errors is at compilation time.

涓庢ā鏉胯繃婊ゅ櫒涓鏍凤紝杩欎簺娓叉煋鍑芥暟搴旇鎹曡幏閿欒锛岃屼笉鏄姏鍑洪敊璇傛ā鏉挎爣绛惧彧鑳藉湪缂栬瘧鐨勬椂鍊欐墠鑳芥姏鍑洪敊璇

Registering the Tag
娉ㄥ唽鏍囩

Finally, you need to register the tag with your modules Library instance. Registering custom tags is very similar to registering custom filters (as explained above). Just instantiate a template.Library instance and call its tag() method. For example:

鏈鍚庯紝浣犻渶瑕佺敤浣犵殑妯″潡 Library 瀹炰緥娉ㄥ唽杩欎釜鏍囩銆傛敞鍐岃嚜瀹氫箟鏍囩涓庢敞鍐岃嚜瀹氫箟杩囨护鍣ㄩ潪甯哥被浼硷紙濡傚墠鏂囨墍杩帮級銆傚疄渚嬪寲涓涓 template.Library 瀹炰緥鐒跺悗璋冪敤瀹冪殑 tag() 鏂规硶銆備緥濡傦細

register.tag('current_time', do_current_time)

The tag() method takes two arguments:

tag() 鏂规硶闇瑕佷袱涓弬鏁:

The name of the template tag (string). If this is left out, the

妯℃澘鏍囩鐨勫悕瀛楋紙瀛楃涓诧級銆傚鏋滆閬楁紡鐨勮瘽锛屽皢浼氫娇鐢ㄧ紪璇戝嚱鏁扮殑鍚嶅瓧銆

name of the compilation function will be used.

The compilation function.

缂栬瘧鍑芥暟銆

As with filter registration, it is also possible to use register.tag as a decorator in Python 2.4 and above:

鍜屾敞鍐岃繃婊ゅ櫒绫讳技锛屼篃鍙互鍦≒ython2.4鍙婂叾浠ヤ笂鐗堟湰涓娇鐢 register.tag 淇グ锛

@register.tag(name="current_time")
def do_current_time(parser, token):
    # ...

@register.tag
def shout(parser, token):
    # ...

If you leave off the name argument, as in the second example, Django will use the functions name as the tag name.

濡傛灉浣犲儚鍦ㄧ浜屼釜渚嬪瓙涓偅鏍峰拷鐣 name 鍙傛暟鐨勮瘽锛孌jango浼氫娇鐢ㄥ嚱鏁板悕绉颁綔涓烘爣绛惧悕绉般

Setting a Variable in the Context
鍦ㄤ笂涓嬫枃涓缃彉閲

The previous sections example simply returned a value. Often its useful to set template variables instead of returning values. That way, template authors can just use the variables that your template tags set.

鍓嶄竴鑺傜殑渚嬪瓙鍙槸绠鍗曠殑杩斿洖涓涓笺傚緢澶氭椂鍊欒缃竴涓ā鏉垮彉閲忚岄潪杩斿洖鍊间篃寰堟湁鐢ㄣ傞偅鏍凤紝妯℃澘浣滆呭氨鍙兘浣跨敤浣犵殑妯℃澘鏍囩鎵璁剧疆鐨勫彉閲忋

To set a variable in the context, use dictionary assignment on the context object in the render() method. Heres an updated version of CurrentTimeNode that sets a template variable, current_time , instead of returning it:

瑕佸湪涓婁笅鏂囦腑璁剧疆鍙橀噺锛屽湪 render() 鍑芥暟鐨刢ontext瀵硅薄涓婁娇鐢ㄥ瓧鍏歌祴鍊笺傝繖閲屾槸涓涓慨鏀硅繃鐨 CurrentTimeNode 锛屽叾涓瀹氫簡涓涓ā鏉垮彉閲 current_time 锛屽苟娌℃湁杩斿洖瀹冿細

class CurrentTimeNode2(template.Node):

    def __init__(self, format_string):
        self.format_string = format_string

    def render(self, context):
        now = datetime.datetime.now()
        context['current_time'] = now.strftime(self.format_string)
        return ''

Note that render() returns an empty string. render() should always return a string, so if all the template tag does is set a variable, render() should return an empty string.

娉ㄦ剰 render() 杩斿洖浜嗕竴涓┖瀛楃涓层 render() 搴斿綋鎬绘槸杩斿洖涓涓瓧绗︿覆锛屾墍浠ュ鏋滄ā鏉挎爣绛惧彧鏄璁剧疆鍙橀噺锛 render() 灏卞簲璇ヨ繑鍥炰竴涓┖瀛楃涓层

Heres how youd use this new version of the tag:

浣犲簲璇ヨ繖鏍蜂娇鐢ㄨ繖涓柊鐗堟湰鐨勬爣绛撅細

{% current_time2 "%Y-%M-%d %I:%M %p" %}
<p>The time is {{ current_time }}.</p>

But theres a problem with CurrentTimeNode2 : the variable name current_time is hard-coded. This means youll need to make sure your template doesnt use {{ current_time }} anywhere else, because {% current_time2 %} will blindly overwrite that variables value.

浣嗘槸 CurrentTimeNode2 鏈変竴涓棶棰: 鍙橀噺鍚 current_time 鏄‖缂栫爜鐨勩傝繖鎰忓懗鐫浣犲繀椤荤‘瀹氫綘鐨勬ā鏉垮湪鍏跺畠浠讳綍鍦版柟閮戒笉浣跨敤 {{ current_time }} 锛屽洜涓 {% current_time2 %} 浼氱洸鐩殑瑕嗙洊璇ュ彉閲忕殑鍊笺

A cleaner solution is to make the template tag specify the name of the variable to be set, like so:

涓绉嶆洿绠娲佺殑鏂规鏄敱妯℃澘鏍囩鏉ユ寚瀹氶渶瑕佽瀹氱殑鍙橀噺鐨勫悕绉帮紝灏卞儚杩欐牱锛

{% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
<p>The current time is {{ my_current_time }}.</p>

To do so, youll need to refactor both the compilation function and the Node class, as follows:

涓烘锛屼綘闇瑕侀噸鏋勭紪璇戝嚱鏁板拰 Node 绫伙紝濡備笅鎵绀猴細

import re

class CurrentTimeNode3(template.Node):

    def __init__(self, format_string, var_name):
        self.format_string = format_string
        self.var_name = var_name

    def render(self, context):
        now = datetime.datetime.now()
        context[self.var_name] = now.strftime(self.format_string)
        return ''

def do_current_time(parser, token):
    # This version uses a regular expression to parse tag contents.
    try:
        # Splitting by None == splitting by spaces.
        tag_name, arg = token.contents.split(None, 1)
    except ValueError:
        msg = '%r tag requires arguments' % token.contents[0]
        raise template.TemplateSyntaxError(msg)

    m = re.search(r'(.*?) as (\w+)', arg)
    if m:
        fmt, var_name = m.groups()
    else:
        msg = '%r tag had invalid arguments' % tag_name
        raise template.TemplateSyntaxError(msg)

    if not (fmt[0] == fmt[-1] and fmt[0] in ('"', "'")):
        msg = "%r tag's argument should be in quotes" % tag_name
        raise template.TemplateSyntaxError(msg)

    return CurrentTimeNode3(fmt[1:-1], var_name)

Now do_current_time() passes the format string and the variable name to CurrentTimeNode3 .

鐜板湪 do_current_time() 鎶婃牸寮忓瓧绗︿覆鍜屽彉閲忓悕浼犻掔粰 CurrentTimeNode3

Parsing Until Another Block Tag
鍒嗘瀽鐩磋嚦鍙︿竴涓潡鏍囩

Template tags can work as blocks containing other tags (think {% if %} , {% for %} , etc.). To create a template tag like this, use parser.parse() in your compilation function.

妯℃澘鏍囩鍙互鍍忓寘鍚叾瀹冩爣绛剧殑鍧椾竴鏍峰伐浣滐紙鎯虫兂 {% if %}{% for %} 绛夛級銆 瑕佸垱寤轰竴涓繖鏍风殑妯℃澘鏍囩锛屽湪浣犵殑缂栬瘧鍑芥暟涓娇鐢 parser.parse()

Heres how the standard {% comment %} tag is implemented:

鏍囧噯鐨 {% comment %} 鏍囩鏄繖鏍峰疄鐜扮殑锛

def do_comment(parser, token):
    nodelist = parser.parse(('endcomment',))
    parser.delete_first_token()
    return CommentNode()

class CommentNode(template.Node):
    def render(self, context):
        return ''

parser.parse() takes a tuple of names of block tags to parse until. It returns an instance of django.template.NodeList , which is a list of all Node objects that the parser encountered before it encountered any of the tags named in the tuple.

parser.parse() 鎺ユ敹涓涓寘鍚簡闇瑕佸垎鏋愬潡鏍囩鍚嶇殑鍏冪粍浣滀负鍙傛暟. 瀹冭繑鍥炰竴涓 django.template.NodeList 瀹炰緥, 瀹冩槸涓涓寘鍚簡鎵鏈 Node 瀵硅薄鐨勫垪琛,杩欎簺瀵硅薄浠h〃浜嗗垎鏋愬櫒鍦ㄩ亣鍒板厓缁勪腑浠讳竴鏍囩鍚嶄箣 鐨勫唴瀹.

So in the preceding example, nodelist is a list of all nodes between {% comment %} and {% endcomment %} , not counting {% comment %} and {% endcomment %} themselves.

鍥犳鍦ㄥ墠闈㈢殑渚嬪瓙涓紝 nodelist 鏄湪 {% comment %}{% endcomment %} 涔嬮棿鎵鏈夎妭鐐圭殑鍒楄〃锛屼笉鍖呮嫭 {% comment %}{% endcomment %} 鑷韩銆

After parser.parse() is called, the parser hasnt yet consumed the {% endcomment %} tag, so the code needs to explicitly call parser.delete_first_token() to prevent that tag from being processed twice.

parser.parse() 琚皟鐢ㄤ箣鍚庯紝鍒嗘瀽鍣ㄨ繕娌℃湁娓呴櫎 {% endcomment %} 鏍囩锛屽洜姝や唬鐮侀渶瑕佹樉寮忓湴璋冪敤 parser.delete_first_token() 鏉ラ槻姝㈣鏍囩琚鐞嗕袱娆°

Then CommentNode.render() simply returns an empty string. Anything between {% comment %} and {% endcomment %} is ignored.

涔嬪悗 CommentNode.render() 鍙槸绠鍗曞湴杩斿洖涓涓┖瀛楃涓层傚湪 {% comment %}{% endcomment %} 涔嬮棿鐨勬墍鏈夊唴瀹归兘琚拷鐣ャ

Parsing Until Another Block Tag and Saving Contents
鍒嗘瀽鐩磋嚦鍙﹀涓涓潡鏍囩骞朵繚瀛樺唴瀹

In the previous example, do_comment() discarded everything between {% comment %} and {% endcomment %} . Its also possible to do something with the code between block tags instead.

鍦ㄥ墠涓涓緥瀛愪腑锛 do_comment() 鎶涘純浜嗗湪 {% comment %}{% endcomment %} 涔嬮棿鐨勬墍鏈夊唴瀹广傚悓鏍凤紝涔熷彲浠ュ鍧楁爣绛句箣闂寸殑浠g爜杩涜澶勭悊銆

For example, heres a custom template tag, {% upper %} , that capitalizes everything between itself and {% endupper %} :

渚嬪锛岃繖涓嚜瀹氫箟妯℃澘鏍囩锛 {% upper %} 锛屽畠鎶婅嚜宸卞拰 {% endupper %} 涔嬮棿鐨勬墍鏈夊唴瀹归兘鍙樻垚澶у啓锛

{% upper %}
    This will appear in uppercase, {{ your_name }}.
{% endupper %}

As in the previous example, well use parser.parse() . This time, we pass the resulting nodelist to Node :

灏卞儚鍓嶉潰鐨勪緥瀛愪竴鏍凤紝鎴戜滑灏嗕娇鐢 parser.parse() 銆傝繖娆★紝鎴戜滑灏嗕骇鐢熺殑 nodelist 浼犻掔粰 Node

@register.tag
def do_upper(parser, token):
    nodelist = parser.parse(('endupper',))
    parser.delete_first_token()
    return UpperNode(nodelist)

class UpperNode(template.Node):

    def __init__(self, nodelist):
        self.nodelist = nodelist

    def render(self, context):
        output = self.nodelist.render(context)
        return output.upper()

The only new concept here is self.nodelist.render(context) in UpperNode.render() . This simply calls render() on each Node in the node list.

杩欓噷鍞竴鐨勪竴涓柊姒傚康鏄 UpperNode.render() 涓殑 self.nodelist.render(context) 銆傚畠瀵硅妭鐐瑰垪琛ㄤ腑鐨勬瘡涓 Node 绠鍗曠殑璋冪敤 render()

For more examples of complex rendering, see the source code for {% if %} , {% for %} , {% ifequal %} , and {% ifchanged %} . They live in django/template/defaulttags.py .

鏇村鐨勫鏉傛覆鏌撶ず渚嬭鏌ョ湅 django/template/defaulttags.py 涓殑 {% if %}{% for %}{% ifequal %}{% ifchanged %} 鐨勪唬鐮併

Shortcut for Simple Tags

绠鍗曟爣绛剧殑蹇嵎鏂瑰紡

Many template tags take a single argumenta string or a template variable referenceand return a string after doing some processing based solely on the input argument and some external information. For example, the current_time tag we wrote earlier is of this variety. We give it a format string, and it returns the time as a string.

璁稿妯℃澘鏍囩鎺ユ敹鍗曚竴鐨勫瓧绗︿覆鍙傛暟鎴栬呬竴涓ā鏉垮彉閲 寮曠敤,鐒跺悗鐙珛鍦版牴鎹緭鍏ュ彉閲忓拰涓浜涘叾瀹冨閮ㄤ俊鎭繘琛屽鐞嗗苟杩斿洖涓涓瓧绗︿覆. 渚嬪, 鎴戜滑鍏堝墠鍐欑殑 current_time 鏍囩灏辨槸杩欐牱涓涓緥瀛. 鎴戜滑缁欏畠鏍煎紡瀛楃涓, 鐒跺悗瀹冩妸鏃堕棿浣滀负瀛楃涓茶繑鍥.

To ease the creation of these types of tags, Django provides a helper function, simple_tag . This function, which is a method of django.template.Library , takes a function that accepts one argument, wraps it in a render function and the other necessary bits mentioned previously, and registers it with the template system.

涓轰簡绠鍖栬繖绫绘爣绛撅紝Django 鎻愪緵浜嗕竴涓府鍔╁嚱鏁帮細 simple_tag 銆傝繖涓嚱鏁版槸 django.template.Library 鐨勪竴涓柟娉曪紝瀹冩帴鍙椾竴涓彧鏈変竴涓弬鏁扮殑鍑芥暟浣滃弬鏁帮紝鎶婂畠鍖呰鍦 render 鍑芥暟鍜屼箣鍓嶆彁鍙婅繃鐨勫叾浠栫殑蹇呰鍗曚綅涓紝鐒跺悗閫氳繃妯℃澘绯荤粺娉ㄥ唽鏍囩銆

Our earlier current_time function could thus be written like this:

鎴戜滑涔嬪墠鐨勭殑 current_time 鍑芥暟浜庢槸鍙互鍐欐垚杩欐牱锛

def current_time(format_string):
    return datetime.datetime.now().strftime(format_string)

register.simple_tag(current_time)

In Python 2.4, the decorator syntax also works:

鍦≒ython 2.4涓紝涔熷彲浠ヤ娇鐢ㄤ慨楗拌娉曪細

@register.simple_tag
def current_time(token):
    ...

A couple of things to notice about the simple_tag helper function are as follows:

鏈夊叧 simple_tag 杈呭姪鍑芥暟锛岄渶瑕佹敞鎰忎笅闈竴浜涗簨鎯咃細

  • Only the (single) argument is passed into our function.

  • 浼犻掔粰鎴戜滑鐨勫嚱鏁扮殑鍙湁锛堝崟涓級鍙傛暟銆

  • Checking for the required number of arguments has already been done by the time our function is called, so we dont need to do that.

  • 鍦ㄦ垜浠殑鍑芥暟琚皟鐢ㄧ殑鏃跺欙紝妫鏌ュ繀闇鍙傛暟涓暟鐨勫伐浣滃凡缁忓畬鎴愪簡锛屾墍浠ユ垜浠笉闇瑕佸啀鍋氳繖涓伐浣溿

  • The quotes around the argument (if any) have already been stripped away, so we receive a plain string.

  • 鍙傛暟涓よ竟鐨勫紩鍙凤紙濡傛灉鏈夌殑璇濓級宸茬粡琚埅鎺変簡锛屾墍浠ユ垜浠細鎺ユ敹鍒颁竴涓櫘閫氬瓧绗︿覆銆

Inclusion Tags

鍖呭惈鏍囩

Another common template tag is the type that displays some data by rendering another template. For example, Djangos admin interface uses custom template tags to display the buttons along the bottom of the add/change form pages. Those buttons always look the same, but the link targets change depending on the object being edited. Theyre a perfect case for using a small template that is filled with details from the current object.

鍙﹀涓绫诲父鐢ㄧ殑妯℃澘鏍囩鏄氳繃娓叉煋 鍏朵粬 妯℃澘鏄剧ず鏁版嵁鐨勩傛瘮濡傝锛孌jango鐨勫悗鍙扮鐞嗙晫闈紝瀹冧娇鐢ㄤ簡鑷畾涔夌殑妯℃澘鏍囩鏉ユ樉绀烘柊澧/缂栬緫琛ㄥ崟椤甸潰涓嬮儴鐨勬寜閽傞偅浜涙寜閽湅璧锋潵鎬绘槸涓鏍风殑锛屼絾鏄摼鎺ュ嵈闅忕潃鎵缂栬緫鐨勫璞$殑涓嶅悓鑰屾敼鍙樸傝繖灏辨槸涓涓娇鐢ㄥ皬妯℃澘寰堝ソ鐨勪緥瀛愶紝杩欎簺灏忔ā鏉垮氨鏄綋鍓嶅璞$殑璇︾粏淇℃伅銆

These sorts of tags are called inclusion tags . Writing inclusion tags is probably best demonstrated by example. Lets write a tag that produces a list of choices for a simple multiple-choice Poll object. Well use the tag like this:

杩欎簺鎺掑簭鏍囩琚О涓 鍖呭惈鏍囩 銆傚浣曞啓鍖呭惈鏍囩鏈濂介氳繃涓句緥鏉ヨ鏄庛傛垜浠潵鍐欎竴涓彲浠ョ敓鎴愪竴涓夐」鍒楄〃鐨勫閫夐」瀵硅薄 Poll 銆傛爣绛捐繖鏍蜂娇鐢細

{% show_results poll %}

The result will be something like this:

缁撴灉灏嗕細鍍忎笅闈㈣繖鏍凤細

<ul>
  <li>First choice</li>
  <li>Second choice</li>
  <li>Third choice</li>
</ul>

First, we define the function that takes the argument and produces a dictionary of data for the result. Notice that we need to return only a dictionary, not anything more complex. This will be used as the context for the template fragment:

棣栧厛锛屾垜浠畾涔変竴涓嚱鏁帮紝閫氳繃缁欏畾鐨勫弬鏁扮敓鎴愪竴涓瓧鍏稿舰寮忕殑缁撴灉銆 闇瑕佹敞鎰忕殑鏄紝鎴戜滑鍙渶瑕佽繑鍥炲瓧鍏哥被鍨嬬殑缁撴灉灏辫浜嗭紝瀹冨皢琚敤鍋氭ā鏉跨墖鏂殑context銆 (璇戞敞锛歞ict 鐨 key 浣滀负鍙橀噺鍚嶅湪妯℃澘涓浣跨敤)

def show_books_for_author(author):
    books = author.book_set.all()
    return {'books': books}

Next, we create the template used to render the tags output. Following our example, the template is very simple:

鎺ヤ笅鏉ワ紝鎴戜滑鍒涘缓鐢ㄤ簬娓叉煋鏍囩杈撳嚭鐨勬ā鏉裤傚湪鎴戜滑鐨勪緥瀛愪腑锛屾ā鏉垮緢绠鍗曪細

<ul>
{% for book in books %}
    <li> {{ book }} </li>
{% endfor %}
</ul>

Finally, we create and register the inclusion tag by calling the inclusion_tag() method on a Library object.

鏈鍚庯紝鎴戜滑閫氳繃瀵逛竴涓 Library 瀵硅薄浣跨敤 inclusion_tag() 鏂规硶鏉ュ垱寤哄苟娉ㄥ唽杩欎釜鍖呭惈鏍囩銆

Following our example, if the preceding template is in a file called polls/result_snippet.html , we register the tag like this:

鍦ㄦ垜浠殑渚嬪瓙涓紝濡傛灉鍏堝墠鐨勬ā鏉垮湪 polls/result_snippet.html 鏂囦欢涓紝閭d箞鎴戜滑杩欐牱娉ㄥ唽鏍囩锛

register.inclusion_tag('books/books_for_author.html')(show_books_for_author)

As always, Python 2.4 decorator syntax works as well, so we could have instead written this:

鍜屽線甯镐竴鏍凤紝鎴戜滑涔熷彲浠ヤ娇鐢≒ython 2.4涓殑淇グ璇硶锛屾墍浠ユ垜浠繕鍙互杩欎箞鍐欙細

@register.inclusion_tag('books/books_for_author.html')
def show_books_for_author(show_books_for_author):
    ...

Sometimes, your inclusion tags need access to values from the parent templates context. To solve this, Django provides a takes_context option for inclusion tags. If you specify takes_context in creating a template tag, the tag will have no required arguments, and the underlying Python function will have one argument: the template context as of when the tag was called.

鏈夋椂鍊欙紝浣犵殑鍖呭惈鏍囩闇瑕佽闂埗妯℃澘鐨刢ontext銆備负浜嗚В鍐宠繖涓棶棰橈紝Django鎻愪緵浜嗕竴涓 takes_context 閫夐」銆傚鏋滀綘鍦ㄥ垱寤烘ā鏉挎爣绛炬椂锛屾寚鏄庝簡杩欎釜閫夐」锛岃繖涓爣绛惧氨涓嶉渶瑕佸弬鏁帮紝骞朵笖涓嬮潰鐨凱ython鍑芥暟浼氬甫涓涓弬鏁帮細灏辨槸褰撹繖涓爣绛捐璋冪敤鏃剁殑妯℃澘context銆

For example, say youre writing an inclusion tag that will always be used in a context that contains home_link and home_title variables that point back to the main page. Heres what the Python function would look like:

渚嬪锛屼綘姝e湪鍐欎竴涓寘鍚爣绛撅紝璇ユ爣绛惧寘鍚湁鎸囧悜涓婚〉鐨 home_linkhome_title 鍙橀噺銆侾ython鍑芥暟浼氬儚杩欐牱锛

@register.inclusion_tag('link.html', takes_context=True)
def jump_link(context):
    return {
        'link': context['home_link'],
        'title': context['home_title'],
    }

Note

澶囨敞

The first parameter to the function must be called context .

鍑芥暟鐨勭涓涓弬鏁 蹇呴』context

The template link.html might contain the following:

妯℃澘 link.html 鍙兘鍖呭惈涓嬮潰鐨勪笢瑗匡細

Jump directly to <a href="{{ link }}">{{ title }}</a>.

Then, anytime you want to use that custom tag, load its library and call it without any arguments, like so:

鐒跺悗鎮ㄦ兂浣跨敤鑷畾涔夋爣绛炬椂锛屽氨鍙互鍔犺浇瀹冪殑搴擄紝鐒跺悗涓嶅甫鍙傛暟鍦拌皟鐢ㄥ畠锛屽氨鍍忚繖鏍凤細

{% jump_link %}

Writing Custom Template Loaders

缂栧啓鑷畾涔夋ā鏉垮姞杞藉櫒

Djangos built-in template loaders (described in the Inside Template Loading section above) will usually cover all your template-loading needs, but its pretty easy to write your own if you need special loading logic. For example, you could load templates from a database, or directly from a Subversion repository using Subversions Python bindings, or (as shown shortly) from a ZIP archive.

Djangos 鍐呯疆鐨勬ā鏉垮姞杞藉櫒锛堝湪鍏堝墠鐨勬ā鏉垮姞杞藉唴骞曠珷鑺傛湁鍙欒堪锛夐氬父浼氭弧瓒充綘鐨勬墍鏈夌殑妯℃澘鍔犺浇闇姹傦紝浣嗘槸濡傛灉浣犳湁鐗规畩鐨勫姞杞介渶姹傜殑璇濓紝缂栧啓鑷繁鐨勬ā鏉垮姞杞藉櫒涔熶細鐩稿綋绠鍗曘傛瘮濡傦細浣犲彲浠ヤ粠鏁版嵁搴撳姞杞芥ā鏉匡紝鎴栬呬娇鐢 Subversions鐨凱ython瀹炵幇鐩存帴浠嶴ubversion搴撳姞杞芥ā鏉匡紝鍐嶆垨鑰咃紙绋嶅悗灞曠ず锛変粠zip鏂囦欢鍔犺浇妯℃澘銆

A template loaderthat is, each entry in the TEMPLATE_LOADERS setting is expected to be a callable with this interface:

涓涓ā鏉垮姞杞藉櫒锛屼篃灏辨槸 TEMPLATE_LOADERS 涓殑姣忎竴椤癸紝閮借鑳借涓嬮潰杩欎釜鎺ュ彛鎵璋冪敤锛

load_template_source(template_name, template_dirs=None)

The template_name argument is the name of the template to load (as passed to loader.get_template() or loader.select_template() ), and template_dirs is an optional list of directories to search instead of TEMPLATE_DIRS .

鍙傛暟 template_name 鏄墍鍔犺浇妯℃澘鐨勫悕绉 (鍜屼紶閫掔粰 loader.get_template() 鎴栬 loader.select_template() 涓鏍), 鑰 template_dirs 鏄竴涓彲閫夌殑鍖呭惈闄ゅ幓 TEMPLATE_DIRS 涔嬪鐨勬悳绱㈢洰褰曞垪琛ㄣ

If a loader is able to successfully load a template, it should return a tuple: (template_source, template_path) . Here, template_source is the template string that will be compiled by the template engine, and template_path is the path the template was loaded from. That path might be shown to the user for debugging purposes, so it should quickly identify where the template was loaded from.

濡傛灉鍔犺浇鍣ㄨ兘澶熸垚鍔熷姞杞戒竴涓ā鏉, 瀹冨簲褰撹繑鍥炰竴涓厓缁勶細 (template_source, template_path) 銆傚湪杩欓噷鐨 template_source 灏辨槸灏嗚妯℃澘寮曟搸缂栬瘧鐨勭殑妯℃澘瀛楃涓诧紝鑰 template_path 鏄鍔犺浇鐨勬ā鏉跨殑璺緞銆傜敱浜庨偅涓矾寰勫彲鑳戒細鍑轰簬璋冭瘯鐩殑鏄剧ず缁欑敤鎴凤紝鍥犳瀹冨簲褰撳緢蹇殑鎸囨槑妯℃澘浠庡摢閲屽姞杞借屾潵銆

If the loader is unable to load a template, it should raise django.template.TemplateDoesNotExist .

濡傛灉鍔犺浇鍣ㄥ姞杞芥ā鏉垮け璐ワ紝閭d箞灏变細瑙﹀彂 django.template.TemplateDoesNotExist 寮傚父銆

Each loader function should also have an is_usable function attribute. This is a Boolean that informs the template engine whether this loader is available in the current Python installation. For example, the eggs loader (which is capable of loading templates from Python eggs) sets is_usable to False if the pkg_resources module isnt installed, because pkg_resources is necessary to read data from eggs.

姣忎釜鍔犺浇鍑芥暟閮藉簲璇ユ湁涓涓悕涓 is_usable 鐨勫嚱鏁板睘鎬с傝繖涓睘鎬ф槸涓涓竷灏斿硷紝鐢ㄤ簬鍛婄煡妯℃澘寮曟搸杩欎釜鍔犺浇鍣ㄦ槸鍚﹀湪褰撳墠瀹夎鐨凱ython涓彲鐢ㄣ備緥濡傦紝濡傛灉 pkg_resources 妯″潡娌℃湁瀹夎鐨勮瘽锛宔ggs鍔犺浇鍣紙瀹冭兘澶熶粠python eggs涓姞杞芥ā鏉匡級灏卞簲璇ユ妸 is_usable 璁句负 False 锛屽洜涓哄繀椤婚氳繃 pkg_resources 鎵嶈兘浠巈ggs涓鍙栨暟鎹

An example should help clarify all of this. Heres a template loader function that can load templates from a ZIP file. It uses a custom setting, TEMPLATE_ZIP_FILES , as a search path instead of TEMPLATE_DIRS , and it expects each item on that path to be a ZIP file containing templates:

涓涓緥瀛愬彲浠ユ竻鏅板湴闃愭槑涓鍒囥傝繖鍎挎槸涓涓ā鏉垮姞杞藉嚱鏁帮紝瀹冨彲浠ヤ粠ZIP鏂囦欢涓姞杞芥ā鏉裤傚畠浣跨敤浜嗚嚜瀹氫箟鐨勮缃 TEMPLATE_ZIP_FILES 鏉ュ彇浠d簡 TEMPLATE_DIRS 鐢ㄤ綔鏌ユ壘璺緞锛屽苟涓斿畠鍋囪鍦ㄦ璺緞涓婄殑姣忎竴涓枃浠堕兘鏄寘鍚ā鏉跨殑ZIP鏂囦欢锛

import zipfile
from django.conf import settings
from django.template import TemplateDoesNotExist

def load_template_source(template_name, template_dirs=None):
    """Template loader that loads templates from a ZIP file."""

    template_zipfiles = getattr(settings, "TEMPLATE_ZIP_FILES", [])

    # Try each ZIP file in TEMPLATE_ZIP_FILES.
    for fname in template_zipfiles:
        try:
            z = zipfile.ZipFile(fname)
            source = z.read(template_name)
        except (IOError, KeyError):
            continue
        z.close()
        # We found a template, so return the source.
        template_path = "%s:%s" % (fname, template_name)
        return (source, template_path)

    # If we reach here, the template couldn't be loaded
    raise TemplateDoesNotExist(template_name)

# This loader is always usable (since zipfile is included with Python)
load_template_source.is_usable = True

The only step left if we want to use this loader is to add it to the TEMPLATE_LOADERS setting. If we put this code in a package called mysite.zip_loader , then we add mysite.zip_loader.load_template_source to TEMPLATE_LOADERS .

鎴戜滑瑕佹兂浣跨敤瀹冿紝杩樺樊鏈鍚庝竴姝ワ紝灏辨槸鎶婂畠鍔犲叆鍒 TEMPLATE_LOADERS 銆傚鏋滄垜浠妸杩欓儴鍒嗕唬鐮佹斁鍒颁竴涓彨鍋 mysite.zip_loader 鐨勫寘涓紝鎴戜滑灏遍渶瑕佹妸 mysite.zip_loader.load_template_source 鍔犲叆鍒 TEMPLATE_LOADERS 涓幓銆

Using the Built-in Template Reference

浣跨敤鍐呯疆鐨勬ā鏉垮弬鑰

Djangos admin interface includes a complete reference of all template tags and filters available for a given site. Its designed to be a tool that Django programmers give to template developers. To see it, go to the admin interface and click the Documentation link at the upper right of the page.

Django绠$悊鐣岄潰鍖呭惈涓涓畬鏁寸殑鍙傝冭祫鏂欙紝閲岄潰鏈夋墍鏈夌殑鍙互鍦ㄧ壒瀹氱綉绔欎笂浣跨敤鐨勬ā鏉挎爣绛惧拰杩囨护鍣ㄣ傚畠璁捐鐨勫垵琛锋槸Django绋嬪簭鍛樻彁渚涚粰妯℃澘寮鍙戜汉鍛樼殑涓涓伐鍏枫備綘鍙互鐐瑰嚮绠$悊椤甸潰鍙充笂瑙掔殑鏂囨。閾炬帴鏉ユ煡鐪嬭繖浜涜祫鏂欍

The reference is divided into four sections: tags, filters, models, and views. The tags and filters sections describe all the built-in tags (in fact, the tag and filter references in Chapter 4 come directly from those pages) as well as any custom tag or filter libraries available.

鍙傝冭鏄庡垎涓4涓儴鍒嗭細鏍囩銆佽繃婊ゅ櫒銆佹ā鍨嬪拰瑙嗗浘銆 鏍囩杩囨护鍣 閮ㄥ垎鎻忚堪浜嗘墍鏈夊唴缃殑鏍囩锛堝疄闄呬笂锛岀4绔犱腑鐢ㄥ埌鐨勬爣绛惧拰杩囨护鍣ㄩ兘鐩存帴鏉ユ簮浜庨偅鍑犻〉锛変互鍙婁竴浜涘彲鐢ㄧ殑鑷畾涔夋爣绛惧拰杩囨护鍣ㄥ簱銆

The views page is the most valuable. Each URL in your site has a separate entry here. If the related view includes a docstring, clicking the URL will show you the following:

瑙嗗浘 椤甸潰鏄渶鏈変环鍊肩殑銆傜綉绔欎腑鐨勬瘡涓猆RL閮藉湪杩欏効鏈夌嫭绔嬬殑鍏ュ彛銆傚鏋滅浉鍏崇殑瑙嗗浘鍖呭惈涓涓 鏂囨。瀛楃涓诧紝 鐐瑰嚮URL锛屼綘灏变細鐪嬪埌锛

  • The name of the view function that generates that view

  • 鐢熸垚鏈鍥剧殑瑙嗗浘鍑芥暟鐨勫悕瀛

  • A short description of what the view does

  • 瑙嗗浘鍔熻兘鐨勪竴涓畝鐭弿杩

  • The context, or a list of variables available in the views template

  • 涓婁笅鏂囨垨涓涓鍥炬ā鏉夸腑鍙敤鐨勫彉閲忕殑鍒楄〃

  • The name of the template or templates that are used for that view

  • 瑙嗗浘浣跨敤鐨勬ā鏉跨殑鍚嶅瓧

For a detailed example of view documentation, read the source code for Djangos generic object_list view, which is in django/views/generic/list_detail.py .

瑕佹兂鏌ョ湅鍏充簬瑙嗗浘鏂囨。鐨勬洿璇︾粏鐨勪緥瀛愶紝璇烽槄璇籇jango鐨勯氱敤 object_list 瑙嗗浘閮ㄥ垎鐨勬簮浠g爜锛屽畠浣嶄簬 django/views/generic/list_detail.py 鏂囦欢涓

Because Django-powered sites usually use database objects, the models pages describe each type of object in the system along with all the fields available on that object.

閫氬父鎯呭喌涓嬶紝鐢盌jango鏋勫缓鐨勭綉绔欓兘浼氫娇鐢ㄦ暟鎹簱瀵硅薄锛 妯″瀷 椤甸潰鎻忚堪浜嗙郴缁熶腑鎵鏈夌被鍨嬬殑瀵硅薄锛屼互鍙婅瀵硅薄瀵瑰簲鐨勬墍鏈夊彲鐢ㄥ瓧娈点

Taken together, the documentation pages should tell you every tag, filter, variable, and object available to you in a given template.

鎬讳箣锛岃繖浜涙枃妗e憡璇変綘鍦ㄦā鏉夸腑鐨勬墍鏈夊彲鐢ㄧ殑鏍囩銆佽繃婊ゅ櫒銆佸彉閲忓拰瀵硅薄銆

Configuring the Template System in Standalone Mode

閰嶇疆鐙珛妯″紡涓嬬殑妯℃澘绯荤粺

Note

澶囨敞

This section is only of interest to people trying to use the template system as an output component in another application. If you are using the template system as part of a Django application, the information presented here doesnt apply to you.

杩欓儴鍒嗗彧閽堝浜庡鍦ㄥ叾浠栧簲鐢ㄤ腑浣跨敤妯$増绯荤粺浣滀负杈撳嚭缁勪欢鎰熷叴瓒g殑浜恒傚鏋滀綘鏄湪Django搴旂敤涓娇鐢ㄦā鐗堢郴缁燂紝璇风暐杩囨閮ㄥ垎銆

Normally, Django will load all the configuration information it needs from its own default configuration file, combined with the settings in the module given in the DJANGO_SETTINGS_MODULE environment variable. But if youre using the template system independently of the rest of Django, the environment variable approach isnt very convenient, because you probably want to configure the template system in line with the rest of your application rather than dealing with settings files and pointing to them via environment variables.

閫氬父锛孌jango浼氫粠瀹冪殑榛樿閰嶇疆鏂囦欢鍜岀敱 DJANGO_SETTINGS_MODULE 鐜鍙橀噺鎵鎸囧畾鐨勬ā鍧椾腑鍔犺浇瀹冮渶瑕佺殑鎵鏈夐厤缃俊鎭備絾鏄綋浣犳兂鍦ㄩ潪Django搴旂敤涓娇鐢ㄦā鐗堢郴缁熺殑鏃跺欙紝閲囩敤鐜鍙橀噺骞朵笉鏄緢濂界殑鏂规硶銆傛瘮璧蜂负妯$増绯荤粺鍗曠嫭閲囩敤閰嶇疆鏂囦欢骞剁敤鐜鍙橀噺鏉ユ寚鍚戝畠锛屼綘鍙兘鏇村笇鏈涜兘澶熷湪浣犵殑搴旂敤涓噰鐢ㄤ竴鑷寸殑閰嶇疆鏂规硶鏉ラ厤缃ā鐗堢郴缁熷拰鍏朵粬閮ㄥ垎

To solve this problem, you need to use the manual configuration option described fully Appendix E. In a nutshell, you need to import the appropriate pieces of the template system and then, before you call any of the template functions, call django.conf.settings.configure() with any settings you wish to specify.

涓轰簡瑙e喅杩欎釜闂锛屼綘闇瑕佷娇鐢ㄩ檮褰旹涓墍鎻忚堪鐨勬墜鍔ㄩ厤缃夐」銆傜畝鍗曟潵璇达紝浣犻渶瑕佸紩鍏ュ悎閫傜殑妯℃澘绯荤粺锛屽苟涓斿湪璋冪敤浠讳綍妯℃澘鍑芥暟 涔嬪墠 璋冪敤 django.conf.settings.configure() 鏉ユ寚瀹氫换浣曚綘鎯宠鐨勮缃

You might want to consider setting at least TEMPLATE_DIRS (if you are going to use template loaders), DEFAULT_CHARSET (although the default of utf-8 is probably fine), and TEMPLATE_DEBUG . All available settings are described in Appendix E, and any setting starting with TEMPLATE_ is of obvious interest.

浣犲彲鑳戒細鑰冭檻鑷冲皯瑕佽缃 TEMPLATE_DIRS 锛堝鏋滀綘鎵撶畻浣跨敤妯℃澘鍔犺浇鍣級锛 DEFAULT_CHARSET 锛堝敖绠¢粯璁ょ殑 utf-8 缂栫爜鐩稿綋濂界敤锛夛紝浠ュ強 TEMPLATE_DEBUG 銆傛墍鏈夊彲鐢ㄧ殑閫夐」閮藉湪闄勫綍E涓缁嗘弿杩帮紝鎵鏈変互 TEMPLATE_ 寮澶寸殑閫夐」閮藉彲鑳戒娇浣犳劅鍏磋叮鐨勩

Whats Next

鎺ヤ笅鏉ワ紵

So far this book has assumed that the content youre displaying is HTML. This isnt a bad assumption for a book about Web development, but at times youll want to use Django to output other data formats.

杩勪粖涓烘锛屾湰涔﹀亣瀹氭偍鎯冲睍绀虹殑鍐呭涓篐TML銆傚浜庝竴涓湁鍏砏eb寮鍙戠殑涔︽潵璇达紝杩欎笉鏄竴涓 涓嶅ソ鐨勫亣璁撅紝浣嗘湁鏃朵綘鎯崇敤Django杈撳嚭鍏朵粬鏁版嵁鏍煎紡銆

The next chapter describes how you can use Django to produce images, PDFs, and any other data format you can imagine.

涓嬩竴绔犲皢璁茶В濡備綍浣跨敤Django鐢熸垚鍥惧儚銆丳DF銆佽繕鏈変綘鍙互鎯冲埌鐨勫叾浠栨暟鎹牸寮忋

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.