這篇文章主要介紹了在Django的通用視圖中處理Context的方法,Django是最具人氣的Python web開發框架,需要的朋友可以參考下
制作友好的模板Context
你也許已經注意到范例中的出版商列表模板在變量 object_list 里保存所有的書籍。這個方法工作的很好,只是對編寫模板的人不太友好。 他們必須知道這里正在處理的是書籍。 更好的變量名應該是publisher_list,這樣變量所代表的內容就顯而易見了。
我們可以很容易地像下面這樣修改 template_object_name 參數的名稱:
- from django.conf.urls.defaults import *
- from django.views.generic import list_detail
- from mysite.books.models import Publisher
- publisher_info = {
- 'queryset': Publisher.objects.all(),
- 'template_name': 'publisher_list_page.html',
- 'template_object_name': 'publisher',
- }
- urlpatterns = patterns('',
- (r'^publishers/$', list_detail.object_list, publisher_info)
- )
在模板中,通用視圖會通過在template_object_name后追加一個_list的方式來創建一個表示列表項目的變量名。
使用有用的 template_object_name 總是個好想法。 你的設計模板的合作伙伴會感謝你的。
添加額外的Context
你常常需要呈現比通用視圖提供的更多的額外信息。 例如,考慮一下在每個出版商的詳細頁面顯示所有其他出版商列表。 object_detail 通用視圖為context提供了出版商信息,但是看起來沒有辦法在模板中 獲取 所有 出版商列表。
這是解決方法: 所有的通用視圖都有一個額外的可選參數 extra_context 。這個參數是一個字典數據類型,包含要添加到模板的context中的額外的對象。 所以要給視圖提供所有出版商的列表,我們就用這樣的info字典:
- publisher_info = {
- 'queryset': Publisher.objects.all(),
- 'template_object_name': 'publisher',
- **'extra_context': {'book_list': Book.objects.all()}**
- }
這樣就把一個 {{ book_list }} 變量放到模板的context中。 這個方法可以用來傳遞任意數據 到通用視圖模板中去,非常方便。 這是非常方便的
不過,這里有一個很隱蔽的BUG,不知道你發現了沒有?
我們現在來看一下, extra_context 里包含數據庫查詢的問題。 因為在這個例子中,我們把 Publisher.objects.all() 放在URLconf中,它只會執行一次(當URLconf第一次加載的時候)。 當你添加或刪除出版商,你會發現在重啟Web服務器之前,通用視圖不會反映出這些修改(有關QuerySet何時被緩存和賦值的更多信息請參考附錄C中“緩存與查詢集”一節)。
備注
這個問題不適用于通用視圖的 queryset 參數。 因為Django知道有些特別的 QuerySet 永遠不能 被緩存,通用視圖在渲染前都做了緩存清除工作。
解決這個問題的辦法是在 extra_context 中用一個回調(callback)來代替使用一個變量。 任何傳遞給extra_context的可調用對象(例如一個函數)都會在每次視圖渲染前執行(而不是只執行一次)。 你可以象這樣定義一個函數:
- **def get_books():**
- **return Book.objects.all()**
- publisher_info = {
- 'queryset': Publisher.objects.all(),
- 'template_object_name': 'publisher',
- 'extra_context': **{'book_list': get_books}**
- }
或者你可以使用另一個不是那么清晰但是很簡短的方法,事實上 Publisher.objects.all 本身就是可以調用的:
- publisher_info = {
- 'queryset': Publisher.objects.all(),
- 'template_object_name': 'publisher',
- 'extra_context': **{'book_list': Book.objects.all}**
- }
注意 Book.objects.all 后面沒有括號;這表示這是一個函數的引用,并沒有真正調用它(通用視圖將會在渲染時調用它)。
新聞熱點
疑難解答