zoukankan      html  css  js  c++  java
  • 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 )
                
  • 相关阅读:
    网络经济与企业管理(第4章:企业组织管理)
    网络经济与企业管理(第3章:客户关系管理)
    软件开发工具(第3章:软件开发工具的理论基础)
    Apache Cordova开发Android应用程序——番外篇
    unittest测试框架之Mock接口联调
    unittest测试框架之分层设计思想和项目路径处理
    unittest测试框架之DDT数据驱动
    unittest测试框架之测试用例类
    unittest测试框架之测试程序运行的启动文件
    接口自动化之requests模块的简单使用
  • 原文地址:https://www.cnblogs.com/morgana/p/8493165.html
Copyright © 2011-2022 走看看