1. 程式人生 > >自定義Xadmin

自定義Xadmin

二級路由 wrap open orm utils 其他 publish gis 是個

1.啟動Xadmin

INSTALLED_APPS = [
    django.contrib.admin,
    django.contrib.auth,
    django.contrib.contenttypes,
    django.contrib.sessions,
    django.contrib.messages,
    django.contrib.staticfiles,
    Xadmin.apps.XadminConfig,
    app01.apps.App01Config,
    app02.apps.App02Config
, ]
執行流程:
1.在啟動Django後,按app順序進行加載。先加載 ‘django.contrib.admin‘,Django自身生成admi.site單例對象,生成user和group兩張表
加載到‘Xadmin.apps.XadminConfig‘,執行Xadmin中apps文件中的XadminConfig
apps中的代碼:
from django.apps import AppConfig
class XadminConfig(AppConfig):
name = ‘Xadmin‘
2.XadminConfig中有個raedy方法,會自動執行,Django默認去讀取自身和其他app的admin文件,如在相應的app的admin文件中輸入

print("xadmin") print("app01")print("app02")進行測試
啟動django後,就會根據加載順序打印出結果:
xadmin
app01
app02
3.在執行第一個app的admin文件時,
from django.contrib import admin 會執行admin,打開admin源碼分析:
admin源碼:
from django.utils.module_loading import autodiscover_modules
def autodiscover():
autodiscover_modules(‘admin‘, register_to=site) #啟動admin

4.打開site site = AdminSite() 因此在執行admin文件時就生成了app應用的單例對象admin.site,在掃描其他app的admin文件時
由於from django.contrib import admin已經加載過,因此直接拿到第一個app生成的單例對象

2.配置Xadmin下的apps文件

我們可以自己設置函數
如:在類中添加
def ready(self):
print("ok") 在啟動django,加載到Xadmin的app文件時,自動執行ready函數,打印出"ok"
Django加載時默認讀取其他app的admin文件,因此要設置在執行這個文件時,去讀取其他app的Xadmin文件.根據admin文件去寫
from django.apps import AppConfig
from django.utils.module_loading import autodiscover_modules
class XadminConfig(AppConfig):
name = ‘Xadmin‘
def ready(self):
autodiscover_modules(‘Xadmin‘)
#在加載app文件時時讀取自身和其他app的xadmin文件。由於是自定義admin,目的是讓其他app執行自定義的admin,因此刪除掉Xadmin下的admin
測試:在app01和app02分別新建Xadmin文件,輸入print("Xadmin app01")和print("Xadmin app01")打印後:
admin app01 #在admin文件中的測試
admin app02
Xadmin app01
Xadmin app02
原因:‘django.contrib.admin‘,會先執行,因此先加載app中的admin文件,將自帶的admin關掉就可以了
Xadmin app01
Xadmin app02

3.配置Xadmin的註冊,新建個文件夾放Xadmin.py文件,代碼仿著admin.py文件寫

#根據ModelAdmin源碼寫
class Modelxadmin(object):
    def __init__(self,model,site):
        self.model=model
        self.site=site

class XadminSite(object):
    def __init__(self, name=admin):
        self._registry = {}
    def register(self, model, admin_class=None, **options):
        if not admin_class:
            admin_class = Modelxadmin #根據AdminSite源碼,定義admin_class類
    self._registry[model] = admin_class(model, self)
site=XadminSite() #生成單例對象

4.在app中的xadmin文件中引入Xadmin,進行註冊模型表

app01 Xadmin.py
from Xadmin.service.Xadmin import site
from app01 import models
site.register(models.Book)
site.register(models.Publish)
site.register(models.Author)
site.register(models.AuthorDetail)
app02 Xadmin.py
from Xadmin.service.Xadmin import site
from app02 import models
site.register(models.Order)
print(site._registry)  #結果有五個表

5.設計路由:

參考admin的路由設計
urlpatterns = [
url(r‘^admin/‘, admin.site.urls), admin.site是Adminsite類的對象,urls是 AdminSite類中的一個方法
]
查看AdminSite源碼:找到urls方法,分析其流程。執行urls方法後,執行get_urls方法,在get_urls設置路由
admin的路由源碼:
技術分享圖片
@property
def urls(self):
    return self.get_urls(), admin, self.name #結果是個元祖即等同於url(r^admin/,(get_urls(),None,None))
def get_urls(self):
    from django.conf.urls import url, include
    def wrap(view, cacheable=False):
        def wrapper(*args, **kwargs):
            return self.admin_view(view, cacheable)(*args, **kwargs)
        wrapper.admin_site = self
        return update_wrapper(wrapper, view)
    # Admin-site-wide views.
    urlpatterns = [
        url(r^$, wrap(self.index), name=index),
        url(r^login/$, self.login, name=login),
        url(r^logout/$, wrap(self.logout), name=logout),
        url(r^password_change/$, wrap(self.password_change, cacheable=True), name=password_change),
        url(r^password_change/done/$, wrap(self.password_change_done, cacheable=True),
            name=password_change_done),
        url(r^jsi18n/$, wrap(self.i18n_javascript, cacheable=True), name=jsi18n),
        url(r^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$, wrap(contenttype_views.shortcut),
            name=view_on_site),
View Code

設置Xadmin路由:

1.from Xadmin.service.Xadmin import site
urlpatterns = [
#根據admin路由設置方式設置Xadmin路由
url(r‘^Xadmin/‘, site.urls),
]
2.在Xadmin中設置urls方法
技術分享圖片
 class XadminSite(object):
        def __init__(self, name=admin):
            self._registry = {}
        def register(self, model, admin_class=None, **options):
            if not admin_class:
                admin_class = Modelxadmin #根據AdminSite源碼,定義夜歌admin_class類
            self._registry[model] = admin_class(model, self)
        def list_view(self,request):
            return HttpResponse("這是查看的網頁")
        def add_view(self,request):
            return HttpResponse("這是添加的網頁")
        def change_view(self,request, id):
            return HttpResponse("這是編輯的網頁")
        def del_view(self,request, id):
            return HttpResponse("這是刪除的網頁")
        def get_url_2(self):
            temp = []
            temp.append(url(r"^$", self.list_view))
            temp.append(url(r"^add/$", self.add_view))
            temp.append(url(r"^(\d+)/change/$", self.change_view))
            temp.append(url(r"^(\d+)/del/$", self.del_view))
            return temp
        @property
        def urls2(self):
            return self.get_url_2(), None, None
        def get_urls(self):
            temp = []
            print(self._registry)
            for model, admin_class in self._registry.items():
                app_name = model._meta.app_label  # 拿到app的名字
                model_name = model._meta.model_name  # 拿到字符串類型的表名
                temp.append(url(r"^{}/{}/".format(app_name, model_name), self.urls2))
            return temp
        @property
        def urls(self): #self就是XadminSite單例出來的對象
            return self.get_urls(), None, None
View Code

6.獲取數據:

將二級路由放到XadminSite類之後,即創建的book,publish等模型表在Xadmin中所有的配置都一樣。
同時在進行相應的表的數據查詢時,比較困難 為了不同的模型表顯示不同的效果,將二級路由放到Modelxadmin中
技術分享圖片
 class Modelxadmin(object):
        def __init__(self,model,site):  #如果傳的是book,model就是book 傳的是publish,model就是publiah
            self.model=model
            self.site=site
        def list_view(self, request):
            print(self.model)  #用戶調用的哪張表,self.model就是哪張表  <class app02.models.Order>
            print(request.path_info)  # /Xadmin/app01/publish/
            data_list=self.model.objects.all()
            # return HttpResponse("這是查看的網頁")
            return render(request,"list.html",{"data_list":data_list})
        def add_view(self, request):
            return HttpResponse("這是添加的網頁")
        def change_view(self, request, id):
            return HttpResponse("這是編輯的網頁")
        def del_view(self, request, id):
            return HttpResponse("這是刪除的網頁")
        def get_url_2(self):
            temp = []
            temp.append(url(r"^$", self.list_view))
            temp.append(url(r"^add/$", self.add_view))
            temp.append(url(r"^(\d+)/change/$", self.change_view))
            temp.append(url(r"^(\d+)/del/$", self.del_view))
            return temp
        @property
        def urls2(self):
            return self.get_url_2(), None, None
    class XadminSite(object):
        def get_urls(self):
            temp = []
            print(self._registry)
            for model, xadmin_class in self._registry.items(): #xadmin_class=admin_class(model, self)是註冊的模型表對象 ModelAdmin(Book)
                app_name = model._meta.app_label  # 拿到app的名字
                model_name = model._meta.model_name  # 拿到字符串類型的表名
                temp.append(url(r"^{}/{}/".format(app_name, model_name), xadmin_class.urls2))
                #此時的路由表示
                  url(r"app01/book",ModelXadmin(Book,site).urls2)
                  url(r"app01/publish",ModelXadmin(Publish,site).urls2)
                  url(r"app02/order",ModelXadmin(Order,site).urls2)
            return temp
View Code

 
 
 
 

自定義Xadmin