django-admin的源码流程
一、admin的源码流程
首先可以确定的是:路由关系一定对应一个视图函数
a、当点击运行的时候,会先找到每一个app中的admin.py文件,并执行
b、执行urls.py
admin.site是什么?
admin.site,urls 返回的是一个元组,里面的第一个元素是一个列表
django-admin的源码流程 我们自己生成的动态的访问url ====================================初级版========================= from django.shortcuts import HttpResponse from django.conf.urls import url from django.contrib import admin from app01 import views def login(request): return HttpResponse("ok") url_list = [] for model_class,v in admin.site._registry.items(): print(model_class) #打印的是每一个类<class 'app01.models.UserInfo'> cls_name = model_class._meta.model_name #当前类名称的小写 app_name = model_class._meta.app_label #当前app的名称 val = url(r'^{0}/{1}/$'.format(app_name,cls_name), login, name="login") url_list.append(val) urlpatterns = [ url(r'^admin/', admin.site.urls), # admin.site这个对象里面有一个属性_registry = {} #点击urls查看源码返回的是一个元组,元组的第一个元素是一个列表 url(r'^index/', ([ url(r'^app01/userinfo/$', login,name="login"), url(r'^app01/roles/$', login,name="login"), ],None,None)), url(r'^index2/', (url_list,None,None,)), #吧上面定义的列表拿下来,这是后就动态生成了 ]
================================升级============================ 路径http://127.0.0.1:8001/index/app01/roles/后面还有增删改查的路径 http://127.0.0.1:8001/index/app01/roles/add/ http://127.0.0.1:8001/index/app01/roles/1/change/ http://127.0.0.1:8001/index/app01/roles/1/del/ 实现流程 from django.shortcuts import HttpResponse from django.conf.urls import url from django.contrib import admin from app01 import views def login(request): return HttpResponse("ok") def change_list(request): return HttpResponse("列表页面") def add_view(request): return HttpResponse("添加页面") def change_view(request,nid): return HttpResponse("修改页面") def delete_view(request,nid): return HttpResponse("删除页面") url_list = [] for model_class,v in admin.site._registry.items(): print(model_class) #打印的是每一个类<class 'app01.models.UserInfo'> cls_name = model_class._meta.model_name #当前类名称的小写 app_name = model_class._meta.app_label #当前app的名称 urls_list = url(r'^{0}/{1}/$'.format(app_name,cls_name), change_list, name="login") url_list.append(urls_list) add_url = url(r'^{0}/{1}/add/$'.format(app_name, cls_name), add_view, name="login") url_list.append(add_url) change_url = url(r'^{0}/{1}/(\d+)/change/$'.format(app_name, cls_name), change_view, name="login") url_list.append(change_url) del_url = url(r'^{0}/{1}/(\d+)/del/$'.format(app_name, cls_name), delete_view, name="login") url_list.append(del_url) urlpatterns = [ url(r'^admin/', admin.site.urls), # admin.site这个对象里面有一个属性_registry = {} #点击urls查看源码返回的是一个元组,元组的第一个元素是一个列表 url(r'^index/', ( [ url(r'^app01/userinfo/$', login,name="login"), url(r'^app01/roles/$', login,name="login"), ],None,None)), url(r'^index2/', (url_list,None,None,)), #吧上面定义的列表拿下来,这是后就动态生成了 ] 说明了: url的本质:它读取_registry所有字典里面的数据,为字典里面的每一个类生成了4个url
==================================修改上面的版本============================= 定义了一个 def get_urls(): temp = [ url(r'^$'.format(app_name, cls_name), change_list), url(r'^add/$'.format(app_name, cls_name), add_view), url(r'^del/$'.format(app_name, cls_name), delete_view), url(r'^change/$'.format(app_name, cls_name), change_view) ] return temp url_list = [] for model_class,v in admin.site._registry.items(): print('-------',model_class) #打印的是每一个类<class 'app01.models.UserInfo'> cls_name = model_class._meta.model_name #当前类名称的小写 app_name = model_class._meta.app_label #当前app的名称 方式一: # all_urls = url(r'^{0}/{1}/'.format(app_name,cls_name), (get_urls(),None,None,)) 方式二: all_urls = url(r'^{0}/{1}/'.format(app_name,cls_name), include(get_urls()) ) url_list.append(all_urls) urlpatterns = [ url(r'^admin/', admin.site.urls), # admin.site这个对象里面有一个属性_registry = {} #点击urls查看源码返回的是一个元组,元组的第一个元素是一个列表 url(r'^index/', ( [ url(r'^app01/userinfo/', ([ url(r'^$', change_list, name="login"), url(r'^add/$', add_view, name="login"), url(r'^(\d+)/del/$', delete_view, name="login"), url(r'^(\d+)/change/$', change_view, name="login"), ],None,None),name="login"), url(r'^app01/usertype/', ([ url(r'^$', change_list, name="login"), url(r'^add/$', add_view, name="login"), url(r'^(\d+)/del/$', delete_view, name="login"), url(r'^(\d+)/change/$', change_view, name="login"), ], None, None), name="login"),],None,None)), url(r'^app02/article/', ([ url(r'^$', change_list, name="login"), url(r'^add/$', add_view, name="login"), url(r'^(\d+)/del/$', delete_view, name="login"), url(r'^(\d+)/change/$', change_view, name="login"), ],None,None),name="login"), # index和index2的两个是一样的,我们可以用index2的方式替代index url(r'^index2/', (url_list,None,None,)), #吧上面定义的列表拿下来,这是后就动态生成了 ] include的本质就是:返回了一个元组,元组的第一个是这个模块 include里面 既可以写一个列表include([]),利用include做分发 也可以返回一个字符串:帮我们去找到这个模块,找到所有的映射关系 include(model_admin.urls) model_admin是什么?ModelAdmin对象的urls
总结
- admin源码流程 a. 运行程序,找到每一个app中的 admin.py 文件,并加载 - app01.admin.py - 创建admin.site中的对象 - 执行对象的 register方法,目的:将注册类添加到 _registry中 _registry = { key是传进来的model value:是ModelAdmin的对象,传了两个参数 models.Role: ModelAdmin(models.Role,admin.site), models.UserInfo: ModelAdmin(models.UserInfo,admin.site) models.UserType: ModelAdmin(models.UserType,admin.site) } - app02.admin.py - 用app01.admin中创建那个admin.site对象 - 执行对象的 register方法,目的:讲注册类添加到 _registry中 _registry = { models.Role: ModelAdmin(models.Role,admin.site), models.UserInfo: ModelAdmin(models.UserInfo,admin.site) models.UserType: ModelAdmin(models.UserType,admin.site) models.Article: ModelAdmin(models.Article,admin.site) } admin.site是一个对象(单例模式创建),其中封装了: _registry = { models.Role: ModelAdmin(models.Role,admin.site), models.UserInfo: ModelAdmin(models.UserInfo,admin.site) models.UserType: ModelAdmin(models.UserType,admin.site) models.Article: ModelAdmin(models.Article,admin.site) } b. urls.py 再次调用 admin.site 对象的 urls属性: urlpatterns = [ url(r'^admin/', admin.site.urls), ] class ModelAdmin(object): def __init__(self,model_class,site): self.model_class = model_class self.site = site def changelist_view(self,request): data_list = self.model_class.objects.all() #是动态的 return HttpResponse('列表页面') def add_view(self,request): return HttpResponse('添加页面') def delete_view(self,request,nid): return HttpResponse('删除页面') def change_view(self,request,nid): return HttpResponse('修改页面') def get_urls(self): urlpatterns = [ url(r'^$', self.changelist_view), url(r'^add/$', self.add_view), url(r'^(.+)/delete/$', self.delete_view), url(r'^(.+)/change/$', self.change_view), ] return urlpatterns @property def urls(self): return self.get_urls() class AdminSite(object): def __init__(self): self._registry = {} def register(self,model_class,model_admin): self._registry[model_class] = model_admin(model_class,self) def get_urls(self): """ models.Role: ModelAdmin(models.Role,admin.site), models.UserInfo: ModelAdmin(models.UserInfo,admin.site) models.UserType: ModelAdmin(models.UserType,admin.site) models.Article: ModelAdmin(models.Article,admin.site) """ url_list = [] for model_class,model_admin in self._registry.items(): model_class是一个类 app_name = model_class._meta.app_label model_name = model_class._meta.model_name url_list += [ url('%s/%s' %(app_name,model_name,), include(model_admin.urls)) ] return url_list @property def urls(self): return (self.get_urls(), None,None )