在django admin的 change_view, add_view和delete_view頁面,如果想讓頁面完成操作后跳轉到我們想去的url,該怎么做
默認django admin會跳轉到changelist_view頁面
------------------------------
下面的代碼是django1.6的
下面是一個可行的做法,寫admin model的時候重寫父類admin.ModelAdmin的change_view 方法
from django.contrib import admin class MyAdmin(admin.ModelAdmin): def change_view(self, request, object_id, form_url='', extra_context=None): result_template = super(MyAdmin, self).change_view(request, object_id, form_url, extra_context) result_template['location'] = '/dest/url' return result_template
可以看到,就是調用ModelAdmin的change_view得到結果,然后給 result_template做了一個這個操作
result_template['location'] = '/dest/url'
然后返回
為什么這樣可行? 我們看看發生了什么
我們重寫change_view,當然參數必須和父類一樣了
首先調用了父類ModelAdmin.change_view的這個函數,這個函數返回了什么呢
追溯一下源代碼,它返回的是一個TemplateResponse對象, 是通過調用 ModelAdmin.render_change_form()
return TemplateResponse(request, form_template or [ "admin/%s/%s/change_form.html" % (app_label, opts.model_name), "admin/%s/change_form.html" % app_label, "admin/change_form.html" ], context, current_app=self.admin_site.name)
那么接下來我們看看TemplateResponse
其實有這樣的派生關系: TemplateResponse <---- SimpleTemplage <-----HttpRespone <--- HttpResponseBase
HttpResponse里實現了
def __setitem__(self, header, value): header = self._convert_to_charset(header, 'ascii') value = self._convert_to_charset(value, 'latin-1', mime_encode=True) self._headers[header.lower()] = (header, value)
而如果一個類實現了 __setitem__, 那么[] 操作符就會去調用這個函數(相當於C++中的重載)
result_template['location'] = '/dest/url'
所以上面這行代碼就在服務器返回的Response的header中寫入了location, 而瀏覽器收到的Http Response的header中如果有location,就會跳轉到location指定的 url
-------------------------------------------------------
但是我還發現了一個現象, 當進入到一個model item的change_view界面時,也就是GET請求這個url,雖然服務端返回了location,但是瀏覽器沒有跳轉,可能是因為當前有form需要提交.
而在change_view界面修改完后, 點擊提交表單,瀏覽器收到服務端的location后,就發生了跳轉.