项目要求: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 不过建表就须要本身动手了