---恢复内容开始---
1 模拟admi启动自动执行admin相关应用,这里我们将自己的文件叫做myadmin,在我们的app01应用下创建myadmin.py文件
在我们创建的myadmin应用中的app下写入固定方法,使用的是atuodiscover_moudels自动检索文件名并在启动第一时间执行该文件
from django.apps import AppConfig from django.utils.module_loading import autodiscover_modules class MyadminConfig(AppConfig): name = 'myadmin' def ready(self): return autodiscover_modules('myadmin')
2 模拟admin注册方法,写出模拟源码,在myadmin文件下创建service文件,名字我自己瞎起的一个,在该文件下创建myadmin
写入模拟django的admin数据模型表的注册源码,注册类和模型表相对应的配置类
配置类类名 class ModelMyadmin(object): #注册模型表源码 class MyadminSite(object): def __init__(self, name='admin'): self._registry = {} # model_class class -> admin_class instance def register(self, model, admin_class=None, **options): if not admin_class: admin_class = ModelMyadmin # Instantiate the admin class to save in the registry self._registry[model] = admin_class(model)
重点:在配置类中self就是我们操作的模型表,
设置路由
首先要搞清楚路由分组的本质,他是用url包裹的前面是路由的路由名称,逗号后边可以跟着的是视图函数的函数名,或者是二级的路由名称加上函数视图的函数名,在加上两个None,需要注意的是一级路由后面不管是什么内容必须用元组的形式给包裹起来。
这里的路由生成模拟admin路由生成的方式在注册的源码和模型表的配置类中生成。
在注册源码中生成模型表查看的一级路由:
def get_urls(self): urls = [] for model_class,config_obj in self._registry.items():
config_obj拿到的是模型表相对应的配置类 #我们通过注册在源码的大字典中可以通过——meta.app_label取出模型表所在应用名,和 #_meta.model_name 取出模型表名 app_label= model_class._meta.app_label model_name = model_class._meta.model_name #通过拼接后生成urls形成一级路由, urls.append( url(r'^%s/%s/'%(app_label,model_name),config_obj.urls) ) return urls @property def urls(self): return self.get_urls(),None,None
二级路由就涉及到模型表的数据操作了,这里不能在注册源码中生成了,因为模板导入使用源码后就形成了单例模式,如果在注册源码生成二级路由那么生成的所有表操作都是一样的了,
但是表的具体操作又不可能是一样的所以要在模型表相对应的配置类中去生成二级路由:
@property def urls(self): urls = [ url(r'^$',self.list_view,name='%s_%s_%s'%(self.app_label,self.model_name,'list')), url(r'^add/',self.add_view,name='%s_%s_%s'%(self.app_label,self.model_name,'add')), url(r'^update/(\d+)/',self.update_view,name='%s_%s_%s'%(self.app_label,self.model_name,'update')), url(r'^delete/(\d+)/',self.delete_view,name='%s_%s_%s'%(self.app_label,self.model_name,'delete')), ] return urls,None,None
路由生成以后就是对模型表操作设计到表的展示,和表数据的增删改查;
其中在表的展示时我们不知道用户到底要展示什么数据,所以我们在配置类设置一个默认的展示,只展示模型表中的一个个对象通过__str__方法展示对象名。在暴露用户的注册表中提供给用户可以自己定制的方法,用户自己写了就用用户的用户如果不写就是使用我们自己默认的
在配置类中默认list_play
class ModelMyadmin(object): list_play = ['__str__',]
在配置类中做判断如果用户没有对list_play设置,那么就使用默认的
def get_new_list_play(self): tmp = [] tmp.append(ModelMyadmin.check_col) tmp.extend(self.list_play) if not self.list_play_links: tmp.append(ModelMyadmin.edit_col) tmp.append(ModelMyadmin.delete_col) return tmp
展示数据内容前台使用table标签进行渲染,在后台的数据处理上就要将表单的处理分为表头展示和表单内容展示,表头想要展示用中文的话,可以现在模型表设置 如:verbose_name='书籍名,
在使用配置类._meta的方法去点出getfield()方法拿到verbose_name
表头展示:
def get_head(self): head_list = [] for field_or_func in self.config_obj.get_new_list_play(): if isinstance(field_or_func, str): if field_or_func == '__str__': head_list.append((self.config_obj.model._meta.model_name).upper()) else: val = self.config_obj.model._meta.get_field(field_or_func).verbose_name head_list.append(val) else: val = field_or_func(self.config_obj, is_head=True) head_list.append(val) return head_list
表单内容展示:
def get_body(self): # 表单展示 body_list = [] for obj in self.page_queryset: print(obj.pk) tmp = [] for field_or_func in self.config_obj.get_new_list_play(): if isinstance(field_or_func, str): val = getattr(obj, field_or_func) if field_or_func in self.config_obj.list_play_links: _url = self.config_obj.get_reverse('update', obj) val = mark_safe('<a href="%s">%s</a>' % (_url, val)) else: val = field_or_func(self.config_obj, obj=obj) tmp.append(val) body_list.append(tmp) return body_list
---恢复内容结束---