自定义Xadmin
自定义Xadmin
1.启动Xadmin
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', ]
执行流程:
1.在启动Django后,按app顺序进行加载。先加载 'django.contrib.admin',Django自身生成admi.site单例对象,生成user和group两张表
加载到'Xadmin.apps.XadminConfig',执行Xadmin中apps文件中的XadminConfig
apps中的代码:
from django.apps import AppConfig
class XadminConfig(AppConfig):
name = 'Xadmin'
2.XadminConfig中有个raedy方法,会自动执行,Django默认去读取自身和其他app的admin文件,如在相应的app的admin文件中输入
print("xadmin") print("app01")print("app02")进行测试
启动django后,就会根据加载顺序打印出结果:
xadmin
app01
app02
3.在执行第一个app的admin文件时,
from django.contrib import admin 会执行admin,打开admin源码分析:
admin源码:
from django.utils.module_loading import autodiscover_modules
def autodiscover():
autodiscover_modules('admin', register_to=site) #启动admin
4.打开site site = AdminSite() 因此在执行admin文件时就生成了app应用的单例对象admin.site,在扫描其他app的admin文件时
由于from django.contrib import admin已经加载过,因此直接拿到第一个app生成的单例对象
2.配置Xadmin下的apps文件
我们可以自己设置函数
如:在类中添加
def ready(self):
print("ok") 在启动django,加载到Xadmin的app文件时,自动执行ready函数,打印出"ok"
Django加载时默认读取其他app的admin文件,因此要设置在执行这个文件时,去读取其他app的Xadmin文件.根据admin文件去写
from django.apps import AppConfig
from django.utils.module_loading import autodiscover_modules
class XadminConfig(AppConfig):
name = 'Xadmin'
def ready(self):
autodiscover_modules('Xadmin')
#在加载app文件时时读取自身和其他app的xadmin文件。由于是自定义admin,目的是让其他app执行自定义的admin,因此删除掉Xadmin下的admin
测试:在app01和app02分别新建Xadmin文件,输入print("Xadmin app01")和print("Xadmin app01")打印后:
admin app01 #在admin文件中的测试
admin app02
Xadmin app01
Xadmin app02
原因:'django.contrib.admin',会先执行,因此先加载app中的admin文件,将自带的admin关掉就可以了
Xadmin app01
Xadmin app02
3.配置Xadmin的注册,新建个文件夹放Xadmin.py文件,代码仿着admin.py文件写
#根据ModelAdmin源码写 class Modelxadmin(object): def __init__(self,model,site): self.model=model self.site=site class XadminSite(object): def __init__(self, name='admin'): self._registry = {} def register(self, model, admin_class=None, **options): if not admin_class: admin_class = Modelxadmin #根据AdminSite源码,定义admin_class类 self._registry[model] = admin_class(model, self) site=XadminSite() #生成单例对象
4.在app中的xadmin文件中引入Xadmin,进行注册模型表
app01 Xadmin.py from Xadmin.service.Xadmin import site from app01 import models site.register(models.Book) site.register(models.Publish) site.register(models.Author) site.register(models.AuthorDetail) app02 Xadmin.py from Xadmin.service.Xadmin import site from app02 import models site.register(models.Order) print(site._registry) #结果有五个表
5.设计路由:
参考admin的路由设计
urlpatterns = [
url(r'^admin/', admin.site.urls), admin.site是Adminsite类的对象,urls是 AdminSite类中的一个方法
]
查看AdminSite源码:找到urls方法,分析其流程。执行urls方法后,执行get_urls方法,在get_urls设置路由
admin的路由源码:
@property def urls(self): return self.get_urls(), 'admin', self.name #结果是个元祖即等同于url(r'^admin/',(get_urls(),None,None)) def get_urls(self): from django.conf.urls import url, include def wrap(view, cacheable=False): def wrapper(*args, **kwargs): return self.admin_view(view, cacheable)(*args, **kwargs) wrapper.admin_site = self return update_wrapper(wrapper, view) # Admin-site-wide views. urlpatterns = [ url(r'^$', wrap(self.index), name='index'), url(r'^login/$', self.login, name='login'), url(r'^logout/$', wrap(self.logout), name='logout'), url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'), url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True), name='password_change_done'), url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'), url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', wrap(contenttype_views.shortcut), name='view_on_site'),
设置Xadmin路由:
1.from Xadmin.service.Xadmin import site
urlpatterns = [
#根据admin路由设置方式设置Xadmin路由
url(r'^Xadmin/', site.urls),
]
2.在Xadmin中设置urls方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class XadminSite(object): def __init__(self, name='admin'): self._registry = {} def register(self, model, admin_class=None, **options): if not admin_class: admin_class = Modelxadmin #根据AdminSite源码,定义夜歌admin_class类 self._registry[model] = admin_class(model, self) def list_view(self,request): return HttpResponse("这是查看的网页") def add_view(self,request): return HttpResponse("这是添加的网页") def change_view(self,request, id): return HttpResponse("这是编辑的网页") def del_view(self,request, id): return HttpResponse("这是删除的网页") def get_url_2(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+)/del/$", self.del_view)) return temp @property def urls2(self): return self.get_url_2(), None, None def get_urls(self): temp = [] print(self._registry) for model, admin_class in self._registry.items(): app_name = model._meta.app_label # 拿到app的名字 model_name = model._meta.model_name # 拿到字符串类型的表名 temp.append(url(r"^{}/{}/".format(app_name, model_name), self.urls2)) return temp @property def urls(self): #self就是XadminSite单例出来的对象 return self.get_urls(), None, None
6.获取数据:
将二级路由放到XadminSite类之后,即创建的book,publish等模型表在Xadmin中所有的配置都一样。
同时在进行相应的表的数据查询时,比较困难 为了不同的模型表显示不同的效果,将二级路由放到Modelxadmin中
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)