Django admin高階用法
@[toc]
Django admin高階用法
使用Django意味著後臺框架的幾乎所有內容都會和Django產生互動,排除功能全部手擼的情況.
Django 後臺admin有大量的屬性和方法,擁有強大的功能和自定義能力.通過完整的程式碼來看Django admin的基礎設定和高階用法,並結合form表單來實現深度自定義.
簡單使用
如果只是使用admin自帶的資料管理功能,只需要將模型註冊到admin中,就可以實現.
from django.contrib import admin
admin.site.register(News)
admin.site.register(NewsType)
admin.site.site_header = "資料庫"
admin.site.index_title = "新聞後臺"
複製程式碼
Django後臺會將對應資料表的所有欄位進行展示,預設點選id
會進入修改頁面,對應change_form.html
模板.
自定義admin類
使用admin也可以自定義一個admin的類,來自定義後臺實現的屬性和方法,然後通過register()
來將自定義的類和模型註冊在一起.
註冊方式有兩種,一種是使用類裝飾器,一種是使用site
from django.contrib import admin
# 裝飾器註冊
@admin.register(ModelClass)
class CustomAdmin(admin.ModelAdmin) :
list_display = '__all__'
複製程式碼
# 使用site
class CustomAdmin(admin.ModelAdmin):
exclude = ['id']
admin.site.register(CustomAdmin,ModelClass)
複製程式碼
admin顯示屬性的設定
ModelAdmin中的屬性設定
admin可以設定在列表頁和詳情頁顯示的欄位以及搜尋欄位等的限制,在admin的類中可以直接定義.
以使用較多的ModelAdmin
為例,ModelAdmin
原始碼中的屬性有:
# 在列表頁顯示的欄位,預設會顯示所有欄位,有對應的方法可以重寫
list_display = ('__str__',)
# 在列表頁顯示的欄位中,可以連結到change_form頁面的欄位
list_display_links = ()
# 右側的篩選,必須是欄位,可以繼承自SimpleListFilter來自定義篩選欄位和規則,SimpleListFilter的方法在後面詳細介紹
list_filter = ()
# 聯表查詢是否自動查詢,可以是布林,列表或元組,如果是列表或元組,則級聯查詢指定的欄位
list_select_related = False
# 列表頁每頁展示的條數
list_per_page = 100
# 分頁,顯示全部,真是資料小於該值時才會顯示全部
list_max_show_all = 200
# 在列表頁可以編輯的欄位
list_editable = ()
# 在列表頁可以模糊搜尋的欄位
search_fields = ()
# 對Date和DateTime型別進行搜尋
date_hierarchy = None
# 在change_form頁面,按鈕為,save按鈕的值(save as new和save add another)
save_as = False
# 點選儲存並繼續編輯
save_as_continue = True
# save按鈕的位置,是True則顯示在頁面上方
save_on_top = False
# 自定義分頁類
paginator = Paginator
# 詳細頁面,刪除、修改,更新後跳轉回列表後,是否保留原搜尋條件管理員現在在建立,編輯或刪除物件後保留列表檢視中的過濾器。
# 可以將此屬性設定為False,以恢復之前清除過濾器的行為。
preserve_filters = True
# 在詳情頁面,如果有FK到其他表,在詳情頁中可以動態的填加或刪除級聯資料
inlines = []
複製程式碼
admin中action操作的設定
admin中的action是指在列表頁的動作,預設為刪除所選的條目,可以自定義填加動作,將動作註冊到action中,需要是一個方法
# 定製action中的操作
actions = []
action_form = helpers.ActionForm
# action選項顯示的位置,頁面上方或者頁面下方
actions_on_top = True
actions_on_bottom = False
# 是否顯示action選擇的個數
actions_selection_counter = True
checks_class = ModelAdminChecks
複製程式碼
BaseModelAdmin中的屬性
除了ModelAdmin中的屬性,也可以自定義在其父類BaseModelAdmin中的屬性和方法,是一些通用的,在繼承子BaseModelAdmin的類中也可以完成的屬性設定.一般是詳情頁的屬性.
# 自動補全,外來鍵查詢資料多時,方便查詢
autocomplete_fields = ()
# 詳情頁,針對外來鍵和M2M欄位變成input框形式
raw_id_fields = ()
# 詳情頁面展示的欄位
fields = None
# 詳情頁面排除的欄位,欄位可以是資料庫中的也可以是自定義的
exclude = None
# 在詳情頁面對資料進行分隔顯示,對應到admin模板中的'fieldsets.html'
fieldsets = None
# 為詳情頁指定form表單,可以自定義顯示的資料,欄位
form = forms.ModelForm
# 下面兩個是M2M顯示時,資料移動選擇.可以參考admin中使用者的許可權操作
filter_vertical = () # 縱向展示
filter_horizontal = () # 橫向展示
# 詳情頁面使用radio顯示選項,FK預設使用select
radio_fields = {}
# 填加頁面,在某欄位輸入值後,自動填加到指定欄位
# prepopulated_fields = {"email": ("user",)},email欄位會在使用者填加user欄位時自動填充
prepopulated_fields = {}
# 詳情頁指定顯示的外掛,後面詳細說明
formfield_overrides = {}
# 詳情頁面的只讀欄位
readonly_fields = ()
# 詳情頁面排序規則
ordering = None
# 禁止某些排序,為空則禁止所有的排序
sortable_by = None
# 編輯時是否在頁面上顯示view on set,可以通過方法來返回一個連結,後面說明
view_on_site = True
# 列表頁,模糊搜尋後面顯示的資料個數樣式
# 為True是顯示條數,為False時顯示全部
show_full_result_count = True
checks_class = BaseModelAdminChecks
複製程式碼
模板的定製
指定自定義模板
在ModelAdmin中自帶了幾個指定模板的屬性,可以自己定義HTML檔案,來指定給某個模板頁面
# Custom templates (designed to be over-ridden in subclasses)
# 新增資料模板頁
add_form_template = None
# 修改資料的模板頁
change_form_template = None
# 修改多條資料的模板頁
change_list_template = None
# 刪除確認資訊模板頁
delete_confirmation_template = None
# 刪除關聯資料的確認頁
delete_selected_confirmation_template = None
# 修改歷史的模板頁
object_history_template = None
# 彈出框模板頁
popup_response_template = None
複製程式碼
重寫自帶模板
在django admin裡面有自己寫好的模板,include模板,每個app也有對應的模板
admin的自帶模板在專案的django/contrib/admin/templates/admin
,目錄下面
include
文目錄下是include
語法包含的模板。
change_form.html
是資料修改頁面的模板,如果想在資料詳情頁面自定義顯示的內容,可以自定義這個頁面
模板使用的全都是模板語法,注意模板語法的繼承機制,在當前頁面重寫的元素,不會直接顯示。
fieldset.htlm
是拼接成詳情頁的塊。前面提到,自定義admin類中的fieldset
屬性,可以自定義詳情頁,使資料欄位分塊顯示,就是改變了傳給這個頁面的值。
例如,使用if
語句來動態新增jQuery和div
標籤,只有在訪問某個app的資料時新增
{% if app_name in request.path %}
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"></script>
<div>
<fieldset class="custom">
<div id="div"></div>
</fieldset>
{% endif %}
複製程式碼
結合form表單
django admin結合form表單,重寫fieldset.html
來實現資料詳情頁面的深度自定義,通過處理form表單提交的資料,來實現後臺功能的完全自定義。
django的admin中可以指定form類,來自定義顯示的內容
from django import forms
# TagValueManager是自定義的類
from tag_manager import TagValueManager
class CustomAddForm(forms.ModelForm):
""" 根據標籤的id,動態生成下拉選項框 """
for i in TagValueManager.all_tag:
locals()[
'field_tag_id_{}'.format(
i['id'])] = forms.ChoiceField(
choices=TagValueManager.get_choice(
i['id']),label=i['name'])
class Meta:
model = CandidateTag
fields = '__all__'
exclude = ['tag_id','tag_value','ext_1','ext_2','candidate_id']
複製程式碼
注意:在form表單中動態生成的屬性,必須使用
fields=’__all__‘
屬性,否則不會顯示,可以結合exclude
屬性來控制需要顯示的表單
然後在admin中註冊form類
class CandidateTagAdmin(admin.ModelAdmin):
list_display = [
'id','tag_count',]
form = CustomAddForm
複製程式碼
自定義列表頁來源
除了可以通過修改admin的屬性,來實現列表頁展示欄位的自定義,也可以對列表頁資料進行篩選,例如,篩選出活躍的使用者等,這個可以在action
中定義新的方法
也可以重寫admin中的get_queryset
方法,返回的qs是重新篩選之後的資料,可以避免一些業務邏輯上的誤操作
這裡的程式碼展示了,在列表頁,展示其他表中的資料,註冊模型表的資料沒有展示
def get_queryset(self,request):
"""
從candidate表中查詢資料,在list_display中統計其標籤個數
"""
qs = Candidate.objects.all().order_by('id')
return qs
複製程式碼
## 處理form資料
給admin類定義form屬性之後,在詳情頁面傳回的資料,會帶上form表單裡面的資料,然後結合業務邏輯處理這個資料
例如,業務場景,接受form資料,儲存到其他幾張表,對於展示資料的表,不進行任何操作,那就需要重寫save_model
方法,這個方法呼叫了模型的save
方法
重寫這個方法:
def save_model(self,request,obj,form,change):
"""
重寫save_model方法
"""
candidate_id = request.path.split('/')[4]
post_dict = request.POST
# 根據返回的form表單的標籤來確定修改的tag_id
include_field = 'field_tag_id_'
for key,value in post_dict.items():
if include_field in key:
tag_id = key.split('_')[-1]
tag_value = value
try:
obj,created = CandidateTag.objects.update_or_create(
defaults={'tag_value': tag_value},candidate_id=candidate_id,tag_id=tag_id)
except Exception as e:
tag_name = TagValueManager.all_tag.get(id=tag_id)['name']
messages.add_message(request,messages.ERROR,'求職者的"{}"標籤資訊儲存失敗'.format(tag_name))
複製程式碼
擴充套件
在get_queryset
方法中,展示類模型中的統計資料,這個統計資料,不是在資料庫中生成的,實在模型類中定義的方法,這個方法的返回值,可以在列表頁中直接展示。例如上文中說道的標籤的個數
同時,也可以返回一個HTML標籤,模板語法中獲取這個欄位時,得到的是一個HTML標籤,直接渲染
from django.utils.safestring import mark_safe
# 使用mark_safe
@mark_safe
def get_user_dept(self,obj):
""" 這個方法在模型中 """
return "<p>this is a HTML tag</p>"
# 允許HTML標籤
get_report_depts.allow_tags = True
# HTML展示時的欄位名
get_report_depts.short_description = '所屬部門'
複製程式碼