項目要求:html
模仿django自帶的admin組件,開發一套屬於咱們本身的start組件
前端
今日項目重點:python
重點一:單例模式,須要理解基於模塊的單例模式具體是怎麼回事,及其做用django
重點二:路由的二級分發app
重點三:對於self什麼狀況指的是理解函數
首先,咱們先來講一下基於模塊的單例模式,測試
單例顧名思義就是隻有一個實例 url
咱們如今一個py文件裏定義好以下的類spa
class F: def __init__(self,name): self.name=name def sname(self): print(self.name) f=F('alex')
print('ok')
而後在另外一個py文件中導入咱們實例化的對象小f命令行
from 基礎知識.a import f print(id(f)) from 基礎知識.a import f print(id(f)) #輸出結果
#ok #1845270931384 #1845270931384
咱們明明導入了兩次模塊 爲啥只打印出一個ok吶 由於這是python獨有的一個機制 它會把第一次導入的模塊 保存到一個地方 若是下面還導入模塊 並不會使用 而是從第一個那拿 咱們所須要的
可是,若是導入的是大F,那就至關於從新實例化獲得一個新的對象 而每個對象都有屬於本身的一塊內存空間
from 基礎知識.a import F print(id(F('alex'))) print(id(F('alex'))) #輸出結果 # ok # 3024850486216 # 3024850485320
若是對類與對象的內存不是很清楚 能夠看下圖
路由的二級分發:
首先來介紹一個路由分發的一個標準([],None,None)列表中 放分發的路由,第一個None是,,,第二個None指的是app暫時用不到 咱們先用None來代替
二級路由分發的最基本的方式:
這麼寫的話 路由分發少的時候 還好 若是路由分發不少的時候 就會很亂 因此咱們能夠用下列方法代替
self:
在咱們看源碼去封裝一個功能或者理解源碼是什麼意思的時候 咱們必定要注意一個問題 那就是self到底指的是哪一個對象
只有肯定了這一點才能繼續往走 self所表明的對象不一樣 整個類所要作的事固然也就不一樣 就向咱們以前所說的 每一個類的實例化對象
即便實例化的值是同樣的可是仍是徹底不一樣的兩個對象
下面開始咱們的項目:
首先第一步 咱們要先從新建一個django項目,
而後在命令行裏 從新建立一個項目用來寫咱們自定義的stark組件的源代碼
而後在app01下加入stark
接下來就須要咱們進去配置文件中將stark配置成項目啓動 stark也會跟着啓動
而後將stark中的app里加一個啓動文件
接下來咱們測試一下,在app01下的stark.py文件中加print("ok")而後啓動django項目看看 會不會直接打印ok
測試成功 說明咱們的準備工做已經作好
先在stark文件下建一個service的包 ,並在裏面建立一個stark.py
而後在url裏導入 跟admin同樣作成一個方法 項目啓動就能夠執行 項目啓動就能執行
而後咱們再去導入的文件裏寫咱們自定義的源碼
class ModelStark(): def __init__(self,model): self.model = model class StarkSite(object): def __init__(self): self._registry = {} def register(self, model, admin_class=None, **options): if not admin_class: admin_class = ModelStark self._registry[model] = admin_class(model, self) site = StarkSite()
這就是個單例生成的對象都是相同的因此所佔的把內存空間都是相同 那_register字典裏的值不會重置,只要生成一個對象就會添加一對鍵值對 這就是單例的好處
接下來咱們須要寫路由分發
class StarkSite(object): def __init__(self): self._registry = {} def register(self, model, admin_class=None, **options): if not admin_class: admin_class = ModelStark self._registry[model] = admin_class(model) def get_urls(self): temp = [ ] for model_class, config_obj in self._registry.items(): print("===>", model_class, config_obj) model_name = model_class._meta.model_name app_label = model_class._meta.app_label print("===>", app_label, model_name) temp.append(url(r'^%s/%s/' % (app_label, model_name), config_obj.urls)) ''' 建立url: url("app01/book/$",self.list_view), url("app01/book/add$",self.add_view), url("app01/book/(\d+)/change/$",self.change_view), url("app01/book/(\d+)/delete/$",self.delete_view), url("app01/publish/$",self.list_view), url("app01/publish/add$",self.add_view), url("app01/publish/(\d+)/change/$",self.change_view), url("app01/publish/(\d+)/delete/$",self.delete_view), ''' return temp @property def urls(self): return self.get_urls(), None, None site = StarkSite()
由於咱們將urls封裝成屬性 因此咱們能夠在url中 直接加點調用一個函數
這裏要聲明一個問題,若是按照下面的寫法,會出現一個問題
class StarkSite(object): def __init__(self): self._registry = {} def register(self, model, admin_class=None, **options): if not admin_class: admin_class = ModelStark self._registry[model] = admin_class(model) def add_view(self, request): return HttpResponse("add_view") def change_view(self, request,id): return HttpResponse("change_view") def delete_view(self, request,id): return HttpResponse("delete_view") def get_urls(self): temp=[ url("^$",self.list_view), url("^add/$",self.add_view), url("^(\d+)/change_view/$",self.change_view), url("^(\d+)/delete_view$",self.delete_view), ] return temp @property def urls(self): return self.get_urls(),None,None def get_urls1(self): temp = [ ] for model_class, config_obj in self._registry.items(): print("===>", model_class, config_obj) model_name = model_class._meta.model_name app_label = model_class._meta.app_label print("===>", app_label, model_name) temp.append(url(r'^%s/%s/' % (app_label, model_name), config_obj.urls)) ''' 建立url: url("app01/book/$",self.list_view), url("app01/book/add$",self.add_view), url("app01/book/(\d+)/change/$",self.change_view), url("app01/book/(\d+)/delete/$",self.delete_view), url("app01/publish/$",self.list_view), url("app01/publish/add$",self.add_view), url("app01/publish/(\d+)/change/$",self.change_view), url("app01/publish/(\d+)/delete/$",self.delete_view), ''' return temp @property def urls(self): return self.get_urls1(), None, None site = StarkSite()
由於site = StarkSite()是單例因此會致使無論誰來調用self都是相同的 這就會致使全部的頁面的樣式都會是相同的 ,這就違背了 咱們要寫的組件 咱們要寫的組件就是爲了可實現,頁面能夠自定義
如下就是完整的路由分發
from django.conf.urls import url from django.shortcuts import HttpResponse,redirect,render class ModelStark(): def __init__(self,model): self.model = model def list_view(self,request): #用戶訪問的模型表: self.model print("self.model:",self.model) print("self.list_display",self.list_display) queryset=self.model.objects.all() return render(request,"stark/list_view.html",{'queryset':queryset}) def add_view(self, request): return HttpResponse("add_view") def change_view(self, request,id): return HttpResponse("change_view") def delete_view(self, request,id): return HttpResponse("delete_view") def get_urls(self): temp=[ url("^$",self.list_view), url("^add/$",self.add_view), url("^(\d+)/change_view/$",self.change_view), url("^(\d+)/delete_view$",self.delete_view), ] return temp @property def urls(self): return self.get_urls(),None,None class StarkSite(object): def __init__(self): self._registry = {} def register(self, model, admin_class=None, **options): if not admin_class: admin_class = ModelStark self._registry[model] = admin_class(model) def get_urls1(self): temp = [ ] for model_class, config_obj in self._registry.items(): print("===>", model_class, config_obj) model_name = model_class._meta.model_name app_label = model_class._meta.app_label print("===>", app_label, model_name) temp.append(url(r'^%s/%s/' % (app_label, model_name), config_obj.urls)) ''' 建立url: url("app01/book/$",self.list_view), url("app01/book/add$",self.add_view), url("app01/book/(\d+)/change/$",self.change_view), url("app01/book/(\d+)/delete/$",self.delete_view), url("app01/publish/$",self.list_view), url("app01/publish/add$",self.add_view), url("app01/publish/(\d+)/change/$",self.change_view), url("app01/publish/(\d+)/delete/$",self.delete_view), ''' return temp @property def urls(self): return self.get_urls1(), None, None site = StarkSite()
可是咱們還會遇到一個問題:前端頁面傳值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h3>數據展現</h3> <ul> {% for item in queryset %} <li>{{ item }}</li> {% endfor %} </ul> </body> </html>
這就須要咱們告訴前端頁面須要打印什麼字段
這就用到自定義
from app01 import models from stark.service.strak import site,ModelStark class BookConfig(ModelStark): list_display = ["title","price"] site.register(models.Book,BookConfig) site.register(models.Publish) site.register(models.Author) site.register(models.AuthorDetail)
自定義樣式如何在前端頁面展現 咱們下個博客更新
還有一點 本文並無寫models 不過建表就須要本身動手了