zoukankan      html  css  js  c++  java
  • 6 admin(注册设计)源码解析、单例模式

    1、单例模式

     https://www.cnblogs.com/yuanchenqi/articles/8323452.html 

    单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

    比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。

    在 Python 中,我们可以用多种方法来实现单例模式:

    • 使用模块
    • 使用 __new__
    • 使用装饰器(decorator)
    • 使用元类(metaclass)

    1. 使用 __new__

    为了使类只能出现一个实例,我们可以使用 __new__ 来控制实例的创建过程,代码如下:

    class Singleton(object):
        _instance = None
        def __new__(cls, *args, **kw):
            if not cls._instance:
                cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)  
            return cls._instance  
    
    class MyClass(Singleton):  
        a = 1

    在上面的代码中,我们将类的实例和一个类变量 _instance 关联起来,如果 cls._instance 为 None 则创建实例,否则直接返回 cls._instance

    执行情况如下:

    >>> one = MyClass()
    >>> two = MyClass()
    >>> one == two
    True
    >>> one is two
    True
    >>> id(one), id(two)
    (4303862608, 4303862608)

    2. 使用模块

     其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:

    # mysingleton.py
    
    class My_Singleton(object):
        x = 12
        def foo(self):
            print(self.x)
    
    my_singleton = My_Singleton()
    
    print('ok')

    将上面的代码保存在文件 mysingleton.py 中,然后这样使用:

    from mysingleton import my_singleton
     
    my_singleton.foo()

     注:python 自己的玩法, python 在导模块时,就执行代码;

    main.py

    # # -*- coding:utf-8 -*-
    #
    from mysingleton import my_singleton
    #
    # # pyc 中间 临时文件
    #
    # # my_singleton.foo()
    # print(id(my_singleton))
    #
    #
    from mysingleton import my_singleton
    #
    #
    # # 在找 不会加载 第二遍  去临时 pyc 拿
    #
    # # my_singleton.foo()
    # print(id(my_singleton))
    #
    #
    # from func import *
    # foo()  #三个id 会一样吗?? 一样,一次程序的执行,
    #
    # """
    # ok
    # 2341951012992
    # 2341951012992
    # 2341951012992
    # """
    #
    #
    # """
    # 12
    # 2664635842288
    # 12
    # 2664635842288
    #
    # 为什么内存地址一样
    #
    # python 自己的玩法, python 在导模块 就执行代码
    # """
    
    
    from mysingleton import my_singleton,My_Singleton
    
    a = My_Singleton()
    b = My_Singleton()
    
    print(id(a),id(b))
    # 2306139672928 2306139673096
    # 不一样,类实例化,
    # 单例 是从模块里 哪一个实例对象
    
    print(id(my_singleton),id(my_singleton))
    # 2310426005856 2310426005856  一样,
    View Code

     func.py

    from mysingleton import my_singleton
    
    def foo():
        print(id(my_singleton))

    2、admin源码解析

    <1> 循环加载执行所有已经注册的app中的admin.py文件

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

    <2> 执行代码

    复制代码
    复制代码
    #admin.py

    class BookAdmin(admin.ModelAdmin): list_display = ("title",'publishDate', 'price')
    admin.site.register(Book, BookAdmin)
    admin.site.register(Publish)
    复制代码
    复制代码

    <3> admin.site  

     这里应用的是一个单例模式,对于AdminSite类的一个单例模式,执行的每一个app中的每一个admin.site都是一个对象

    <4> 执行register方法

    admin.site.register(Book, BookAdmin) 
    admin.site.register(Publish)
    class ModelAdmin(BaseModelAdmin):pass
    
    def register(self, model_or_iterable, admin_class=None, **options):
        if not admin_class:
                admin_class = ModelAdmin
        # Instantiate the admin class to save in the registry
        self._registry[model] = admin_class(model, self)

    思考:在每一个app的admin .py中加上

    print(admin.site._registry)   # 执行结果?

    到这里,注册结束!

    <5> admin的URL配置

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
    ]
    class AdminSite(object):
        
         def get_urls(self):
            from django.conf.urls import url, include
          
            urlpatterns = []
    
            # Add in each model's views, and create a list of valid URLS for the
            # app_index
            valid_app_labels = []
            for model, model_admin in self._registry.items():
                urlpatterns += [
                    url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),
                ]
                if model._meta.app_label not in valid_app_labels:
                    valid_app_labels.append(model._meta.app_label)
    
          
            return urlpatterns
    
        @property
        def urls(self):
            return self.get_urls(), 'admin', self.name

    <6>  url()方法的扩展应用

    from django.shortcuts import HttpResponse
    def test01(request):
        return HttpResponse("test01")
    
    def test02(request):
        return HttpResponse("test02")
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^yuan/', ([
                        url(r'^test01/', test01),
                        url(r'^test02/', test02),
    
                        ],None,None)),
    
    ]

    扩展优化

    from django.conf.urls import url,include
    from django.contrib import admin
    
    from django.shortcuts import HttpResponse
    
    def change_list_view(request):
        return HttpResponse("change_list_view")
    def add_view(request):
        return HttpResponse("add_view")
    def delete_view(request):
        return HttpResponse("delete_view")
    def change_view(request):
        return HttpResponse("change_view")
    
    def get_urls():
    
        temp=[
            url(r"^$".format(app_name,model_name),change_list_view),
            url(r"^add/$".format(app_name,model_name),add_view),
            url(r"^d+/del/$".format(app_name,model_name),delete_view),
            url(r"^d+/change/$".format(app_name,model_name),change_view),
        ]
    
        return temp
    
    
    url_list=[]
    
    for model_class,obj in admin.site._registry.items():
    
        model_name=model_class._meta.model_name
        app_name=model_class._meta.app_label
    
        # temp=url(r"{0}/{1}/".format(app_name,model_name),(get_urls(),None,None))
        temp=url(r"{0}/{1}/".format(app_name,model_name),include(get_urls()))
        url_list.append(temp)
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^yuan/', (url_list,None,None)),
    ]

     

    3、注册源码流程图

     

    {<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x00000085C948DD68>}
    
    {<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x00000085C948DD68>, 
    <class 'app01.models.Book'>: <django.contrib.admin.options.ModelAdmin object at 0x00000085C94C87F0>}

     

    {<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x0000008CD0BCCCF8>}
    {<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x0000008CD0BCCCF8>, 
    <class 'app01.models.Book'>: <django.contrib.admin.options.ModelAdmin object at 0x0000008CD0C0EDA0>}
    {
    <class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x0000008CD0BCCCF8>,
    <class 'app01.models.Book'>: <django.contrib.admin.options.ModelAdmin object at 0x0000008CD0C0EDA0>,
    <class 'app02.models.Book'>: <django.contrib.admin.options.ModelAdmin object at 0x0000008CD0C0EF28>}

     

    3、admin之url方法的使用

        情况1:url(r'^book/', views.book),  # book(request)

      情况2 分发:

    url(r"^yuan/", ([
    url(r'^test01/', ([
    url(r'^test04/', test04),
    url(r'^test05/', test05),
    ], None, None)),
    url(r'^test02/', test02),
    url(r'^test03/', test03),
    ], None, None)
    )

     code

    from django.conf.urls import url
    from django.contrib import admin
    from django.shortcuts import HttpResponse
    
    from app01 import views
    
    def test01(request):
    
        return HttpResponse("test01")
    
    def test02(request):
    
        return HttpResponse("test02")
    
    def test03(request):
    
        return HttpResponse("test03")
    
    
    def test01111(request):
        return HttpResponse('test01111')
    
    def test01333(request):
        return HttpResponse('test01333')
    
    def test01222(request):
        return HttpResponse('test01222')
    
    
    def yuan(request):
    
        return HttpResponse("yuan")
    
    
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/', views.login),
        url(r'^index/', views.index),
        url(r'^book/', views.book),
    
        # url(r'^yuan/', yuan),
    
        url(r'^yuan/',([
                           url(r'^test01/',([
                                                url(r'^test01111',test01111),
                                                url(r'^test01111',test01222),
                                                url(r'^test01111',test01333),
    
                                             ],None,None)),
                           url(r'^test02/',test02),
                           url(r'^test03/',test03),
    
                        ],None,None))
    ]
    View Code

    4、admin源码之url设计

    1、 如何通过model类变量获取该模型的字符串名称和该模型所在app的字符串名称:

    print("===>", model._meta.model_name)
    print("===>", model._meta.app_label)

     

    2、扩展1层url

     3、扩展2层url

     

     5、设计url源码流程

     

     6、总结

    1、code代码

    url.py  设计+注册

    """MRBS URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.11/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url
    from django.contrib import admin
    from django.shortcuts import HttpResponse
    
    from app01 import views
    
    def test01(request):
    
        return HttpResponse("test01")
    
    def test02(request):
    
        return HttpResponse("test02")
    
    def test03(request):
    
        return HttpResponse("test03")
    
    
    def test01111(request):
        return HttpResponse('test01111')
    
    def test01333(request):
        return HttpResponse('test01333')
    
    def test01222(request):
        return HttpResponse('test01222')
    
    
    
    
    def list_view(reuquest):
        return HttpResponse("list_view")
    
    def add(reuquest):
        return HttpResponse("add")
    
    def delete(reuquest,id):
        return HttpResponse("delete")
    
    def change(reuquest,id):
        return HttpResponse("change")
    
    def get_urls2():
        temp = []
        temp.append(url(r"^$/",list_view))
        temp.append(url(r"^add/",add))
        temp.append(url(r"^(d+)/delete",delete))
        temp.append(url(r"^(d+)/change",change))
    
        return temp
    
    def get_urls():
        temp = []
        # print("_registry", admin.site._registry)
        for model,admin_class_obj in admin.site._registry.items():
            # print("model",model)  # model <class 'app02.models.Book'>  "app01"   "book"
            # print(model._meta.model_name)       # "book"
            # print(model._meta.app_label)    # "app01"
            model_name = model._meta.model_name
            app_label = model._meta.app_label
            temp.append(url(r"%s/%s/"%(app_label,model_name),(get_urls2(),None,None)))
    
        return temp
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/', views.login),
        url(r'^index/', views.index),
        url(r'^book/', views.book),
        url(r'^yuan/', (get_urls(),None,None))
    ]
    
    
    
    
    """
    1、url的使用
    url(r'^yuan/',([
                       url(r'^test01/',([
                                            url(r'^test01111',test01111),
                                            url(r'^test01111',test01222),
                                            url(r'^test01111',test01333),
    
                                         ],None,None)),
                       url(r'^test02/',test02),
                       url(r'^test03/',test03),
    
                    ],None,None))
    """
    View Code

    2、知识点1:单例模式

     单例模式

    生成单例模式的方式:
    (1)使用 __new__
            class Singleton(object):
                    _instance = None
                    def __new__(cls, *args, **kw):
                        if not cls._instance:
                            cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)  
                        return cls._instance  
                
                class MyClass(Singleton):  
                    a = 1
                
                >>> one = MyClass()
                >>> two = MyClass()
                >>> one == two
                True
     
            (2)使用模块
                class My_Singleton(object):
                    x = 12
                    def foo(self):
                        print(self.x)
                    
                my_singleton = My_Singleton()
            
            
                from mysingleton import my_singleton
                my_singleton.foo()
     

    2、知识点2:url()的使用:


    情况1:path('book/', views.book), # book(request)
    情况2:分发:
    path('yuan/',yuan), # yuan
    path('yuan/',([],None,None)) # None,None 代表:namespace app(name)
    path('yuan/',([path('test01/',test01)],None,None)), # yuan/test01
            path('yuan/',([
                    path('test01/',([
                        path('test04/',test04),                        # yuan/test01/test04
                        path('test05/',test05)                         # yuan/test01/test05
                                    ],None,None)),
                    path('test02/',test02),                            # yuan/test02
                    path('test03/',test03)                             # yuan/test03
                                ],None,None))    
        
    注: re_path(r'^test04/',test04), # 以test04开头;
    re_path(r'test04/',test04), # 包含test04;

    3、知识点3:admin源码

        admin源码:

    1.注册 admin.py
    from django.contrib import admin

    class BookConfig(admin.ModelAdmin):
    list_display = ['user', 'room']
    ...

    admin.site.register(Book,BookConfig) # admin.site 就是 AdminSite()的一个实例化对象(单例)
    admin.site.register(UserInfo,UserConfig)
    admin.site.register(Room)
            class AdminSite():
                def __init__(self, name='admin'):
                    self._registry = {}
                
                def register(self, model, admin_class=None):
                    if not admin_class:
                        admin_class = ModelAdmin
                
                    self._registry[model] = admin_class(model, self)
    
            ...
            ...
            site = AdminSite()
    复制代码

    所以:按顺序注册后,结果都在 admin.site._registry 字典里面;model为键,admin_class(model, self)为值;
    即:Book为键,BookConfig()为值;
    UserInfo为键,UserConfig()为值;
    Room为键,ModelAdmin()为值;

    注意:admin.site._registry 全局的!! 多个app共用!!(startapp02)
         print(admin.site._registry)
                {<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x000002777731D400>,
                <class 'app01.models.Book'>: <app01.admin.BookConfig object at 0x000002777735C470>,
                <class 'app01.models.UserInfo'>: <app01.admin.UserConfig object at 0x000002777735C4A8>,
                <class 'app01.models.Room'>: <django.contrib.admin.options.ModelAdmin object at 0x000002777735C4E0>,
                <class 'app01.models.GF'>: <django.contrib.admin.options.ModelAdmin object at 0x000002777735C518>,
                <class 'app02.models.Book'>: <django.contrib.admin.options.ModelAdmin object at 0x000002777735C438>}

    2.设计 url:
    注意:
    1.
    path('yuan/',(get_urls(),None,None)),
    path('yuan/',include(get_urls()))

    2.
    for model,admin_class_obj in admin.site._registry.items():
    print('****',model) # **** <class 'app01.models.Book'>

    model_name = model._meta.model_name # book
    app_label = model._meta.app_label # app01

    3.
    temp.append(path('%s/%s/'%(app_label,model_name),(get_urls2(),None,None)))

    4.
    temp.append(path('add/',add))
    temp.append(re_path(r'(d+)/delete/',delete))
    temp.append(re_path(r'(d+)/change/',change))
    temp.append(re_path(r'^$',list_view))

    5.
    # 24条 url 。。。
    # http://127.0.0.1:8020/yuan/app01/book/
    # http://127.0.0.1:8020/yuan/app01/userinfo/add/
    # http://127.0.0.1:8020/yuan/app01/book/5/delete/
    # http://127.0.0.1:8020/yuan/app02/book/
    。。。
    。。。
  • 相关阅读:
    【 SSH 配置参考】
    【 SSH 实例】使用ssh开发的简单项目
    【 Hibernate 】Hibernate的session更新和删除失败问题
    【 SSH 整合】Spring、Struts、Hibernate基本整合
    Tower是个不错的项目管理开放平台
    随便写写,四年多了第一次在博客园上发表
    asp.net获取服务器绝对路径和相对路径
    342. 4的幂
    283. 移动零
    268. 缺失数字
  • 原文地址:https://www.cnblogs.com/venicid/p/9482716.html
Copyright © 2011-2022 走看看