Django admin的個性化定制
首先我們看下,前面章節中定義的models在admin后台管理界面的樣子:
然后我們看下老男孩教育點名平台的admin管理表的后台界面樣子:
admin管理后台常用的就是上面操作的這幾種吧,我們來看下如何實現?
首先我們知道,使用admin后台管理表,需要將表注冊到admins.py文件中:
1 from django.contrib import admin 2 # Register your models here. 3 from app01 import models 4 admin.site.register(models.Author) # 注冊進來 5 admin.site.register(models.Book) # 注冊進來 6 admin.site.register(models.Publisher)
這樣就簡單實現了圖一中的管理界面.
配置成圖2中的顯示多個字段的管理界面其實也很簡單,在admins.py配置文件兩步實現:
1.創建一個管理表單的admin類
2.將這個admin類在注冊表的時候關聯起來.
class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') #指定顯示的字段 admin.site.register(models.Author) admin.site.register(models.Book,BookAdmin) # 注冊的時候,把定義的BookAdmin類作為參數傳入進來 admin.site.register(models.Publisher)
保存后,訪問http://127.0.0.1:8000/admin/app01/book/
結果如下:
這里我們有一點關於顯示Book表中定義的關於manytomany關系表的顯示.
Django admin后台管理是不支持顯示這種many_to_many關系的,如果你配置了,
1 class BookAdmin(admin.ModelAdmin): 2 list_display = ('title','authors','publisher','publication_date') #指定顯示的字段
訪問時會報如下錯誤:
1 <class 'app01.admin.BookAdmin'>: (admin.E109) The value of 'list_display[1]' must not be a ManyToManyField.
為什么呢?
因為一行顯示不了多個作者.並且這樣顯示,效率非常底,因為它要另外一張表一個一個查找出來.多一次查詢.
了解了怎么實現個性化定制admin的方法.下面我們定義其他想圖2中的配置.
1 from django.contrib import admin 2 3 # Register your models here. 4 from app01 import models 5 6 class BookAdmin(admin.ModelAdmin): 7 list_display = ('id','title','publisher','publication_date') #指定顯示的字段 8 search_fields = ('title','publisher__name') #添加搜索字段 9 # 這里我們定義了兩個可以提供搜尋的字段 Book.title 和一個外鍵表.name 10 # 我們知道外鍵關聯的是另外一個orm類,如果你想在本張表中通過搜索關聯表字段來做帥選,是不是要搜外間表.Django admin里使用publisher__字段名 的方式實現了讓你在當前表搜外鍵表的功能 11 list_filter = ('publisher','publication_date') # 添加按照字段過濾的關鍵字list_filter 12 # 這里外鍵就可以直接寫字段了. 13 list_editable = ('title','publisher','publication_date') #讓后台界面上可以直接修改字段值的關鍵字定義list_editable 14 #這里注意Django admin后台默認顯示的第一個表字段是不能修改的. 15 list_per_page = 10 # 讓每頁顯示幾條記錄的設置 16 17 filter_horizontal = ('authors',) #只針對多對多 18 raw_id_fields = ('publisher',) # 只針對外鍵的 19 20 21 22 admin.site.register(models.Author) 23 admin.site.register(models.Book,BookAdmin) # 注冊的時候,把定義的BookAdmin類作為參數傳入進來 24 admin.site.register(models.Publisher)
首頁里顯示的東西差不多就這些定制.
訪問頁面看下效果:
接下來就是點到條目內的個性化定制
filter_horizontal = ('authors',) #只針對多對多
raw_id_fields = ('publisher',) # 只針對外鍵的
我們看下效果:
Django的后台管理只適用內容管理,像監控平台這種不能用admin后台管理!!
Admin Actions
配置admin后台的Admin Actions 來進行批量操作.
假如,Book有一個狀態:已出版\待出版\禁書
首先我們先給models.py文件中的Book 類,加一個字段為status,並且這個字段的值只能選擇3個狀態中的一個
1 class Book(models.Model): 2 title = models.CharField(max_length=100) 3 authors = models.ManyToManyField(Author) 4 publisher = models.ForeignKey(Publisher) 5 publication_date = models.DateField() 6 7 # 添加狀態的選擇范圍,用戶在創建的時候只能從這里選擇三個狀態 8 status_choices = (('published',u"已出版"), 9 ('producing',u"待出版"), 10 ('forbidden',u"禁書"), 11 12 ) 13 # 前面定義了選項,這里要創建一個字段用到前面的選項 14 status = models.CharField(choices=status_choices,max_length=32) 15 def __str__(self): 16 return "<%s>"%(self.title)
我們完成上面的更改后,在執行同步數據庫的操作.這里會碰到一個問題,因為我們是給一個已存在的表添加字段,那么添加之前的記錄都沒有這個字段,我們添加字段的時候,就要給一個默認值.
如果不給我們在使用命令生成配置文件也會提示我們,讓我們設置一個.如:
1 $ python3.5 manage.py makemigrations 2 You are trying to add a non-nullable field 'status' to book without a default; we can't do that (the database needs something to populate existing rows). 3 Please select a fix: 4 1) Provide a one-off default now (will be set on all existing rows) 5 2) Quit, and let me add a default in models.py 6 Select an option:
那我們最后是在添加status字段的時候定義.如:
1 class Book(models.Model): 2 title = models.CharField(max_length=100) 3 authors = models.ManyToManyField(Author) 4 publisher = models.ForeignKey(Publisher) 5 publication_date = models.DateField() 6 7 # 添加狀態的選擇范圍,用戶在創建的時候只能從這里選擇三個狀態 8 status_choices = (('published',u"已出版"), 9 ('producing',u"待出版"), 10 ('forbidden',u"禁書"), 11 12 ) 13 # 前面定義了選項,這里要創建一個字段用到前面的選項 14 status = models.CharField(choices=status_choices,max_length=32,default='producing') #這里加一個default屬性 15 def __str__(self): 16 return "<%s>"%(self.title)
然后我們在同步數據庫,就不會報錯了,如:
1 $ python3.5 manage.py makemigrations 2 Migrations for 'app01': 3 0002_book_status.py: 4 - Add field status to book 5 zhoumingdeMacBook-Pro:day18_site tedzhou$ python3.5 manage.py migrate 6 Operations to perform: 7 Apply all migrations: admin, app01, auth, sessions, contenttypes 8 Running migrations: 9 Rendering model states... DONE 10 Applying app01.0002_book_status... OK
然后讓status顯示在admin管理后台
1 class BookAdmin(admin.ModelAdmin): 2 list_display = ('id','title','publisher','publication_date','status') #把status加入到顯示列表 3 search_fields = ('title','publisher__name') #添加搜索字段 4 list_filter = ('publisher','publication_date') # 添加按照字段過濾的關鍵字list_filter 5 list_editable = ('title','publisher','publication_date','status') # 把status加入可編輯列表 6 list_per_page = 10 # 讓每頁顯示幾條記錄的設置 7 8 filter_horizontal = ('authors',) #只針對多對多字段 9 raw_id_fields = ('publisher',) # 只針對外鍵的 10 11 12 admin.site.register(models.Author) 13 admin.site.register(models.Book,BookAdmin) # 注冊的時候,把定義的BookAdmin類作為參數傳入進來 14 admin.site.register(models.Publisher)
這時候我們訪問后台http://127.0.0.1:8000/admin/app01/book/?
然后我們就是如何實現把更高status放到admin Action中,進行批量更改記錄了.
兩步:都是在admin.py文件里操作
1.定義更改字段的函數
2.在ModelAdmin類里添加actions=[]屬性
代碼如下:
1 def make_forbidden(modelAdmin,request,queryset): #這里必須是三個參數,modelAdmin指的是調用此函數的modelAdmin的類,queryset指的是我們在后台中選中的記錄 2 print('--->',request,queryset) 3 queryset.update(status='forbidden') 4 make_forbidden.short_description = "Set to forbidden" # 定義在action后台中顯示的文本內容 5 6 class BookAdmin(admin.ModelAdmin): 7 list_display = ('id','title','publisher','publication_date','status') 8 search_fields = ('title','publisher__name') 9 list_filter = ('publisher','publication_date') 10 list_editable = ('title','publisher','publication_date','status') 11 list_per_page = 10 12 13 filter_horizontal = ('authors',) 14 raw_id_fields = ('publisher',) 15 actions = [make_forbidden,] #定義actions屬性 16 admin.site.register(models.Author) 17 admin.site.register(models.Book,BookAdmin) # 注冊的時候,把定義的BookAdmin類作為參數傳入進來 18 admin.site.register(models.Publisher)
此時我們就可以批量操作記錄了http://127.0.0.1:8000/admin/app01/book/
ok 添加action的功能就這樣實現了。
django admin 擴展之根據不同的status狀態,顯示不同顏色
引入圖片010.png
代碼如何顯示呢?
1.首先要在models.py文件里的Book類里寫一個函數如下:
1 class Book(models.Model): 2 title = models.CharField(max_length=100) 3 authors = models.ManyToManyField(Author) 4 publisher = models.ForeignKey(Publisher) 5 publication_date = models.DateField() 6 7 # 添加狀態的選擇范圍,用戶在創建的時候只能從這里選擇三個狀態 8 status_choices = (('published',u"已出版"), 9 ('producing',u"待出版"), 10 ('forbidden',u"禁書"), 11 12 ) 13 # 前面定義了選項,這里要創建一個字段用到前面的選項 14 status = models.CharField(choices=status_choices,max_length=32,default='producing') 15 def __str__(self): 16 return "<%s>"%(self.title) 17 18 # 新Book類中新定義colored_status方法 19 def colored_status(self): 20 if self.status == "published": 21 # format_td = format_html('<span stype="padding:2px;color:white">已報名</span>') 22 format_td = '<span stype="padding:2px;background-color:yellowgreen;color:white">已出版</span>' 23 elif self.status == 'producing': 24 format_td = '<span stype="padding:2px;background-color:pink;color:white">待出版</span>' 25 elif self.status == 'forbidden': 26 format_td = '<span stype="padding:2px;background-color:orange;color:white">禁書</span>' 27 28 return format_td
2.定義好后,如何在后台中顯示該內容呢?在admin里定義的顯示列表中直接將此方法加入即可
1 class BookAdmin(admin.ModelAdmin): 2 list_display = ('id','title','publisher','publication_date','colored_status','status') #指定顯示的字段
3.然后我們在瀏覽器訪問http://127.0.0.1:8000/admin/app01/book/
顯示如下
4.我們看到雖然admin后台中顯示新加的字段內容.但是卻不是前端的代碼,而是一個字符串.這個在Django1.7及以前都是直接解析成前端代碼的.而現在我們用的1.9,就需要在models.py文件中定義Book類中方法時調用format_html方法.
代碼如下:
1 from django.utils.html import format_html # 引入format_html方法 2 class Book(models.Model): 3 title = models.CharField(max_length=100) 4 authors = models.ManyToManyField(Author) 5 publisher = models.ForeignKey(Publisher) 6 publication_date = models.DateField() 7 8 # 添加狀態的選擇范圍,用戶在創建的時候只能從這里選擇三個狀態 9 status_choices = (('published',u"已出版"), 10 ('producing',u"待出版"), 11 ('forbidden',u"禁書"), 12 13 ) 14 # 前面定義了選項,這里要創建一個字段用到前面的選項 15 status = models.CharField(choices=status_choices,max_length=32,default='producing') 16 def __str__(self): 17 return "<%s>"%(self.title) 18 19 def colored_status(self): 20 if self.status == "published": 21 format_td = format_html('<span stype="padding:2px;background-color:yellowgreen;color:white">已出版</span>') # 實例化format_html類 22 elif self.status == 'producing': 23 format_td = format_html('<span stype="padding:2px;background-color:pink;color:white">待出版</span>') 24 elif self.status == 'forbidden': 25 format_td = format_html('<span stype="padding:2px;background-color:orange;color:white">禁書</span>') 26 27 return format_td
5.再次訪問http://127.0.0.1:8000/admin/app01/book/