zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    js截取字符串区分汉字字母代码
    List 去处自定义重复对象方法
    63. Unique Paths II
    62. Unique Paths
    388. Longest Absolute File Path
    41. First Missing Positive
    140. Word Break II
    139. Word Break
    239. Sliding Window Maximum
    5. Longest Palindromic Substring
  • 原文地址:https://www.cnblogs.com/xiao987334176/p/9550969.html
Copyright © 2011-2022 走看看