Django 【第二十五篇】Django admin源碼解析

1、admin的源碼流程django

首先能夠肯定的是:路由關係必定對應一個視圖函數app

a、當點擊運行的時候,會先找到每個app中的admin.py文件,並執行函數

b、執行urls.py post

admin.site是什麼?url

admin.site,urls    返回的是一個元組,裏面的第一個元素是一個列表code

django-admin的源碼流程
咱們本身生成的動態的訪問url
====================================初級版=========================
from django.shortcuts import HttpResponse
from django.conf.urls import url
from django.contrib import admin
from app01 import views
def login(request):
    return HttpResponse("ok")

url_list = []

for model_class,v in admin.site._registry.items():
    print(model_class)  #打印的是每個類<class 'app01.models.UserInfo'>
    cls_name = model_class._meta.model_name #當前類名稱的小寫
    app_name = model_class._meta.app_label  #當前app的名稱
    val = url(r'^{0}/{1}/$'.format(app_name,cls_name), login, name="login")
    url_list.append(val)

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # admin.site這個對象裏面有一個屬性_registry = {}
    #點擊urls查看源碼返回的是一個元組,元組的第一個元素是一個列表
    url(r'^index/', ([
            url(r'^app01/userinfo/$', login,name="login"),
             url(r'^app01/roles/$', login,name="login"),
        ],None,None)),
        
    url(r'^index2/', (url_list,None,None,)),  #吧上面定義的列表拿下來,這是後就動態生成了
]
================================升級============================
路徑http://127.0.0.1:8001/index/app01/roles/後面還有增刪改查的路徑
http://127.0.0.1:8001/index/app01/roles/add/
http://127.0.0.1:8001/index/app01/roles/1/change/
http://127.0.0.1:8001/index/app01/roles/1/del/

實現流程
from django.shortcuts import HttpResponse
from django.conf.urls import url
from django.contrib import admin
from app01 import views
def login(request):
    return HttpResponse("ok")

def change_list(request):
    return HttpResponse("列表頁面")

def add_view(request):
    return HttpResponse("添加頁面")

def change_view(request,nid):
    return HttpResponse("修改頁面")

def delete_view(request,nid):
    return HttpResponse("刪除頁面")

url_list = []

for model_class,v in admin.site._registry.items():
    print(model_class)  #打印的是每個類<class 'app01.models.UserInfo'>
    cls_name = model_class._meta.model_name #當前類名稱的小寫
    app_name = model_class._meta.app_label  #當前app的名稱
    urls_list = url(r'^{0}/{1}/$'.format(app_name,cls_name), change_list, name="login")
    url_list.append(urls_list)

    add_url = url(r'^{0}/{1}/add/$'.format(app_name, cls_name), add_view, name="login")
    url_list.append(add_url)

    change_url = url(r'^{0}/{1}/(\d+)/change/$'.format(app_name, cls_name), change_view, name="login")
    url_list.append(change_url)

    del_url = url(r'^{0}/{1}/(\d+)/del/$'.format(app_name, cls_name), delete_view, name="login")
    url_list.append(del_url)

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # admin.site這個對象裏面有一個屬性_registry = {}
    #點擊urls查看源碼返回的是一個元組,元組的第一個元素是一個列表
    url(r'^index/', (
        [
            url(r'^app01/userinfo/$', login,name="login"),
            url(r'^app01/roles/$', login,name="login"),
         ],None,None)),
    url(r'^index2/', (url_list,None,None,)),  #吧上面定義的列表拿下來,這是後就動態生成了
]

說明了:
    url的本質:它讀取_registry全部字典裏面的數據,爲字典裏面的每個類生成了4個url
==================================修改上面的版本=============================
定義了一個
def get_urls():
    temp = [
        url(r'^$'.format(app_name, cls_name), change_list),
        url(r'^add/$'.format(app_name, cls_name), add_view),
        url(r'^del/$'.format(app_name, cls_name), delete_view),
        url(r'^change/$'.format(app_name, cls_name), change_view)
    ]
    return temp
    
url_list = []
for model_class,v in admin.site._registry.items():
    print('-------',model_class)  #打印的是每個類<class 'app01.models.UserInfo'>
    cls_name = model_class._meta.model_name #當前類名稱的小寫
    app_name = model_class._meta.app_label  #當前app的名稱
    方式一:
    # all_urls = url(r'^{0}/{1}/'.format(app_name,cls_name), (get_urls(),None,None,))
    方式二:
    all_urls = url(r'^{0}/{1}/'.format(app_name,cls_name), include(get_urls()) )   
    url_list.append(all_urls)

    
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # admin.site這個對象裏面有一個屬性_registry = {}
    #點擊urls查看源碼返回的是一個元組,元組的第一個元素是一個列表
    url(r'^index/', (
        [
            url(r'^app01/userinfo/', ([
                                           url(r'^$', change_list, name="login"),
                                           url(r'^add/$', add_view, name="login"),
                                           url(r'^(\d+)/del/$', delete_view, name="login"),
                                           url(r'^(\d+)/change/$', change_view, name="login"),
                                       ],None,None),name="login"),
            url(r'^app01/usertype/', ([
                                           url(r'^$', change_list, name="login"),
                                           url(r'^add/$', add_view, name="login"),
                                           url(r'^(\d+)/del/$', delete_view, name="login"),
                                           url(r'^(\d+)/change/$', change_view, name="login"),
                                       ], None, None), name="login"),],None,None)),
            url(r'^app02/article/', ([
                                           url(r'^$', change_list, name="login"),
                                           url(r'^add/$', add_view, name="login"),
                                           url(r'^(\d+)/del/$', delete_view, name="login"),
                                           url(r'^(\d+)/change/$', change_view, name="login"),
                                       ],None,None),name="login"),

    # index和index2的兩個是同樣的,咱們能夠用index2的方式替代index
    url(r'^index2/', (url_list,None,None,)),  #吧上面定義的列表拿下來,這是後就動態生成了
]


include的本質就是:返回了一個元組,元組的第一個是這個模塊
include裏面
    既能夠寫一個列表include([]),利用include作分發
    也能夠返回一個字符串:幫咱們去找到這個模塊,找到全部的映射關係

include(model_admin.urls)
model_admin是什麼?ModelAdmin對象的urls

總結orm

- admin源碼流程
        a. 運行程序,找到每個app中的 admin.py 文件,並加載
            - app01.admin.py 
                - 建立admin.site中的對象
                - 執行對象的 register方法,目的:將註冊類添加到 _registry中 
                    _registry = {  
                        key是傳進來的model   value:是ModelAdmin的對象,傳了兩個參數
                        models.Role: ModelAdmin(models.Role,admin.site),
                        models.UserInfo: ModelAdmin(models.UserInfo,admin.site)
                        models.UserType: ModelAdmin(models.UserType,admin.site)
                    }
                
            - app02.admin.py
                - 用app01.admin中建立那個admin.site對象
                - 執行對象的 register方法,目的:講註冊類添加到 _registry中 
                    _registry = {
                        models.Role: ModelAdmin(models.Role,admin.site),
                        models.UserInfo: ModelAdmin(models.UserInfo,admin.site)
                        models.UserType: ModelAdmin(models.UserType,admin.site)
                        models.Article: ModelAdmin(models.Article,admin.site)
                    }
        
            admin.site是一個對象(單例模式建立),其中封裝了: 
                _registry = {
                    models.Role: ModelAdmin(models.Role,admin.site),
                    models.UserInfo: ModelAdmin(models.UserInfo,admin.site)
                    models.UserType: ModelAdmin(models.UserType,admin.site)
                    models.Article: ModelAdmin(models.Article,admin.site)
                }
        b. urls.py 
            再次調用 admin.site 對象的 urls屬性:
                urlpatterns = [
                    url(r'^admin/', admin.site.urls),
                ]
            
            class ModelAdmin(object):
                def __init__(self,model_class,site):
                    self.model_class = model_class
                    self.site = site 
                    
                def changelist_view(self,request):
                    data_list = self.model_class.objects.all()   #是動態的
                    return HttpResponse('列表頁面')

                def add_view(self,request):
                    return HttpResponse('添加頁面')


                def delete_view(self,request,nid):
                    return HttpResponse('刪除頁面')

                def change_view(self,request,nid):
                    return HttpResponse('修改頁面')
                
                def get_urls(self):
                     urlpatterns = [
                        url(r'^$', self.changelist_view),
                        url(r'^add/$', self.add_view),
                        url(r'^(.+)/delete/$', self.delete_view),
                        url(r'^(.+)/change/$', self.change_view),
                    ]
                    return urlpatterns
                
                @property 
                def urls(self):
                    return self.get_urls()
                
            
            class AdminSite(object):
                def __init__(self):
                    self._registry = {}
                    
                def register(self,model_class,model_admin):
                    self._registry[model_class] = model_admin(model_class,self)
                
                def get_urls(self):
                    """
                    models.Role: ModelAdmin(models.Role,admin.site),
                    models.UserInfo: ModelAdmin(models.UserInfo,admin.site)
                    models.UserType: ModelAdmin(models.UserType,admin.site)
                    models.Article: ModelAdmin(models.Article,admin.site)
                    """
                    url_list = []
                    for model_class,model_admin in self._registry.items():
                        model_class是一個類
                        app_name = model_class._meta.app_label
                        model_name = model_class._meta.model_name 
                        url_list += [
                            url('%s/%s' %(app_name,model_name,), include(model_admin.urls))
                        ]
                        
                    return url_list
                        
                
                @property
                def urls(self):
                    return (self.get_urls(), None,None )
相關文章
相關標籤/搜索