Django-admin源碼解析

單例模式

前言:實(shí)例化出來的每個對象都是不同的內(nèi)存地址,調(diào)用每個對象的方法都是調(diào)用同一塊內(nèi)存地址 —— 個人理解

單例模式(Singleton Pattern)是一種常用的軟件設(shè)計模式,該模式的主要目的是確保某一個類只有一個實(shí)例存在.當(dāng)你希望在整個系統(tǒng)中,某個類只能出現(xiàn)一個實(shí)例時,單例對象就能派上用場.

比如,某個服務(wù)器程序的配置信息存放在一個文件中,客戶端通過一個 AppConfig 的類來讀取配置文件的信息.如果在程序運(yùn)行期間,有很多地方都需要使用配置文件的內(nèi)容,也就是說,很多地方都需要創(chuàng)建 AppConfig 對象的實(shí)例,這就導(dǎo)致系統(tǒng)中存在多個AppConfig 的實(shí)例對象,而這樣會嚴(yán)重浪費(fèi)內(nèi)存資源,尤其是在配置文件內(nèi)容很多的情況下.事實(shí)上,類似 AppConfig 這樣的類,我們希望在程序運(yùn)行期間只存在一個實(shí)例對象.

在 Python 中,我們可以用多種方式實(shí)現(xiàn)單例模式:

  • 使用模塊
  • 使用 _new_
  • 使用裝飾器 (decorator)
  • 使用元類 (metaclass)

每個實(shí)例化的對象都是生成不一樣的內(nèi)存空間(除單例模式)
調(diào)用同一個實(shí)例化對象,第一次生成自己的內(nèi)存空間,第二次第三次都是調(diào)用第一次的內(nèi)存地址

(1)使用 new

為了使類只能出現(xiàn)一個實(shí)例,我們可以使用 new 來控制實(shí)例的創(chuàng)建過程,代碼如下

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

在上面的代碼中,我們將類的實(shí)例和一個類變量 _instance 關(guān)聯(lián)起來,如果 cls._instance 為 None 則創(chuàng)建實(shí)例,否則直接返回 cls._instance。

執(zhí)行情況如下:

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

(2)使用模塊

其實(shí),Python 的模塊就是天然的單例模式,因?yàn)槟K在第一次導(dǎo)入時,會生成 .pyc 文件,當(dāng)?shù)诙螌?dǎo)入時,就會直接加載 .pyc 文件,而不會再次執(zhí)行模塊代碼。因此,我們只需把相關(guān)的函數(shù)和數(shù)據(jù)定義在一個模塊中,就可以獲得一個單例對象了。如果我們真的想要一個單例類,可以考慮這樣做:

# mysingleton.py
class My_Singleton(object):
    def foo(self):
        pass
 
my_singleton = My_Singleton()

將上面的代碼保存在文件 mysingleton.py 中,然后這樣使用:

from mysingleton import my_singleton
 
my_singleton.foo()

admin執(zhí)行流程

<1> 循環(huán)加載執(zhí)行所有已經(jīng)注冊的app中的admin.py文件

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

<2> 執(zhí)行代碼

#admin.py

class BookAdmin(admin.ModelAdmin):
    list_display = ("title",'publishDate', 'price')

admin.site.register(Book, BookAdmin) 
admin.site.register(Publish)

<3> admin.site

image.png

這里應(yīng)用的是一個單例模式,對于AdminSite類的一個單例模式,執(zhí)行的每一個app中的每一個admin.site都是一個對象
<4> 執(zhí)行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)   # 執(zhí)行結(jié)果?

到這里,注冊結(jié)束!

<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()方法的擴(kuò)展應(yīng)用

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)),

]

擴(kuò)展優(yōu)化

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)),
]
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,569評論 19 139
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時...
    歐辰_OSR閱讀 30,244評論 8 265
  • 一 在我家樓的對面里,有一個女孩,一個膽子很小的女孩,女孩子一般都很膽小,這并不奇怪,但是她的膽子就是出乎意料的膽...
    李不通閱讀 1,407評論 4 38
  • 懶加載的介紹 swift中也有懶加載的方式(蘋果的設(shè)計思想:希望所有的對象在使用時才真正加載到內(nèi)存中) 和OC不同...
    猴子的救兵520閱讀 1,049評論 0 1
  • 1 知識準(zhǔn)備 1.1 NSMethodSignature NSMethodSignature-方法簽名類方法簽名中...
    盤石垂釣閱讀 502評論 0 4

友情鏈接更多精彩內(nèi)容