Django学习【第29篇】: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 )