一直很想仔細研究一下,我在django模板裏,能夠直接訪問變量user, request之類的變量,哪裏來的,到底都有哪些?這會兒週五,我有空來仔細看看代碼。html
模擬一下需求:django
咱們作一個在線商城,須要把這些全局變量注入到全部頁面,如用戶的資料:好比用戶的帳號、用戶的姓名等。api
一般的解決辦法:app
在每一個views方法中經過render_to_response方法注入用戶數據的話,這樣就會作很是多的重複工做,就像下面這樣: ui
def views_meth1(request): return render_to_response('template_1.html', {'user': request.user}) def views_meth2(request): return render_to_response('template_2.html', {'user': request.user}) def views_meth3(request): return render_to_response('template_3.html', {'user': request.user}) # ...剩下的N個方法
在須要傳入的變量比較簡單、數量較少的時候,這個方法是最簡潔明瞭的。可是一旦須要注入的變量增多,或是須要通過一些額外的計算才能生成的時候,這種方法就會顯得很臃腫,擴展性不好。this
如何避免低效的重複自身代碼,顯然,就是將render_to_response進行再次封裝:spa
# in utils.py: def mp_render(request, template, context={}): context['user'] = request.user return render_to_response(template, context) # in views.py: from utils import mp_render def views_meth1(request): return mp_render(request, 'template_1.html') def views_meth2(request): return mp_render(request, 'template_2.html') def views_meth3(request): return mp_render(request, 'template_3.html')
很好理解,有新增長的全局變量須要注入的話,只須要修改mp_render方法就好了。code
django自帶的解決辦法: htm
下面說到重點:先來看看django文檔裏面對於render_to_response這個方法的定義吧,在’Required arguments’裏面,有提到這個方法的第三個參數,叫context_instance,對於這個參數的說明以下:對象
The context instance to render the template with. By default, the template will be rendered with a Context instance (filled with values from dictionary). If you need to use context processors, render the template with a RequestContext instance instead. Your code might look something like this:
大意是:「默認的,render_to_response方法的第二個dictionary參數會被填充爲一個Context對象注入進html模板文件裏面。若是你須要使用context processors,那麼須要使用一個RequestContext對象來渲染模板。」
那麼什麼是context processors呢?看完這一段文檔的定義之後,應該一切就很明瞭了。
首先須要明白在django模板系統中,有兩種封裝模板變量的類,一個是django.template.Context,這是最經常使用的,咱們在使用render_to_response方法的時候傳入的第二個dictionary參數,就會被這個Context類封裝一次,而後傳到模板當中;另外一個是django.template.RequestContext,它和Context類相比有兩個不一樣之處。第一個不一樣的是,在生成一個RequestContext變量的時候,須要傳入一個HttpRequest對象做爲它的第一個參數:
c = RequestContext(request, {'foo': 'bar', })
第二個區別是,它會增長一些自動注入模板的變量,這些變量從哪兒來呢?在django的settings.py裏有一部分是配置TEMPLATE_CONTEXT_PROCESSORS的,這個配置中的那一個個的tuple元素實際上是一個個能夠被調用的方法,而這些方法都會接收一個HttpRequest對象做爲參數,而最終return一個dictionary,這個dictionary裏面的元素就會成爲RequestContext中自動注入模板的變量。咱們看看settings.py中TEMPLATE_CONTEXT_PROCESSORS的某一個元素 django.contrib.auth.context_processors.auth 對應的代碼吧:
# in django/contrib/auth/context_processors.py def auth(request): """ ignore doc string """ def get_user(): .... return { 'user': SimpleLazyObject(get_user), 'messages': messages.get_messages(request), 'perms': lazy(lambda: PermWrapper(get_user()), PermWrapper)(), }
能夠看到,auth方法最後返回的一個字典中,包含了三個元素,因此若是在使用render_to_response方法時,傳入了第三個RequestContext參數,那麼在它所渲染的模板中,就能夠獲取到對應的user、messages、perms變量了。
因此最後文藝解決方法是,在每個須要注入全局變量的views方法中,調用render_to_response的時候,都傳入第三個RequestContext對象參數便可:
def views_meth1(request): d1 = {'method': 1} return render_to_response('template_1.html', d1, context_instance=RequestContext(request)) def views_meth2(request): d2 = {'method': 2} return render_to_response('template_2.html', d2, context_instance=RequestContext(request)) def views_meth3(request): d3 = {'method': 3} return render_to_response('template_2.html', d3, context_instance=RequestContext(request))
這樣須要注入的全局對象,就能夠經過擴展TEMPLATE_CONTEXT_PROCESSORS來實現,靈活性更高,更易擴展。固然,在通常的項目開發中,我的以爲普通方法也足夠用,因此就根據項目來作取捨吧。
參考文章:http://www.kuqin.com/system-analysis/20120210/318036.html