Web 應用中離不開的就是後臺管理, Django 自帶的 admin 組件提供了一部份內容,但每每現實項目中會有更多的需求,因此自定義本身的後臺管理就十分重要了,此處所謂的 Xadmin 組件就是自定義後臺。html
首先,和建立 app01 相似,建立一個名爲 Xadmin 的 APP 。並在 settings.py 文件中加入該組件的配置信息。python
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'Xadmin.apps.XadminConfig', 'app01.apps.App01Config', 'app02.apps.App02Config', ]
在 Xadmin 組件中的 app.py 文件中更改 XadminConfig 類,主要是增長一個 ready 函數,使得在項目運行時就自動執行每一個 APP 下面的 Xadmin 文件。git
# Xadmin/app.py from django.apps import AppConfig from django.utils.module_loading import autodiscover_modules # 組件Xadmin的配置類,在項目啓動時進行加載 class XadminConfig(AppConfig): name = 'Xadmin' # 加載該類時自動執行ready函數 def ready(self): # 掃描全部Xadmin的模塊,啓動完成後執行每一個APP下的Xadmin文件 autodiscover_modules('Xadmin')
注意,剛開始建立的 APP 中並無 Xadmin 文件,而是有 admin.py 文件,這是 Django 自帶的,建立一個 Xadmin.py 文件來代替 admin.py ,以後會在這個文件中進行對數據 model 的註冊。github
在 Xadmin 組件文件中建立一個 service 的包,在其中建立一個 Xadmin.py 文件,做爲 Xadmin 類的文件。如上圖目錄結構所示。django
XadminSite 類就是 Xadmin 組件的類。session
XadminSite 類須要兩個函數,一個是 init 函數用來初始化註冊過的字典,另外一個是 register 函數用來對數據 model 進行註冊。app
# Xadmin/service/Xadmin.py class XadminSite(object): def __init__(self): self._registry = {} def register(self, model, admin_class=None, **options): if not admin_class: admin_class = ModelXadmin self._registry[model] = admin_class(model, self)
ModelXadmin 類就是 Xadmin 每一個數據 model 的配置類的父類,一些自定義內容都是在該類中進行實現的。函數
該類主要傳入的是 model 類對象和 Xadmin 類的實例對象。url
# Xadmin/service/Xadmin.py class ModelXadmin(object): def __init__(self, model, site): self.model = model self.site = site
爲了在整個項目運行過程當中使用同一個 Xadmin 的實例對象,須要經過模塊方式對 XadminSite 實現單例對象。設計
關於單例對象的內容請參考:單例模式
# Xadmin/service/Xadmin.py site = XadminSite()
Xadmin 中 url 的設計思路與 admin 中的實際上是相同的,請參考Django 中 admin 的執行流程中的 url 配置。
在 urls.py 文件中,咱們像 admin 組件同樣配置 url 。
from django.conf.urls import url from django.contrib import admin from Xadmin.service.Xadmin import site urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^Xadmin/', site.urls), ]
與 admin 組件相似,經過 XadminSite 的靜態方法 urls 來配置 url 。
class XadminSite(object): def __init__(self): self._registry = {} def get_urls(self): temp = [] for model, admin_class_obj in self._registry.items(): app_name = model._meta.app_label mode_name = model._meta.model_name temp.append(url(r'^{}/{}/'.format(app_name, mode_name), admin_class_obj.urls2)) return temp @property def urls(self): return self.get_urls(), None, None def register(self, model, admin_class=None, **options): if not admin_class: admin_class = ModelXadmin self._registry[model] = admin_class(model, self)
注意,函數 urls 返回的是個元組,元組的第一個元素是個列表,該列表由函數 get_urls 返回,列表存儲的是 url 。而在 get_urls 函數返回的連接列表中是 ModelXadmin 示例對象調用的函數。這就是第二層 url 。
第二層 url 的意義在於對不一樣數據 model 作不一樣操做時是不一樣的連接。
而第二層 url 由 ModelXadmin 調用是由於在該配置類中能夠定義不一樣的需求。
class ModelXadmin(object): def __init__(self, model, site): self.model = model self.site = site def get_urls2(self): temp = [] temp.append(url(r'^$', self.list_view)) temp.append(url(r'^add/$', self.add_view)) temp.append(url(r'^(\d+)/change/$', self.change_view)) temp.append(url(r'^(\d+)/delete/$', self.delete_view)) return temp @property def urls2(self): return self.get_urls2(), None, None
GitHub 地址:https://github.com/protea-ban/oldboy/tree/master/s9day83/Xadmindemo