• python 全栈开发,Day112(内容回顾,单例模式,路由系统,stark组件)


    一、内容回顾

    类可否作为字典的key

    初级

    举例:

    class Foo(object):
        pass
    
    _registry = {
        Foo:123
    }
    
    print(_registry)
    View Code

    执行输出:

    {<class '__main__.Foo'>: 123}

    说明说法是成立的。

    中级

    class User(object):
        pass
    
    class Role(object):
        pass
    
    class Bar(object):
        def __init__(self,b):
            self.b = b
    
    _registry = {
        User:Bar(User),
        Role:Bar(Role),
    }
    
    print(_registry)
    View Code

    执行输出:

    {<class '__main__.Role'>: <__main__.Bar object at 0x00000158F1BFC668>, <class '__main__.User'>: <__main__.Bar object at 0x00000158F1B39320>}

    高级

    class User(object):
        pass
    
    class Role(object):
        pass
    
    class Bar(object):
        def __init__(self,b):
            self.b = b
    
    _registry = {
        User:Bar(User),
        Role:Bar(Role),
    }
    
    
    for k,v in _registry.items():
        print(k, v.b)
    View Code

    执行输出:

    <class '__main__.Role'> <class '__main__.Role'>
    <class '__main__.User'> <class '__main__.User'>

    从结果上来看,k和v.b 结果是一样的!请记住这个例子,下面的内容会用到!

    通过model获取app名和类名

    创建一个项目untitled,注意:django版本为1.11

    进入命令行,创建第二个应用

    python manage.py startapp app02

    修改settings.py,注册2个app

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app01.apps.App01Config',
        'app02.apps.App02Config',
    ]
    View Code

    修改 app01-->models.py,新建表名为UserInfo

    from django.db import models
    
    # Create your models here.
    class UserInfo(models.Model):
        username = models.CharField(verbose_name="用户名",max_length=32)
    View Code

    修改 app02->models.py,新建表名为Role

    from django.db import models
    
    # Create your models here.
    class Role(models.Model):
        title = models.CharField(verbose_name="名称", max_length=32)
    View Code

    使用2个命令,生成表

    python manage.py makemigrations
    python manage.py migrate

    修改urls.py,添加路由和视图

    from django.conf.urls import url
    from django.contrib import admin
    
    ###视图暂时写在这里
    from django.shortcuts import HttpResponse
    from app01 import models as m1
    from app02 import models as m2
    def index(request):
        print(m1.UserInfo)
        print(m2.Role)
        return HttpResponse('ok')
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/', index),
    ]
    View Code

    启动django项目,访问页面:

    查看Pycharm控制台输出:

    <class 'app01.models.UserInfo'>
    <class 'app02.models.Role'>

    获取app名和类名

    修改urls.py

    from django.conf.urls import url
    from django.contrib import admin
    
    ###视图暂时写在这里
    from django.shortcuts import HttpResponse
    from app01 import models as m1
    from app02 import models as m2
    def index(request):
        print(m1.UserInfo,m1.UserInfo._meta.app_label,m1.UserInfo._meta.model_name)
        print(m2.Role,m1.UserInfo._meta.app_label,m1.UserInfo._meta.model_name)
        return HttpResponse('ok')
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/', index),
    ]
    View Code

    刷新页面,查看Pycharm控制台输出:

    <class 'app01.models.UserInfo'> app01 userinfo
    <class 'app02.models.Role'> app01 userinfo

    可以发现,app名和表名,都出来了!

    二、单例模式

    举例1

    新建文件a.py

    class AdminSite(object):
        pass
    
    obj1 = AdminSite()
    obj2 = AdminSite()
    
    # id表示查看对象的内存地址
    print(obj1,id(obj1))
    print(obj2,id(obj2))
    View Code

    执行输出:

    <__main__.AdminSite object at 0x000001A3175549E8> 1799982762472
    <__main__.AdminSite object at 0x000001A3175549B0> 1799982762416

    可以看出内存地址不一样,它不是单例模式!

    举例2

    修改a.py

    class AdminSite(object):
        pass
    
    obj1 = AdminSite()
    obj2 = AdminSite()
    View Code

    创建c.py

    import a
    
    print(a.obj1,id(a.obj1))
    View Code

    创建b.py

    import a
    
    print(a.obj1,id(a.obj1))
    
    import c
    View Code

    导入模块关系如下:

    c导入了a,b导入了a,同时也导入到c。

    那么a会重复导入吗?

    执行b.py,输出:

    <a.AdminSite object at 0x0000024FA2354E80> 2541047074432
    <a.AdminSite object at 0x0000024FA2354E80> 2541047074432

    内存地址一致,说明a没有重复导入,这个就是一个最简单的单例模式!

    那么以后使用单例模式时,先声明一个类,再实例化。其它模块导入使用时,直接引用变量。

    这样,就可以形成一个单例模式,节省内存!

    举例3

    修改a.py

    class AdminSite(object):
        def __init__(self):
            self._registry = {}
    
    obj1 = AdminSite()
    View Code

    修改b.py

    import a
    
    a.obj1._registry['k1'] = 11
    
    import c
    
    print(a.obj1._registry)
    View Code

    修改c.py

    import a
    
    a.obj1._registry['k2'] = 22
    View Code

    执行b.py,输出:

    {'k2': 22, 'k1': 11}

    其它调用者,就可以操作同一个字典。如果key重名,那么后执行,覆盖前端的!

    三、路由系统

    include

    修改untitled项目的urls.py,增加路由

    from django.conf.urls import url,include
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^rbac/', include('app01.urls')),
    ]
    View Code

    在app01目录下创建文件urls.py

    from django.conf.urls import url,include
    from app01 import views
    
    urlpatterns = [
        url(r'^login/', views.login),
        url(r'^logout/', views.logout),
    ]
    View Code

    修改app01-->views.py

    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    def login(request):
        return HttpResponse('login')
    
    def logout(request):
        return HttpResponse('logout')
    View Code

    访问登录页面:http://127.0.0.1:8000/rbac/login/

    路由就相当于

    url(r'^/rbac/login/', views.login),

    再分发一层

    修改app01-->urls.py

    from django.conf.urls import url,include
    from app01 import views
    
    urlpatterns = [
        url(r'^login/', views.login),
        url(r'^logout/', include('app01.urls2')),
    ]
    View Code

    修改app01-->urls2.py

    from django.conf.urls import url,include
    from app01 import views
    
    urlpatterns = [
        url(r'^x1/', views.x1),
        url(r'^x2/', views.x2),
    ]
    View Code

    修改app01-->views.py

    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    def login(request):
        return HttpResponse('login')
    
    def logout(request):
        return HttpResponse('logout')
    
    def x1(request):
        return HttpResponse('x1')
    
    def x2(request):
        return HttpResponse('x2')
    View Code

    访问url:http://127.0.0.1:8000/rbac/logout/x1/

    那么路由就相当于这样

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^/rbac/login/', views.login),
        url(r'^/rbac/logout/x1/', views.login),
        url(r'^/rbac/logout/x2/', views.login),
    ]

    name

    name是为了做url反向解析的

    修改app01-->urls.py

    from django.conf.urls import url,include
    from app01 import views
    
    urlpatterns = [
        url(r'^login/', views.login, name='login'),
        url(r'^logout/', include('app01.urls2')),
    ]
    View Code

    修改app01-->urls2.py

    from django.conf.urls import url,include
    from app01 import views
    
    urlpatterns = [
        url(r'^x1/', views.x1, name='x1'),
        url(r'^x2/', views.x2, name='x2'),
    ]
    View Code

    namespace

    namespace是为防止url重名

    修改 untitled-->urls.py,这个是总路由

    from django.conf.urls import url,include
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^rbac/', include('app01.urls',namespace='rbac')),
    ]
    View Code

    修改app01-->urls.py

    from django.conf.urls import url,include
    from app01 import views
    
    urlpatterns = [
        url(r'^login/', views.login, name='login'),
        url(r'^logout/', include('app01.urls2',namespace='logout')),
    ]
    View Code

    那么urls2.py里面的路由,使用反向解析时,就相当于

    rbac:logout:x1
    rbac:logout:x2

    总结:

    include可以随意分层,namespace反向解析时,必须带上命名空间。

    假设django没有提供include,怎么办?

    看include源码,它返回了3个值

    return (urlconf_module, app_name, namespace)

    注意:return返回多个值时,它是一个元组!

    修改urls.py,修改rbac,它必须返回3个值。最后面的rbac是命名空间

    url(r'^/rbac/', (None,None,'rbac')),

    再修改,完整代码如下:

    第一个值是最重要的,另外2个参数为None也无所谓

    from django.conf.urls import url,include
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^rbac/', ([
            url(r'^login/', views.login, name='login'),
            url(r'^logout/', views.logout, name='logout'),
        ],None,'rbac')),
    ]
    View Code

    重启django程序,访问页面:http://127.0.0.1:8000/rbac/login/

    再分发一次,修改urls.py,要指定3个值

    url(r'^rbac/', ([
        url(r'^login/', views.login, name='login'),
        url(r'^logout/', views.logout, name='logout'),
        url(r'^x1/', (None,None,None)),
    ],None,'rbac')),

    进阶修改

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^rbac/', ([
            url(r'^login/', views.login, name='login'),
            url(r'^logout/', views.logout, name='logout'),
            url(r'^x1/', ([
                        url(r'^add/', views.add, name='add'),
                        url(r'^change/', views.change, name='change'),
                          ],None,None)),
        ],None,'rbac')),
    ]
    View Code

    修改 app01-->views.py

    from django.shortcuts import render,HttpResponse
    from django.urls import reverse
    
    # Create your views here.
    def login(request):
        url1 = reverse('rbac:add')
        print(url1)
        return HttpResponse('login')
    
    def logout(request):
        return HttpResponse('logout')
    
    def x1(request):
        return HttpResponse('x1')
    
    def x2(request):
        return HttpResponse('x2')
    
    def add(request):
        return HttpResponse('add')
    
    def change(request):
        return HttpResponse('change')
    View Code

    重启django程序,访问页面:http://127.0.0.1:8000/rbac/login/

    查看Pycharm控制台输出:

    /rbac/x1/add/

    可以看到,能反向解析出url

    修改urls.py,更改命名空间为xxx

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^rbac/', ([
            url(r'^login/', views.login, name='login'),
            url(r'^logout/', views.logout, name='logout'),
            url(r'^x1/', ([
                        url(r'^add/', views.add, name='add'),
                        url(r'^change/', views.change, name='change'),
                          ],None,'xxx')),
        ],None,'rbac')),
    ]
    View Code

    修改 app01-->views.py,指定命名空间

    重启django程序,访问页面:http://127.0.0.1:8000/rbac/login/

    查看Pycharm控制台输出,效果同上

    有些项目录音没有写在urls.py里面,那么在其它地方,肯定有操作urlpatterns变量的!

    查看admin路由

    创建超级用户

    python manage.py createsuperuser

    修改 app01-->admin.py,注册表

    from django.contrib import admin
    from app01 import models
    # Register your models here.
    admin.site.register(models.UserInfo)
    View Code

    登录admin后台,点击表userinfo

    查看的url为:

    http://127.0.0.1:8000/admin/app01/userinfo/

    点击添加,url为

    http://127.0.0.1:8000/admin/app01/userinfo/add/

    点击修改,url为

    http://127.0.0.1:8000/admin/app01/userinfo/1/change/

    点击删除,url为

    http://127.0.0.1:8000/admin/app01/userinfo/1/delete/

    注意:这些URL是自动添加的,执行这一行代码,就添加了4个URL

    admin.site.register(models.UserInfo)

    它是在路由加载之前操作的!

    每一个应用,都有admin.py。它一定是在路由加载之前,就添加了路由!
    否则上述几个页面是无法访问的。

    那么它是如何做的呢?查看admin模块源码

    def autodiscover():
        autodiscover_modules('admin', register_to=site)

    它调用了autodiscover方法,它是用来做自动发现的。用来动态添加路由!

    上面的'admin'指的是admin模块。它会自动寻找每一个应用名下的admin.py文件,并加载!

    四、stark组件

    stark组件介绍

    stark组件是根据Django admin为原型写的一个组件,能够让我们告别增删改查.stark组件是可插拔试的组件,

    移植性强,而且只用配置文件就能够得到想要的数据。

    注意:这个不是django的组件。是自己根据admin为原型开发的!并没有统一的标准。

    stark名字的由来

    stark来源于《冰与火之歌》里面的史塔克。

    史塔克家族是北境最古老也是最重要的家族,是北境各大小封臣的总领主,在被伊耿一世征服之前曾是独立数千年的北境之王。

    名字叫啥都可以,看你的爱好了!貌似大家都会叫stark组件。

    为什么要用stark组件

    虽然django 提供的admin后台,能快速对一个表做增加改查。但是在生成环境中,是不会用admin后台的。

    因为admin只是提供了简单的功能,在企业复杂环境中,需要自己定制功能。那么开发一套适合企业环境的stark组件,尤为重要!比如项目设计到几十张表的时候!

    初始工作

    创建应用stark并注册

    在untitled项目的基础上,创建一个应用stark

    这个应用,是专门做增删改查的!

    python manage.py startapp stark

    修改settings.py,注册app

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app01.apps.App01Config',
        'app02.apps.App02Config',
        'stark.apps.StarkConfig',
    ]
    View Code

    修改 stark-->apps.py

    from django.apps import AppConfig
    
    
    class StarkConfig(AppConfig):
        name = 'stark'
        
        def ready(self):
            # 导入自动发现模块
            from django.utils.module_loading import autodiscover_modules
            # 查找每一个应用下的stark模块,也就是stark.py
            autodiscover_modules('stark')
    View Code

    注意:这里导入了自动发现模块,并指定模块为stark。那么它会读取settings.py里面注册的每一个应用。并查找应用下的stark.py文件是否存在。存在就加载,否则不加载!

    在app01和app02目录下,分别创建stark.py

    修改 app01-->stark.py,内容如下:

    print(666)

    重启django项目,查看Pycharm控制台输出:

    666
    666

    它会执行2次,至于为什么会执行2次。这个就不知道了!

    启动步骤

    1. 读取配置文件,找到stark组件

    2. 在路由匹配之前,会查找所有app名下的stark.py文件

    3. 执行stark.py,在路由里面添加数据

    注意:如果要应用stark组件,其他应用比如创建stark.py。并做相关配置,就可以使用stark组件了!

    配置stark组件

    在stark应用目录下,创建server目录,在此目录下新建文件stark.py

    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'start'
            self.namespace = 'start'
    
        def register(self,model_class):
            # 添加键值对,固定值为1
            self._registry[model_class] = 1
    
            print(self._registry)  # 打印字典
    
    site = AdminSite()  # 实例化类
    View Code

    修改 app01-->stark.py

    # 这里的site,指的是实例化后的变量名
    from stark.server.stark import site
    from app01 import models
    
    site.register(models.UserInfo)  # 注册表
    View Code

    修改 app02-->stark.py

    # 这里的site,指的是实例化后的变量名
    from stark.server.stark import site
    from app02 import models
    
    site.register(models.Role)  # 注册表
    View Code

    重启django项目,查看Pycharm控制台输出:

    {<class 'app01.models.UserInfo'>: 1}
    {<class 'app01.models.UserInfo'>: 1, <class 'app02.models.Role'>: 1}
    {<class 'app01.models.UserInfo'>: 1}
    {<class 'app02.models.Role'>: 1, <class 'app01.models.UserInfo'>: 1}

    注意:如果输入内容为空!那是因为stark应用下的apps.py没有配置ready方法!!!

    由于字典是无序的,所有显示的顺序和大家可能不一样。不要诧异!

    从上面的输出,可以看出。现在字典有2个值,分别是

    <class 'app02.models.Role'>: 1和<class 'app01.models.UserInfo'>: 1

    这是一个单例模式,app01和app02共同操作了同一个字典_registry

    修改  stark-->server-->stark.py

    class StarkConfig(object):
        def __init__(self,model_class):
            self.b = model_class
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'start'
            self.namespace = 'start'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            self._registry[model_class] = stark_config(model_class)
    
            # print(self._registry)  # 打印字典
    
            for k, v in self._registry.items():
                print(k, v.b)
                # print(id(k), id(v.b))
    
    site = AdminSite()  # 实例化类
    View Code

    重启django项目,查看Pycharm控制台输出:

    <class 'app01.models.UserInfo'> <class 'app01.models.UserInfo'>
    <class 'app02.models.Role'> <class 'app02.models.Role'>
    <class 'app01.models.UserInfo'> <class 'app01.models.UserInfo'>
    <class 'app01.models.UserInfo'> <class 'app01.models.UserInfo'>
    <class 'app02.models.Role'> <class 'app02.models.Role'>
    <class 'app01.models.UserInfo'> <class 'app01.models.UserInfo'>

    从上面的结果可以看出,k和v.b的值是一样的!

    为什么k和v.b的值是一样的呢?请参考文章的开头《类可否作为字典的key》里面的高级用法!

    需要注意的是,stark_config(model_class)等同于StarkConfig(model_class)

    还是一个就是if not None问题

    看一下app01是如何注册UserInfo表的

    site.register(models.UserInfo)  # 注册表

    它并没有传入参数stark_config。那么register方法,会调用stark_config的默认参数,也就是None

    修改  stark-->server-->stark.py,把key改规范一点

    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'start'
            self.namespace = 'start'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                models.UserInfo:StarkConfig(models.UserInfo)
                models.Role:StarkConfig(models.Role)
            }
            """
    
            for k, v in self._registry.items():
                print(k,v.model_class)
    
    site = AdminSite()  # 实例化类
    View Code

    重启django项目,查看Pycharm控制台输出,效果同上!

    修改 app02-->stark.py,注册表时,传一个参数

    # 这里的site,指的是实例化后的变量名
    # StarkConfig表示类
    from stark.server.stark import site,StarkConfig
    from app02 import models
    
    class RoleConfig(StarkConfig):
        pass
    
    site.register(models.Role,RoleConfig)  # 注册表
    View Code

    修改 stark-->server-->stark.py,打印k和v

    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'start'
            self.namespace = 'start'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                app01.models.UserInfo:StarkConfig(app01.models.UserInfo)
                app02.models.Role:RoleConfig(app02.models.Role)
            }
            """
    
            for k, v in self._registry.items():
                print(k,v)
    
    site = AdminSite()  # 实例化类
    View Code

    重启django项目,查看Pycharm控制台输出

    <class 'app01.models.UserInfo'> <stark.server.stark.StarkConfig object at 0x000001DEF35A09B0>
    <class 'app02.models.Role'> <app02.stark.RoleConfig object at 0x000001DEF35A0860>
    <class 'app01.models.UserInfo'> <stark.server.stark.StarkConfig object at 0x000001DEF35A09B0>
    <class 'app01.models.UserInfo'> <stark.server.stark.StarkConfig object at 0x000001FD23D209E8>
    <class 'app01.models.UserInfo'> <stark.server.stark.StarkConfig object at 0x000001FD23D209E8>
    <class 'app02.models.Role'> <app02.stark.RoleConfig object at 0x000001FD23D20898>

    可以发现,现在_registry字典有2个值了。key和value是不一样的

    {
        app01.models.UserInfo:StarkConfig(app01.models.UserInfo),
        app02.models.Role:RoleConfig(app02.models.Role)
    }

    UserInfo对应StarkConfig,Role对应RoleConfig。

    为什么是这样的呢?请参数面向对象的继承,因为时间关系,没法一一细说。

    注意:self指的是实例化对象。如果实例化了StarkConfig,那么self就是StarkConfig类!

    下面是一个面向对象的小练习,如果能弄懂,那么上面的结果,也就明白了

    """ 第一个列子
    class StarkConfig(object):
        def __init__(self, model_class,site):
            self.model_class = model_class
            self.site = site
    
        def func(self):
            print(666)
    
    class RoleConfig(StarkConfig):
    
        def func(self):
            print(999)
    
    
    obj1 = StarkConfig(11,22)
    obj1.func() # obj1是谁的对象?StarkConfig
    
    obj2 = RoleConfig(44,55)
    obj2.func() # obj2是谁的对象?RoleConfig对象
    """
    
    """ 第二个列子
    class StarkConfig(object):
        def __init__(self, model_class, site):
            self.model_class = model_class
            self.site = site
    
        def func(self):
            print(666)
    
        def run(self):
            self.func()
    
    class RoleConfig(StarkConfig):
    
        def func(self):
            print(999)
    
    
    obj1 = StarkConfig(11,22)
    obj1.run() # 666
    
    obj2 = RoleConfig(44,55)
    obj2.run() # 999
    
    # self到底是谁?self是谁就是哪个类中先开始超找
    """
    
    
    
    """ 第三个列子
    class StarkConfig(object):
        def __init__(self, model_class, site):
            self.model_class = model_class
            self.site = site
    
        def func(self):
            print(self.site)
    
        def run(self):
            self.func()
    
    class RoleConfig(StarkConfig):
    
        def func(self):
            print(self.site)
    
    
    obj1 = StarkConfig(11,22)
    obj1.run() # 22
    
    obj2 = RoleConfig(44,55)
    obj2.run() # 55
    """
    View Code

    修改 stark-->server-->stark.py,增加urls方法

    第一个值是列表,这样做的目的,是为路由分发。

    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'stark'
            self.namespace = 'stark'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                app01.models.UserInfo:StarkConfig(app01.models.UserInfo)
                app02.models.Role:RoleConfig(app02.models.Role)
            }
            """
    
            for k, v in self._registry.items():
                print(k,v)
    
        @property
        def urls(self):
            # self.app_name和self.namespace值是一样的,都是stark
            return [],self.app_name,self.namespace
    
    site = AdminSite()  # 实例化类
    View Code

    修改untitled-->urls.py,这个是总路由。导入site

    from django.conf.urls import url,include
    from django.contrib import admin
    from app01 import views
    from stark.server.stark import site
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        # site.urls等同于[],'stark','stark'
        url(r'^stark/', site.urls),
    
        url(r'^rbac/', ([
            url(r'^login/', views.login, name='login'),
            url(r'^logout/', views.logout, name='logout'),
            url(r'^x1/', ([
                        url(r'^add/', views.add, name='add'),
                        url(r'^change/', views.change, name='change'),
                          ],None,'xxx')),
        ],None,'rbac')),
    ]
    View Code

    修改 stark-->server-->stark.py,增加get_urls方法

    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'stark'
            self.namespace = 'stark'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                app01.models.UserInfo:StarkConfig(app01.models.UserInfo)
                app02.models.Role:RoleConfig(app02.models.Role)
            }
            """
    
            for k, v in self._registry.items():
                print(k,v)
    
        def get_urls(self):
            urlpatterns = []
            return urlpatterns
    
        @property
        def urls(self):
            # 调用get_urls方法
            # self.app_name和self.namespace值是一样的,都是stark
            return self.get_urls(),self.app_name,self.namespace
    
    site = AdminSite()  # 实例化类
    View Code

    修改 stark-->server-->stark.py,增加视图函数x1,x2

    from django.conf.urls import url
    from django.shortcuts import HttpResponse
    
    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'stark'
            self.namespace = 'stark'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                app01.models.UserInfo:StarkConfig(app01.models.UserInfo)
                app02.models.Role:RoleConfig(app02.models.Role)
            }
            """
    
            # for k, v in self._registry.items():
            #     print(k,v)
    
        def x1(self, request):
            return HttpResponse('stark x1')
    
        def x2(self, request):
            return HttpResponse('stark x2')
    
        def get_urls(self):
            urlpatterns = []
    
            urlpatterns.append(url(r'^x1/',self.x1))
            urlpatterns.append(url(r'^x2/', self.x2))
    
            return urlpatterns
    
        @property
        def urls(self):
            # 调用get_urls方法
            # self.app_name和self.namespace值是一样的,都是stark
            return self.get_urls(),self.app_name,self.namespace
    
    site = AdminSite()  # 实例化类
    View Code

    修改untitled-->urls.py,这个是总路由。删除多余的代码

    from django.conf.urls import url,include
    from django.contrib import admin
    from app01 import views
    from stark.server.stark import site
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        # 导入stark组件的路由
        url(r'^stark/', site.urls),
    ]
    View Code

    重启django项目,访问url: http://127.0.0.1:8000/stark/x1/

    还可以再做一次路由分发

    修改 stark-->server-->stark.py,增加4个路径

    from django.conf.urls import url
    from django.shortcuts import HttpResponse
    
    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'stark'
            self.namespace = 'stark'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                app01.models.UserInfo:StarkConfig(app01.models.UserInfo)
                app02.models.Role:RoleConfig(app02.models.Role)
            }
            """
    
            # for k, v in self._registry.items():
            #     print(k,v)
    
        def x1(self, request):
            return HttpResponse('stark x1')
    
        def x2(self, request):
            return HttpResponse('stark x2')
    
        def get_urls(self):
            urlpatterns = []
    
            urlpatterns.append(url(r'^x1/',self.x1))
            urlpatterns.append(url(r'^x2/', self.x2))
            urlpatterns.append(url(r'^x3/', ([
                                                 url(r'^add/', self.x1),
                                                 url(r'^change/', self.x1),
                                                 url(r'^del/', self.x1),
                                                 url(r'^edit/', self.x1),
                                             ],None,None)))
    
            return urlpatterns
    
        @property
        def urls(self):
            # 调用get_urls方法
            # self.app_name和self.namespace值是一样的,都是stark
            return self.get_urls(),self.app_name,self.namespace
    
    site = AdminSite()  # 实例化类
    View Code

    重启django项目,访问url:  http://127.0.0.1:8000/stark/x3/add/

    这样写太麻烦了,使用for循环

    修改 stark-->server-->stark.py

    from django.conf.urls import url
    from django.shortcuts import HttpResponse
    
    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'stark'
            self.namespace = 'stark'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                app01.models.UserInfo:StarkConfig(app01.models.UserInfo)
                app02.models.Role:RoleConfig(app02.models.Role)
            }
            """
    
            # for k, v in self._registry.items():
            #     print(k,v)
    
        def x1(self, request):
            return HttpResponse('stark x1')
    
        def x2(self, request):
            return HttpResponse('stark x2')
    
        def get_urls(self):
            urlpatterns = []
    
            # urlpatterns.append(url(r'^x1/',self.x1))
            # urlpatterns.append(url(r'^x2/', self.x2))
            # urlpatterns.append(url(r'^x3/', ([
            #                                      url(r'^add/', self.x1),
            #                                      url(r'^change/', self.x1),
            #                                      url(r'^del/', self.x1),
            #                                      url(r'^edit/', self.x1),
            #                                  ],None,None)))
            for k, v in self._registry.items():
                # k=modes.UserInfo,v=StarkConfig(models.UserInfo), # 封装:model_class=UserInfo,site=site对象
                # k=modes.Role,v=RoleConfig(models.Role)           # 封装:model_class=Role,site=site对象
                app_label = k._meta.app_label
                model_name = k._meta.model_name
                # 为每一个表,添加增删改查的url
                urlpatterns.append(url(r'^%s/%s/' % (app_label, model_name,), ([
                                                 url(r'^add/', self.x1),
                                                 url(r'^change/', self.x1),
                                                 url(r'^del/', self.x1),
                                                 url(r'^edit/', self.x1),
                                             ],None,None)))
    
            return urlpatterns
    
        @property
        def urls(self):
            # 调用get_urls方法
            # self.app_name和self.namespace值是一样的,都是stark
            return self.get_urls(),self.app_name,self.namespace
    
    site = AdminSite()  # 实例化类
    View Code

    重启django项目,访问userinfo表的添加方法

    http://127.0.0.1:8000/stark/app01/userinfo/add/

    效果如下:

    但是urlpatterns固定了,这样不好

    修改 stark-->server-->stark.py

    from django.conf.urls import url
    from django.shortcuts import HttpResponse
    
    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'stark'
            self.namespace = 'stark'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                app01.models.UserInfo:StarkConfig(app01.models.UserInfo)
                app02.models.Role:RoleConfig(app02.models.Role)
            }
            """
    
            # for k, v in self._registry.items():
            #     print(k,v)
    
        def x1(self, request):
            return HttpResponse('stark x1')
    
        def x2(self, request):
            return HttpResponse('stark x2')
    
        def get_urls(self):
            urlpatterns = [
                url(r'^list/$', self.x1),
                url(r'^add/$', self.x1),
                url(r'^(?P<pk>d+)/change/', self.x1),
                url(r'^(?P<pk>d+)/del/', self.x1),
            ]
    
            return urlpatterns
    
        @property
        def urls(self):
            # 调用get_urls方法
            # self.app_name和self.namespace值是一样的,都是stark
            return self.get_urls(),self.app_name,self.namespace
    
    site = AdminSite()  # 实例化类
    View Code

    视图函数的名字不够规范,需要改名

    修改 stark-->server-->stark.py

    from django.conf.urls import url
    from django.shortcuts import HttpResponse
    
    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'stark'
            self.namespace = 'stark'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                app01.models.UserInfo:StarkConfig(app01.models.UserInfo)
                app02.models.Role:RoleConfig(app02.models.Role)
            }
            """
    
            # for k, v in self._registry.items():
            #     print(k,v)
    
        def change_list(self, request):
            return HttpResponse('stark list')
    
        def change_add(self, request):
            return HttpResponse('stark add')
    
        def change_form(self, request, pk):
            return HttpResponse('stark form')
    
        def change_del(self, request, pk):
            return HttpResponse('stark del')
    
        def get_urls(self):
            urlpatterns = [
                url(r'^list/$', self.change_list),
                url(r'^add/$', self.change_add),
                url(r'^(?P<pk>d+)/change/', self.change_form),
                url(r'^(?P<pk>d+)/del/', self.change_del),
            ]
            # for k, v in self._registry.items():
            #     # k=modes.UserInfo,v=StarkConfig(models.UserInfo), # 封装:model_class=UserInfo,site=site对象
            #     # k=modes.Role,v=RoleConfig(models.Role)           # 封装:model_class=Role,site=site对象
            #     app_label = k._meta.app_label
            #     model_name = k._meta.model_name
            #     urlpatterns.append(url(r'^%s/%s/' % (app_label, model_name,), (v.urls, None, None)))
    
            return urlpatterns
    
        @property
        def urls(self):
            # 调用get_urls方法
            # self.app_name和self.namespace值是一样的,都是stark
            return self.get_urls(), self.app_name, self.namespace
    
    site = AdminSite()  # 实例化类
    View Code

    某一个表要增加方法呢?可以定义extra_url方法,用来扩展

    修改 stark-->server-->stark.py

    注意:这里要来一个大的变动。将AdminSite相关代码移植到StarkConfig,并在StarkConfig增加extra_url方法

    from django.conf.urls import url
    from django.shortcuts import HttpResponse
    
    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
        def change_list(self, request):
            return HttpResponse('stark list')
    
        def change_add(self, request):
            return HttpResponse('stark add')
    
        def change_form(self, request, pk):
            return HttpResponse('stark form')
    
        def change_del(self, request, pk):
            return HttpResponse('stark del')
    
        def get_urls(self):
            info = self.model_class._meta.app_label, self.model_class._meta.model_name
    
            urlpatterns = [
                url(r'^list/$', self.change_list),
                url(r'^add/$', self.change_add),
                url(r'^(?P<pk>d+)/change/', self.change_form),
                url(r'^(?P<pk>d+)/del/', self.change_del),
            ]
    
            extra = self.extra_url()
            if extra:  # 判断变量不为空
                # 扩展路由
                urlpatterns.extend(extra)
    
            return urlpatterns
    
        def extra_url(self):  # 额外的路由,由调用者重构
            pass
    
        @property
        def urls(self):
            return self.get_urls()
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'stark'
            self.namespace = 'stark'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                app01.models.UserInfo:StarkConfig(app01.models.UserInfo)
                app02.models.Role:RoleConfig(app02.models.Role)
            }
            """
    
            # for k, v in self._registry.items():
            #     print(k,v)
    
        def get_urls(self):
            urlpatterns = []
    
            for k, v in self._registry.items():
                # k=modes.UserInfo,v=StarkConfig(models.UserInfo), # 封装:model_class=UserInfo,site=site对象
                # k=modes.Role,v=RoleConfig(models.Role)           # 封装:model_class=Role,site=site对象
                app_label = k._meta.app_label
                model_name = k._meta.model_name
                urlpatterns.append(url(r'^%s/%s/' % (app_label, model_name,), (v.urls, None, None)))
    
            return urlpatterns
    
        @property
        def urls(self):
            # 调用get_urls方法
            # self.app_name和self.namespace值是一样的,都是stark
            return self.get_urls(), self.app_name, self.namespace
    
    site = AdminSite()  # 实例化类
    View Code

    修改 app02-->stark.py,重构extra_url方法。添加新的路由

    # 这里的site,指的是实例化后的变量名
    # StarkConfig表示类
    from stark.server.stark import site,StarkConfig
    from app02 import models
    from django.conf.urls import url
    from django.shortcuts import HttpResponse
    
    class RoleConfig(StarkConfig):
        def sk2(self, request):
            return HttpResponse('sk2神仙水')
    
        def extra_url(self):
            data = [
                url(r'^sk2/$', self.sk2),
            ]
            return data
    
    site.register(models.Role,RoleConfig)  # 注册表
    View Code

    重启django项目,访问新增加的url:

    http://127.0.0.1:8000/stark/app02/role/sk2/

    效果如下:

    那么role表,就有5个url了。

    而userinfo表,只有4个url

    查看admin相关源码,将url改成和admin的一致

    修改 stark-->server-->stark.py

    from django.conf.urls import url
    from django.shortcuts import HttpResponse
    
    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
        def changelist_view(self, request):
            return HttpResponse('stark list')
    
        def add_view(self, request):
            return HttpResponse('stark add')
    
        def change_view(self, request, pk):
            return HttpResponse('stark change')
    
        def delete_view(self, request, pk):
            return HttpResponse('stark delete')
    
        def get_urls(self):
            info = self.model_class._meta.app_label, self.model_class._meta.model_name
    
            urlpatterns = [
                url(r'^list/$', self.changelist_view),
                url(r'^add/$', self.add_view),
                url(r'^(?P<pk>d+)/change/', self.change_view),
                url(r'^(?P<pk>d+)/del/', self.delete_view),
            ]
    
            extra = self.extra_url()
            if extra:  # 判断变量不为空
                # 扩展路由
                urlpatterns.extend(extra)
    
            return urlpatterns
    
        def extra_url(self):  # 额外的路由,由调用者重构
            pass
    
        @property
        def urls(self):
            return self.get_urls()
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'stark'
            self.namespace = 'stark'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                app01.models.UserInfo:StarkConfig(app01.models.UserInfo)
                app02.models.Role:RoleConfig(app02.models.Role)
            }
            """
    
            # for k, v in self._registry.items():
            #     print(k,v)
    
        def get_urls(self):
            urlpatterns = []
    
            for k, v in self._registry.items():
                # k=modes.UserInfo,v=StarkConfig(models.UserInfo), # 封装:model_class=UserInfo,site=site对象
                # k=modes.Role,v=RoleConfig(models.Role)           # 封装:model_class=Role,site=site对象
                app_label = k._meta.app_label
                model_name = k._meta.model_name
                urlpatterns.append(url(r'^%s/%s/' % (app_label, model_name,), (v.urls, None, None)))
    
            return urlpatterns
    
        @property
        def urls(self):
            # 调用get_urls方法
            # self.app_name和self.namespace值是一样的,都是stark
            return self.get_urls(), self.app_name, self.namespace
    
    site = AdminSite()  # 实例化类
    View Code

    增加别名

    修改 stark-->server-->stark.py

    from django.conf.urls import url
    from django.shortcuts import HttpResponse
    
    class StarkConfig(object):
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
        def changelist_view(self, request):
            return HttpResponse('stark list')
    
        def add_view(self, request):
            return HttpResponse('stark add')
    
        def change_view(self, request, pk):
            return HttpResponse('stark change')
    
        def delete_view(self, request, pk):
            return HttpResponse('stark delete')
    
        def get_urls(self):
            info = self.model_class._meta.app_label, self.model_class._meta.model_name
    
            urlpatterns = [
                url(r'^list/$', self.changelist_view, name='%s_%s_changelist' % info),
                url(r'^add/$', self.add_view, name='%s_%s_add' % info),
                url(r'^(?P<pk>d+)/change/', self.change_view, name='%s_%s_change' % info),
                url(r'^(?P<pk>d+)/del/', self.delete_view, name='%s_%s_del' % info),
            ]
    
            extra = self.extra_url()
            if extra:  # 判断变量不为空
                # 扩展路由
                urlpatterns.extend(extra)
    
            return urlpatterns
    
        def extra_url(self):  # 额外的路由,由调用者重构
            pass
    
        @property
        def urls(self):
            return self.get_urls()
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = 'stark'
            self.namespace = 'stark'
    
        def register(self,model_class,stark_config=None):
            # not None的结果为Ture
            if not stark_config:
                # 也就是说,当其他应用调用register时,如果不指定stark_config参数
                # 那么必然执行下面这段代码!
                # stark_config和StarkConfig是等值的!都能实例化
                stark_config = StarkConfig
    
            # 添加键值对,实例化类StarkConfig,传入参数model_class
            # self指的是AdminSite类
            self._registry[model_class] = stark_config(model_class,self)
    
            # print(self._registry)  # 打印字典
            """
            {
                app01.models.UserInfo:StarkConfig(app01.models.UserInfo)
                app02.models.Role:RoleConfig(app02.models.Role)
            }
            """
    
            # for k, v in self._registry.items():
            #     print(k,v)
    
        def get_urls(self):
            urlpatterns = []
    
            for k, v in self._registry.items():
                # k=modes.UserInfo,v=StarkConfig(models.UserInfo), # 封装:model_class=UserInfo,site=site对象
                # k=modes.Role,v=RoleConfig(models.Role)           # 封装:model_class=Role,site=site对象
                app_label = k._meta.app_label
                model_name = k._meta.model_name
                urlpatterns.append(url(r'^%s/%s/' % (app_label, model_name,), (v.urls, None, None)))
    
            return urlpatterns
    
        @property
        def urls(self):
            # 调用get_urls方法
            # self.app_name和self.namespace值是一样的,都是stark
            return self.get_urls(), self.app_name, self.namespace
    
    site = AdminSite()  # 实例化类
    View Code

    重启django项目,访问url: 

    http://127.0.0.1:8000/stark/app02/role/list/

    效果如下:

    从django启动,到每一个表,生成了4个URL。这中间经历了复杂的过程!

    流程图

    说明:

    注意以app01为例:

    1. 启动时,执行settings.py。加载INSTALLED_APPS里面的app,从上到下执行!

    2.执行到stark应用时,执行apps.py。执行ready方法,调用autodiscover_modules方法!
    它会查找每一个app应用下的stark.py文件,并执行文件!

    3. 执行stark.py时,执行from stark.server.stark import site。它会调用stark-->server-->stark.py里面的site
    site执行了实例化

    4. 再执行site.register(models.UserInfo)。它会调用stark-->server-->stark.py里面的register方法
    执行self._registry[model_class] = stark_config(model_class,self),调用StarkConfig的__init__方法
    self._registry增加key-value。value就是StarkConfig类

    5.执行总路由,也就是urls.py,调用site.urls。这里的site就是stark-->server-->stark.py里面的site
    执行AdminSite的urls方法。注意,它加了@property。所以可以site.urls执行方法。

    6.它里面调用了get_urls方法,执行for循环,将url添加到urlpatterns列表中。以app01的userinfo表为列
    url(r'^%s/%s/' % (app_label, model_name,)就相当于url(r'^app01/userinfo/',)
    后面的(v.urls, None, None),它是一个元组。这就相当于执行了include。include它返回一个元组。必须有3个值
    这里的v.urls,指的就是StarkConfig.urls。为什么v是StarkConfig类?看步骤4的key-value


    7. 执行StarkConfig类的urls方法,注意:它加了@property,可以不需要括号,就可以执行。


    8. 它调用了get_urls方法。这里的self就是StarkConfig类。执行get_urls方法里面的urlpatterns,它加了4个URL,用来做增删改查的。


    9. 判断app应用下start.py是否重构了extra_url方法。如果是,执行自己应用下的extra_url方法。它必须返回一个列表。

        这里只有app02重构了extra_url方法。返回了一个列表。执行urlpatterns.extend(extra)。表示在urlpatterns列表中添加一个列表。


    10. 此时在总路由中,urlpatterns数据结构如下:

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^stark/', ([
            url(r'^app01/userinfo/', ([
                url(r'^list/$', self.changelist_view, name='app01_userinfo_changelist'),
                url(r'^add/$', self.add_view, name='app01_userinfo_add'),
                url(r'^(?P<pk>d+)/change/', self.change_view, name='app01_userinfo_change'),
                url(r'^(?P<pk>d+)/del/', self.delete_view, name='app01_userinfo_del'),
                  ],None,None)),
        ],None,'stark')),
    ]

    所以可以访问一下url: 

    http://127.0.0.1:8000/stark/app01/userinfo/list/

    效果如下:

    完整代码,请访问github

    https://github.com/987334176/luffy_stark/archive/v1.0.zip

  • 相关阅读:
    DIV高度设置全屏
    Yii2使用PHPExcel读取excel
    关于linux centos7 vmware 和windows7 文件共享笔记
    mysql rpm包安装
    linux crontab 计划任务脚本
    linux php5.6 安装
    linux上安装php phpredis扩展
    让微信小程序每次请求的时候不改变session_id的方法
    mysql主从配置
    mysql存储过程之游标遍历数据表
  • 原文地址:https://www.cnblogs.com/xiao987334176/p/9550969.html
Copyright © 2020-2023  润新知