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