自定义admin同django_admin,三步走
一,启动
django启动加载settings.py中的 INSTALLED_APPS 下注册的每一个app,在django_admin中为了让django加载每一个app中的admin.py文件,调用了
autodiscover_modules('admin', register_to=site)
该方法循环加载了每一个app中的admin.py中我们注册的模型表类和配置类;
那么我们仿照django_admin实现一下:
先创建一个stark的app,然后在 INSTALLED_APPS 中注册,这里需要调用一个方法:
在注册的stark下的apps.py中,添加ready方法,在注册完stark后就能自动执行该方法下的代码,在该方法去调用 autodiscover_modules('stark', register_to=site),
from django.apps import AppConfig from django.utils.module_loading import autodiscover_modules from stark.service.sites import site class StarkConfig(AppConfig): name = 'stark' def ready(self): autodiscover_modules('stark', register_to=site)
ok,启动完毕!
二,注册
直接仿照django_admin,现在自己的组件stark文件夹下,新建一个sites.py,(当然这个sites.py放在那个目录都可以,而且名字也无所谓叫什么),这里我们的文件结构如下:
在sites.py中创建我们的stark组件的全局类AdminSite(类比django_admin中的AdminSite()),以及我们的默认配置类ModelStark(类比django_admin中的ModelAdmin),还有单例对象
class ModelStark(object): """ 默认的配置类 """ list_display = [] def __init__(self, model, admin_class): self.model = model # 这一步完成了把模型表赋值在self中,即self.model # self.admin_class = admin_class
class AdminSite(object): """ stark组件的全局类 """ def __init__(self): self._registry = {} # 设置 那个存储不同app注册的模型表 def register(self, model, admin_class=None): # 配置默认的样式类,为我们自己的ModelStark类 if not admin_class: admin_class = ModelStark self._registry[model] = admin_class(model, self) # 仿照admin,把所有的注册了的 模型表和配置类组成的键值对 添加到自己全局类的那个字典中
# 单例模式, 每一个app下的stark.py中注册时都是同一个site对象,调用的同一个_registry那个字典,往里面添加键值对 site = AdminSite()
然后和注册django_admin一样需要在我们的每个app下的stark.py中注册:
from app01 import models from stark.service.sites import site, ModelStark class BookConfig(ModelStark): # 自定义配置类 list_display = ["title", "price"] site.register(models.Book, BookConfig) site.register(models.Publish) # 没有传入自定义配置类,使用默认的配置类ModelStark site.register(models.Author) # 没有传入自定义配置类,使用默认的配置类ModelStark site.register(models.AuthorDetail) # 没有传入自定义配置类,使用默认的配置类ModelStark
注册完毕!
三,URL配置
仿照django的url分发,自定义url分发:
from django.conf.urls import url from django.contrib import admin from stark.service.sites import site # 导入我们的那个单例对象 urlpatterns = [ url(r'^admin/', admin.site.urls), # 自定义的stark组件(类似django_admin) url(r'^stark/', site.urls), 调用全局类中的静态方法urls ]
所以我们的全局类要这么写:
class AdminSite(object): """ stark组件的全局类 """ def __init__(self): self._registry = {} # 设置 那个存储不同app注册的模型表 def register(self, model, admin_class=None): # 配置默认的样式类,为我们自己的ModelStark类 if not admin_class: admin_class = ModelStark self._registry[model] = admin_class(model, self) def get_urls(self): temp = [] for model, config_obj in self._registry.items(): model_name = model._meta.model_name # 拿到模型表名 app_name = model._meta.app_label # 拿到app名称 temp.append(url(r"^{}/{}/".format(app_name, model_name), config_obj.urls)) # 这里注意,是使用的config_obj.urls,config_obj就是我们的配置类,把二级分发路由写到配置类中, # 把对应的视图函数也写在配置类中,这样我们在调用试图函数时,self就是我们的配置类(config_obj), # 而且,每一次循环就是其对应的表的配置类, # 而self.model就是我们在实例化配置类的时候添加进去的,也就是我们对应的模型表类 return temp @property def urls(self): # 上面url就是调用的这个静态方法 return self.get_urls(), None, None # 路由分发必须返回三个参数: [], None, None
二级路由是放在配置类中的,由配置类调用配置类中的urls静态方法,同时把我们的视图函数先写在配置类中,所以我们的配置类要这么写
from django.conf.urls import url from django.shortcuts import HttpResponse, redirect, render # 仿照django_admin自定义一个类似的组件 class ModelStark(object): """ 默认的配置类 """ list_display = [] def __init__(self, model, admin_class): self.model = model # 这一步完成了把模型表赋值在self中,即self.model # self.admin_class = admin_class def view_list(self, request): # print(self) # self就是配置类本身 # print(self.model) # self.model就是模型表 all_data = self.model.objects.all() # print(self.list_display) return render(request, "view_list.html", {"all_data": all_data}) def add(self, request): return HttpResponse("add") def delete(self, request, pk): return HttpResponse("delete") def change(self, request, pk): return HttpResponse("change") def get_urls(self): temp = [ url(r"^$", self.view_list), url(r"^add/$", self.add), url(r"^(\d+)/change/$", self.change), url(r"^(\d+)/delete/$", self.delete), ] return temp @property def urls(self): # 配置类调用就是这个urls方法 return self.get_urls(), None, None
#!/usr/bin/env python # -*- coding:utf8 -*- from django.conf.urls import url from django.shortcuts import HttpResponse, redirect, render # 仿照django_admin自定义一个类似的组件 class ModelStark(object): """ 默认的配置类 """ list_display = [] def __init__(self, model, admin_class): self.model = model # 这一步完成了把模型表赋值在self中,即self.model # self.admin_class = admin_class def view_list(self, request): # print(self) # self就是配置类本身 # print(self.model) # self.model就是模型表 all_data = self.model.objects.all() # print(self.list_display) return render(request, "view_list.html", {"all_data": all_data}) def add(self, request): return HttpResponse("add") def delete(self, request, pk): return HttpResponse("delete") def change(self, request, pk): return HttpResponse("change") def get_urls(self): temp = [ url(r"^$", self.view_list), url(r"^add/$", self.add), url(r"^(\d+)/change/$", self.change), url(r"^(\d+)/delete/$", self.delete), ] return temp @property def urls(self): return self.get_urls(), None, None class AdminSite(object): """ stark组件的全局类 """ def __init__(self): self._registry = {} # 设置 那个存储不同app注册的模型表 def register(self, model, admin_class=None): # 配置默认的样式类,为我们自己的ModelStark类 if not admin_class: admin_class = ModelStark self._registry[model] = admin_class(model, self) def get_urls(self): temp = [] for model, config_obj in self._registry.items(): model_name = model._meta.model_name # 拿到模型表名 app_name = model._meta.app_label # 拿到app名称 temp.append(url(r"^{}/{}/".format(app_name, model_name), config_obj.urls)) # 这里注意,是使用的config_obj.urls,config_obj就是我们的配置类,把二级分发路由写到配置类中, # 把对应的视图函数也写在配置类中,这样我们在调用试图函数时,self就是我们的配置类(config_obj), # 而且,每一次循环就是其对应的表的配置类, # 而self.model就是我们在实例化配置类的时候添加进去的,也就是我们对应的模型表类 return temp @property def urls(self): return self.get_urls(), None, None # 路由分发必须返回三个参数: [], None, None # 单例模式, 每一个app下的stark.py中注册时都是同一个site对象,调用的同一个_registry那个字典,往里面添加键值对 site = AdminSite()
这样访问以下的url,就能返回我们想要的结果了:
/stark/app01/book/add/ # 增 /stark/app01/book/1/delete/ # 删 /stark/app01/book/1/change/ # 改 /stark/app01/book/ # 查 /stark/app01/publish/add/ # 增 /stark/app01/publish/1/delete/ # 删 /stark/app01/publish/1/change/ # 改 /stark/app01/publish/ # 查 ........等等所有我们注册的表