程序启动时查找所有注册了的apps.py 会执行def ready方法
MyAdmin.apps.py:
def ready(self):
super(MyadminConfig,self).ready()
from django.utils.module_loading import autodiscover_modules
autodiscover_modules('reg')
这里应该是收集所有的reg文件。执行reg.py中的注册函数
app01.reg.py:
from app01 import models
from MyAdmin.service import v1
#执行v1.site.register方法,将model_class传入
v1.site.register(models.UserInfo)
v1.site.register(models.Role)
MyAdmin.service.v1.py:
#site为MySite对象
site = MySite()
#通过执行并传入model的register函数,生成一个字典并保存:
ret={
"UserInfo":BaseAdmin(UserInfo,site)
"Role":BaseAdmin(Role,site)
}
def register(self,model_class,xxx = BaseAdmin):
self._registry[model_class] = xxx(model_class,self)
Django.urls.py:
from django.conf.urls import url
from MyAdmin.service import v1
urlpatterns = [
url(r'^md/', v1.site.urls),
]
当Django启动后,这里使用路由分发的原理 v1.site.urls 分发了预设的url以及
根据app名称跟类名拼接生成的url,在此基础上再次分发,使每个类都有
4个url:changelist、add、delete、change
MyAdmin.service.v1.py class
@property 1. def urls(self): return self.get_urls(),self.app_name,self.namespace 2. def get_urls(self): from django.conf.urls import url,include ret = [ url(r'^login/',self.login,name='login'), url(r'^logout/',self.login,name='logout'), ] """ model_cls为models类,admin_obj为BaseAdmin(model类, MySite()即site ),即传入2个参数的BaseAdmin对象, admin_obj.urls则执行BaseAdmin的urls方法 """ for model_cls,admin_obj in self._registry.items(): app_label = model_cls._meta.app_label model_name = model_cls._meta.model_name ret.append(url(r'^%s/%s' % (app_label,model_name),include(admin_obj.urls))) return ret 3.@property def urls(self): from django.conf.urls import url,include info = self.model_class._meta.app_label,self.model_class._meta.model_name """
这里的self.model_class为之前传入的model类,所以一样可以取得app和model类名,由此设置别名,
方便后续反向生成url.
"""
urlpatterns = [
url(r'^$',self.changelist_view,name='%s_%s_changelist' % info),
url(r'^add/$',self.add_view,name='%s_%s_add' % info),
url(r'^(.+)/delete/$',self.delete_view,name='%s_%s_delete' % info),
url(r'^(.+)/change/$',self.change_view,name='%s_%s_change' % info),
]
return urlpatterns
生成url后,我们需要对每个url指定不同的操作,以changelist为例子,每个类定义的字段,以及字段名都不同,我们又不可能为每一个类的url做单独的模版,假如有几十个类,这样增删改查工作量太大,因此我们需要为每个类的增删改查做统一的视图模版.
阶段一代码:
1.目录结构:
2.代码:
1 from django.http import HttpResponse 2 from django.shortcuts import render 3 4 class BaseAdmin(object): 5 list_display = "__all__" 6 7 def __init__(self,model_class,site): 8 self.model_class = model_class 9 self.site = site 10 self.request = None 11 12 @property 13 def urls(self): 14 from django.conf.urls import url 15 """ 16 这里的self.model_class为之前传入的model类,所以一样可以取得app和model类名,由此设置别名, 17 方便后续反向生成url. 18 """ 19 info = self.model_class._meta.app_label,self.model_class._meta.model_name 20 urlpatterns = [ 21 url(r'^$',self.changelist_view,name='%s_%s_changelist' % info), 22 url(r'^add/$',self.add_view,name='%s_%s_add' % info), 23 url(r'^(.+)/delete/$',self.delete_view,name='%s_%s_delete' % info), 24 url(r'^(.+)/change/$',self.change_view,name='%s_%s_change' % info), 25 ] 26 return urlpatterns 27 28 def add_view(self,request): 29 """ 30 新增数据 31 :param request: 32 :return: 33 """ 34 info = self.model_class._meta.app_label,self.model_class._meta.model_name 35 data = "%s_%s_add" % info 36 return HttpResponse(data) 37 38 def delete_view(self,request,pk): 39 """ 40 删除数据 41 :param request: 42 :return: 43 """ 44 # self.model_class.objects.filter(id=pk).delete() 45 info = self.model_class._meta.app_label, self.model_class._meta.model_name 46 data = "%s_%s_del" % info 47 return HttpResponse(data) 48 49 def change_view(self,request,pk): 50 """ 51 修改数据 52 :param request: 53 :return: 54 """ 55 info = self.model_class._meta.app_label, self.model_class._meta.model_name 56 data = "%s_%s_change" % info 57 return HttpResponse(data) 58 59 def changelist_view(self,request): 60 """ 61 查看列表 62 :param request: 63 :return: 64 """ 65 self.request = request 66 result_list = self.model_class.objects.all() 67 context = { 68 'result_list':result_list, 69 'list_display':self.list_display, 70 'admin_obj':self #此处self为自定制的Admin-models类对象 71 } 72 return render(request,'md/change_list.html',context) 73 74 75 class MySite(object): 76 def __init__(self): 77 self._registry = {} 78 self.namespace = 'MyAdmin' 79 self.app_name = 'MyAdmin' 80 81 def register(self,model_class,xxx = BaseAdmin): 82 self._registry[model_class] = xxx(model_class,self) 83 """{ 84 modle类:BaseAdmin(model类, MySite()即site ) 85 } 86 """ 87 88 def get_urls(self): 89 from django.conf.urls import url,include 90 ret = [ 91 url(r'^login/',self.login,name='login'), 92 url(r'^logout/',self.login,name='logout'), 93 ] 94 #通过循环items获得每一个model类所在的app名,以及小写的类名 95 for model_cls,admin_obj in self._registry.items(): 96 """ 97 model_cls为models类,admin_obj为BaseAdmin(model类, MySite()即site ),即传入2个参数的BaseAdmin对象, 98 admin_obj.urls则执行BaseAdmin的urls方法 99 """ 100 app_label = model_cls._meta.app_label 101 model_name = model_cls._meta.model_name 102 # print(app_label,model_name) 103 #拼接生成url,如/md/app01/userinfo/,再次分发拿到最终的/md/app01/userinfo/change_list等url 104 ret.append(url(r'^%s/%s' % (app_label,model_name),include(admin_obj.urls))) 105 106 return ret 107 108 @property 109 def urls(self): 110 return self.get_urls(),self.app_name,self.namespace 111 112 def login(self,request): 113 return HttpResponse('login') 114 115 site = MySite()