django admin 模板修改,定制,詳細


我們根據數據庫建立了多個model,此時這個model也是用的admin的原生的模板,因為每個model的樣式可能會不一樣,此時我們可以這樣做。

假如我們要修改名字為back的app的,且model名siteinfo的的change頁面,則我們可以按照如下步驟

(1)在項目的templates建立admin/back/siteinfo

(2)在此目錄下建立change_form.html即可


項目目錄:

[html] view plain copy
  1. shuili  
  2. |-- back  
  3. |   |-- admin.py  
  4. |   |-- admin.pyc  
  5. |   |-- apps.py  
  6. |   |-- backcontroller.py  
  7. |   |-- backcontroller.pyc  
  8. |   |-- __init__.py  
  9. |   |-- __init__.pyc  
  10. |   |-- migrations  
  11. |   |   |-- 0001_initial.py  
  12. |   |   |-- 0001_initial.pyc  
  13. |   |   |-- __init__.py  
  14. |   |   `-- __init__.pyc  
  15. |   |-- models.py  
  16. |   |-- models.pyc  
  17. |   |-- tests.py  
  18. |   `-- views.py  
  19. |-- manage.py  
  20. |-- run.py  
  21. |-- shuili  
  22. |   |-- __init__.py  
  23. |   |-- __init__.pyc  
  24. |   |-- settings.py  
  25. |   |-- settings.pyc  
  26. |   |-- urls.py  
  27. |   |-- urls.pyc  
  28. |   |-- wsgi.py  
  29. |   `-- wsgi.pyc  
  30. `-- templates  
  31.     |-- admin  
  32.     |   |-- back  
  33.     |   |   `-- siteinfo  
  34.     |   |       `-- change_form.html  
  35.     |   `-- change_form.html  
  36.     `-- index.html  


詳細:

admin的禪宗 
作為它的核心,Django的admin設計用來為如下的一個單獨的活動: 
受信任的用戶編輯結構化的內容 
是的,很簡單,但是這簡單的一行隱藏着很多內容,Django的admin的整個哲學都基於此 
讓我們深入了解這個句子的子內容: 
"受信任的用戶" 
admin設計來被你(開發者)信任的人用,這不僅僅表示那些被授權的用戶,它表示Django假設你的內容編輯者可以 
被信任來做正確的事情,這意味着編輯內容沒有批准的過程,如果你信任你的用戶,沒有人需要對編輯的批准 
這也表明了權限系統不支持基於一個對象的限制訪問 
如果你信任某人來編輯他自己的故事,你也將信任他不會在沒有權限的情況下編輯別人的故事 
"編輯" 
Django的admin的首要目的是讓人們編輯內容,這最初看起來很顯而易見,但是也存在一些細小而強大的影響 
例如,盡管admin對重新視查數據很有用,但是它不是設計來干這個的,注意缺少"can view"權限(參考第12章) 
Django假設如果用戶被允許在admin里查看內容,他們也被允許編輯它 
另外一個很值得注意的地方是admin缺少一些例如"工作流"的東西,如果一些任務需要幾步來完成,admin不支持 
特別的順序來做這件事情,admin關注於編輯,而不是圍繞編輯的其它活動 
對於工作流的缺乏支持也起源於信任的原則,admin的哲學是,工作流屬於個人問題,而不應該用代碼實現 
最后,注意admin缺乏統計的支持,它不支持顯示總數,平均數等等 
再一次說明,admin是用來編輯的,它期望你寫自定義的視圖來完成其它的任務 
"結構化的內容" 
因為Django其它部分的關系,admin希望你與結構化的數據工作,這樣,admin僅僅支持編輯用Django模型存儲的數據 
對於其它形式的數據,你則需要自定義視圖 
總結 
現在應該很清楚了,Django的admin不是給任何用戶來做任何事情的,而是牢牢的關注一點並且把這一點做的非常好 
當我們需要擴展Django的admin時,同一哲學的大部分內容存在與此(注意擴展性無處不在) 
因為自定義的Django視圖可以做任何事情,而且它們可以可視化的集成到admin(參看下面內容),內建的定制admin的 
機會在一定程序上被設計所限制 

定制admin模板 
我們下面將看到,你有幾種工具來定制內建的admin模板,但是對於其它任務,例如需要自定義工作流或者細粒度權限 
你將需要閱讀本章末尾講到的定制admin視圖 
現在我們來看看快速定制admin的外觀和行為,第6章講到了一些常見的任務,如更改logo樣式和提供自定義admin表單 
就這點來說,我們通常需要更改一個特殊項的一些模板 
admin的每一個視圖,如更改列表,編輯表單,刪除確認頁面,歷史視圖等都有一個分配的模板 
而這個模板可以通過幾種方式來覆蓋 
首先,你可以全局覆蓋模板,admin視圖使用標准模板載入機制來尋找模板,所以如果你在你的模板目錄里創建模板 
Django將載入並使用這些模板而不是使用Django綁定的默認admin模板 
這些全局模板如下: 
視圖 基本模板名 
更改列表 admin/change_list.html 
增加/編輯表單 admin/change_form.html 
刪除確認 admin/delete_confirmation.html 
對象歷史 admin/object_history.html 
盡管如此,大多數情況下你只想更改一個單獨的對象或者app的模板而不是全局的模板 
這樣的話,每個admin視圖首先尋找模型和app專有的模板,這些視圖按下面的順序尋找模板: 
admin/<app_lable>/<object_name>/<template>.html 
admin/<app_lable>/<template>.html 
admin/<template>.html 
例如,在bookstore app的Book模型的增加/編輯表單的視圖(第6章的例子)按下面的順序尋找模板: 
admin/bookstore/book/change_form.html 
admin/bookstore/change_form.html 
admin/change_form.html 

定制模型模板 
大多數情況下,你想使用上面第一個模板來創建模型專有的模板 
通常情況下通過擴展基本模板並在其中的塊定義中添加信息會將這個任務完成的最好 
例如我們想在book頁面頂端添加一些幫助內容,可能像下面這樣: 
[img][/img] 
這很容易做到,創建一個叫admin/bookstore/book/change_form.html的模板並且插入下面的代碼: 

Java代碼  復制代碼
  1. {% extends "admin/change_form.html" %}   
  2.   
  3. {% block form_top %}   
  4.   <p>Insert meaningful help message here..</p>   
  5. {% endblock %}  
[java]  view plain copy
  1. {% extends "admin/change_form.html" %}  
  2.   
  3. {% block form_top %}  
  4.   <p>Insert meaningful help message here..</p>  
  5. {% endblock %}  

所有的這些模板都定義了一些塊來讓你覆蓋,對於大多數程序,代碼就是最好的文檔,所以我們鼓勵你瀏覽admin模板 
(在django/contrib/admin/templates/里面)來得到最新的信息 

定制JavaScript  
使用這個自定義的模型模板最常見的用途就是添加自定義的JavaScript到admin頁面,可能是實現一些特殊的小窗口部件 
或者是客戶端行為 
幸運的是,這再簡單不過了,每個admin模板定義了一個{% block extrahead %},你可以把使用它來把其它的內容添加 
到head元素里去,例如你想在你的一個admin歷史頁面引入jQuery: 
Java代碼  復制代碼
  1. {% extends "admin/object_history.html" %}   
  2.   
  3. {% block extrahead %}   
  4.     <script src="http://media.example.com/javascript/jquery.js" type="text/javascript"></script>   
  5.     <script type="text/javascript">   
  6.   
  7.         // code to actually use jQuery here...  
  8.   
  9.     </script>   
  10. {% endblock %}  
[java]  view plain copy
  1. {% extends "admin/object_history.html" %}  
  2.   
  3. {% block extrahead %}  
  4.     <script src="http://media.example.com/javascript/jquery.js" type="text/javascript"></script>  
  5.     <script type="text/javascript">  
  6.   
  7.         // code to actually use jQuery here...  
  8.   
  9.     </script>  
  10. {% endblock %}  

我不知道為什么你在對象歷史頁面需要jQuery,但是這個例子適用於admin的任何模板 
你可以使用這個技術來引入任何其它你可能需要的JavaScript小窗口部件 

定制admin視圖  
到目前為止那些想添加自定義行為到Django的admin中的人們可能開始困惑了,他們會喊,"你所講述的都是關於怎樣改變 
admin的外觀,但是我怎樣改變admin的工作方式呢?" 
好了,別喊了,這里就是答案 
需要理解的第一件事就是它一點也不神奇,admin做的任何事都不特殊,它只是一些像其它視圖一樣處理數據的視圖罷了 
這些視圖在django.contrib.admin.views,當然這里有很多代碼,它必須處理所有的選項,域類型和影響模型行為的設置 
同樣的,當你意識到admin只是一些視圖時,添加自定義的admin視圖就變得更容易理解 
讓我們添加一個"publisher report"視圖到我們第6章的book app中,我們將構建一個admin視圖來顯示通過publisher 
分組的books列表,這是一個非常典型你可能想構建的自定義admin"report"的例子 
首先我們在URLconf里面包裝一個視圖,我們需要把這行代碼插入到admin視圖的引入行之前 
Java代碼  復制代碼
  1. (r'^admin/bookstore/report/$''bookstore.admin_views.report'),  
[java]  view plain copy
  1. (r'^admin/bookstore/report/$''bookstore.admin_views.report'),  

完整的URL配置可能像下面這樣: 
Java代碼  復制代碼
  1. from django.conf.urls.defaults import *   
  2.   
  3. urlpatterns = patterns('',   
  4.     (r'^admin/bookstore/report/$''bookstore.admin_views.report'),   
  5.     (r'^admin/', include('django.contrib.admin.urls')),   
  6. )  
[java]  view plain copy
  1. from django.conf.urls.defaults import *  
  2.   
  3. urlpatterns = patterns('',  
  4.     (r'^admin/bookstore/report/$''bookstore.admin_views.report'),  
  5.     (r'^admin/', include('django.contrib.admin.urls')),  
  6. )  

為什么把自定義視圖放在admin引入之前?回想一下Django處理URL模式的順序,因為admin的引入URL匹配幾乎所有的東西 
如果我們把上面的兩行URL配置代碼調換順序,Django將會查找一個內建的視圖來匹配這個URL,這將不能工作 
在這種特殊情況下,Django將試圖載入bookstore app的Report模型的更改列表,這是不存在的 
現在讓我們來寫我們的視圖,為了簡單起見,我們只是載入所有的books在context里並讓模板使用{% regroup %}標簽處理 
分組,用下面的代碼創建一個bookstore/admin_views.py文件: 
Java代碼  復制代碼
  1. from bookstore.models import Book   
  2. from django.template import RequestContext   
  3. from django.shortcuts import render_to_response   
  4. from django.contrib.admin.views.decorators import staff_member_required   
  5.   
  6. @staff_member_required  
  7. def report(request):   
  8.     return render_to_response(   
  9.         "admin/bookstore/report.html",   
  10.         {'book_list' : Book.objects.all()},   
  11.         RequestContext(request, {}),   
  12.     )  
[java]  view plain copy
  1. from bookstore.models import Book  
  2. from django.template import RequestContext  
  3. from django.shortcuts import render_to_response  
  4. from django.contrib.admin.views.decorators import staff_member_required  
  5.   
  6. @staff_member_required  
  7. def report(request):  
  8.     return render_to_response(  
  9.         "admin/bookstore/report.html",  
  10.         {'book_list' : Book.objects.all()},  
  11.         RequestContext(request, {}),  
  12.     )  

因為我們把分組留給模板來做,這個視圖非常簡單,盡管如此,這里有一些細小的東西值得解釋: 
1,我們使用django.contrib.admin.views.decorators的staff_member_required裝飾器,它類似於第12章討論的 
login_required裝飾器,但是這個還檢查給定的用戶是否標記為"staff"成員來決定是否允許訪問admin 
這個裝飾器保護所有內建的admin視圖,讓你的視圖的認證邏輯和admin的其它部分匹配 
2,我們渲染在admin/下面的模板,雖然這沒有嚴格的要求,但是保持你所有的admin模板分組在一個admin目錄下 
被認為是最佳實踐,我們把模板放在我們的app后面叫bookstore的目錄下也是最佳實踐 
3,我們使用RequestContext作為第3個參數(context_instance)傳遞給render_to_response 
這保證了關於當前用戶的信息可以在模板里得到,參看第10章得到更多關於RequestContext的信息 
最后我們將為這個視圖創建一個模板,我們繼承內建的admin模板來使這個視圖視覺上看起來是admin的一部分: 
Java代碼  復制代碼
  1. {% extends "admin/base_site.html" %}   
  2.   
  3. {% block title %}List of books by publisher{% endblock %}   
  4.   
  5. {% block content %}   
  6. <div id="content-main">   
  7.   <h1>List of books by publisher:</h1>   
  8.   {% regroup book_list|dictsort:"publisher.name" by publisher as books_by_publisher %}   
  9.   {% for publisher in books_by_publisher %}   
  10.     <h3>{{ publisher.grouper }}</h3>   
  11.     <ul>   
  12.       {% for book in publisher.list|dictsort:"title" %}   
  13.             <li>{{ book }}</li>   
  14.       {% endfor %}   
  15.     </ul>   
  16.   {% endfor %}   
  17. </div>   
  18. {% endblock %}  
[java]  view plain copy
  1. {% extends "admin/base_site.html" %}  
  2.   
  3. {% block title %}List of books by publisher{% endblock %}  
  4.   
  5. {% block content %}  
  6. <div id="content-main">  
  7.   <h1>List of books by publisher:</h1>  
  8.   {% regroup book_list|dictsort:"publisher.name" by publisher as books_by_publisher %}  
  9.   {% for publisher in books_by_publisher %}  
  10.     <h3>{{ publisher.grouper }}</h3>  
  11.     <ul>  
  12.       {% for book in publisher.list|dictsort:"title" %}  
  13.             <li>{{ book }}</li>  
  14.       {% endfor %}  
  15.     </ul>  
  16.   {% endfor %}  
  17. </div>  
  18. {% endblock %}  

通過繼承admin/base_site.html我們"免費"得到Django的admin的外觀,它看起來像這樣: 
[img][/img] 

今天你需要在哪里使用admin?  
你可以使用這個技術來向admin添加任何你想到的東西,記住所謂的"定制admin視圖"事實上只是普通的Django視圖 
你可以使用你在本書其它部分所學的所有技術來構建任意復雜的admin視圖 
我們將以一些自定義admin視圖的一些好注意結束本章內容 

覆蓋內建的視圖  
默認的admin視圖不包含這些,你可以很輕松的在admin的任何地方跳轉到你的自定義視圖,只需讓你的URL覆蓋掉內建的那些 
例如,我們可以用一個簡單的讓用戶輸入ISBN的表單替代內建的book創建視圖,然后我們就可以從http://isbn.nu/來查詢 
book信息和自動創建對象 
這個視圖的代碼留給讀者做練習,最重要的部分是下面的URL配置: 
Java代碼  復制代碼
  1. (r'^admin/bookstore/book/add/$''bookstore.admin_views.add_by_isbn'),  
[java]  view plain copy
  1. (r'^admin/bookstore/book/add/$''bookstore.admin_views.add_by_isbn'),  

如果這段代碼在你的URL配置中放在admin的URL前面的話,add_by_isbn視圖將完全替代標准的admin視圖 
我們可以遵循類似的動作來替代刪除確認頁面,編輯頁面或者admin的任何其它部分


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM