6 admin(注册设计)源码解析、单例模式
1、单例模式
https://www.cnblogs.com/yuanchenqi/articles/8323452.html
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。
在 Python 中,我们可以用多种方法来实现单例模式:
使用模块
使用
__new__使用装饰器(decorator)
使用元类(metaclass)
1. 使用 __new__
为了使类只能出现一个实例,我们可以使用 __new__ 来控制实例的创建过程,代码如下:
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
在上面的代码中,我们将类的实例和一个类变量 _instance 关联起来,如果 cls._instance 为 None 则创建实例,否则直接返回 cls._instance。
执行情况如下:
>>> one = MyClass()
>>> two = MyClass()
>>> one == two
True
>>> one is two
True
>>> id(one), id(two)
(4303862608, 4303862608)

2. 使用模块
其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:
# mysingleton.py class My_Singleton(object):
x = 12
def foo(self):
print(self.x) my_singleton = My_Singleton() print('ok')
将上面的代码保存在文件 mysingleton.py 中,然后这样使用:
from mysingleton import my_singleton my_singleton.foo()
注:python 自己的玩法, python 在导模块时,就执行代码;
main.py
# # -*- coding:utf-8 -*-
#
from mysingleton import my_singleton
#
# # pyc 中间 临时文件
#
# # my_singleton.foo()
# print(id(my_singleton))
#
#
from mysingleton import my_singleton
#
#
# # 在找 不会加载 第二遍 去临时 pyc 拿
#
# # my_singleton.foo()
# print(id(my_singleton))
#
#
# from func import *
# foo() #三个id 会一样吗?? 一样,一次程序的执行,
#
# """
# ok
#
#
#
# """
#
#
# """
#
#
#
#
#
# 为什么内存地址一样
#
# python 自己的玩法, python 在导模块 就执行代码
# """ from mysingleton import my_singleton,My_Singleton a = My_Singleton()
b = My_Singleton() print(id(a),id(b))
# 2306139672928 2306139673096
# 不一样,类实例化,
# 单例 是从模块里 哪一个实例对象 print(id(my_singleton),id(my_singleton))
# 2310426005856 2310426005856 一样,
func.py
from mysingleton import my_singleton def foo():
print(id(my_singleton))

2、admin源码解析
<1> 循环加载执行所有已经注册的app中的admin.py文件
def autodiscover():
autodiscover_modules('admin', register_to=site)
<2> 执行代码


#admin.py class BookAdmin(admin.ModelAdmin):
list_display = ("title",'publishDate', 'price')
admin.site.register(Book, BookAdmin)
admin.site.register(Publish)


<3> admin.site

这里应用的是一个单例模式,对于AdminSite类的一个单例模式,执行的每一个app中的每一个admin.site都是一个对象
<4> 执行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) # 执行结果?
到这里,注册结束!
<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()方法的扩展应用
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)), ]
扩展优化
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)),
]
3、注册源码流程图



{<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x00000085C948DD68>}
{<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x00000085C948DD68>,
<class 'app01.models.Book'>: <django.contrib.admin.options.ModelAdmin object at 0x00000085C94C87F0>}


{<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x0000008CD0BCCCF8>}
{<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x0000008CD0BCCCF8>,
<class 'app01.models.Book'>: <django.contrib.admin.options.ModelAdmin object at 0x0000008CD0C0EDA0>}
{<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x0000008CD0BCCCF8>,
<class 'app01.models.Book'>: <django.contrib.admin.options.ModelAdmin object at 0x0000008CD0C0EDA0>,
<class 'app02.models.Book'>: <django.contrib.admin.options.ModelAdmin object at 0x0000008CD0C0EF28>}

3、admin之url方法的使用
情况1:url(r'^book/', views.book), # book(request)


情况2 分发:
url(r"^yuan/", ([
url(r'^test01/', ([
url(r'^test04/', test04),
url(r'^test05/', test05),
], None, None)),
url(r'^test02/', test02),
url(r'^test03/', test03),
], None, None)
)





code
from django.conf.urls import url
from django.contrib import admin
from django.shortcuts import HttpResponse from app01 import views def test01(request): return HttpResponse("test01") def test02(request): return HttpResponse("test02") def test03(request): return HttpResponse("test03") def test01111(request):
return HttpResponse('test01111') def test01333(request):
return HttpResponse('test01333') def test01222(request):
return HttpResponse('test01222') def yuan(request): return HttpResponse("yuan") urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
url(r'^index/', views.index),
url(r'^book/', views.book), # url(r'^yuan/', yuan), url(r'^yuan/',([
url(r'^test01/',([
url(r'^test01111',test01111),
url(r'^test01111',test01222),
url(r'^test01111',test01333), ],None,None)),
url(r'^test02/',test02),
url(r'^test03/',test03), ],None,None))
]
4、admin源码之url设计
1、 如何通过model类变量获取该模型的字符串名称和该模型所在app的字符串名称:
print("===>", model._meta.model_name)
print("===>", model._meta.app_label)





2、扩展1层url


3、扩展2层url



5、设计url源码流程



6、总结
1、code代码
url.py 设计+注册
"""MRBS URL Configuration The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from django.shortcuts import HttpResponse from app01 import views def test01(request): return HttpResponse("test01") def test02(request): return HttpResponse("test02") def test03(request): return HttpResponse("test03") def test01111(request):
return HttpResponse('test01111') def test01333(request):
return HttpResponse('test01333') def test01222(request):
return HttpResponse('test01222') def list_view(reuquest):
return HttpResponse("list_view") def add(reuquest):
return HttpResponse("add") def delete(reuquest,id):
return HttpResponse("delete") def change(reuquest,id):
return HttpResponse("change") def get_urls2():
temp = []
temp.append(url(r"^$/",list_view))
temp.append(url(r"^add/",add))
temp.append(url(r"^(\d+)/delete",delete))
temp.append(url(r"^(\d+)/change",change)) return temp def get_urls():
temp = []
# print("_registry", admin.site._registry)
for model,admin_class_obj in admin.site._registry.items():
# print("model",model) # model <class 'app02.models.Book'> "app01" "book"
# print(model._meta.model_name) # "book"
# print(model._meta.app_label) # "app01"
model_name = model._meta.model_name
app_label = model._meta.app_label
temp.append(url(r"%s/%s/"%(app_label,model_name),(get_urls2(),None,None))) return temp urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
url(r'^index/', views.index),
url(r'^book/', views.book),
url(r'^yuan/', (get_urls(),None,None))
] """
1、url的使用
url(r'^yuan/',([
url(r'^test01/',([
url(r'^test01111',test01111),
url(r'^test01111',test01222),
url(r'^test01111',test01333), ],None,None)),
url(r'^test02/',test02),
url(r'^test03/',test03), ],None,None))
"""
2、知识点1:单例模式
单例模式
生成单例模式的方式:
(1)使用 __new__
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 >>> one = MyClass()
>>> two = MyClass()
>>> one == two
True
(2)使用模块
class My_Singleton(object):
x = 12
def foo(self):
print(self.x) my_singleton = My_Singleton() from mysingleton import my_singleton
my_singleton.foo()
2、知识点2:url()的使用:
情况1:path('book/', views.book), # book(request)
情况2:分发:
path('yuan/',yuan), # yuan
path('yuan/',([],None,None)) # None,None 代表:namespace app(name)
path('yuan/',([path('test01/',test01)],None,None)), # yuan/test01
path('yuan/',([
path('test01/',([
path('test04/',test04), # yuan/test01/test04
path('test05/',test05) # yuan/test01/test05
],None,None)),
path('test02/',test02), # yuan/test02
path('test03/',test03) # yuan/test03
],None,None))
注: re_path(r'^test04/',test04), # 以test04开头;
re_path(r'test04/',test04), # 包含test04;
3、知识点3:admin源码
admin源码:
1.注册 admin.py
from django.contrib import admin
class BookConfig(admin.ModelAdmin):
list_display = ['user', 'room']
...
admin.site.register(Book,BookConfig) # admin.site 就是 AdminSite()的一个实例化对象(单例)
admin.site.register(UserInfo,UserConfig)
admin.site.register(Room)
class AdminSite():
def __init__(self, name='admin'):
self._registry = {} def register(self, model, admin_class=None):
if not admin_class:
admin_class = ModelAdmin self._registry[model] = admin_class(model, self) ...
...
site = AdminSite()

所以:按顺序注册后,结果都在 admin.site._registry 字典里面;model为键,admin_class(model, self)为值;
即:Book为键,BookConfig()为值;
UserInfo为键,UserConfig()为值;
Room为键,ModelAdmin()为值; 注意:admin.site._registry 全局的!! 多个app共用!!(startapp02)
print(admin.site._registry)
{<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x000002777731D400>,
<class 'app01.models.Book'>: <app01.admin.BookConfig object at 0x000002777735C470>,
<class 'app01.models.UserInfo'>: <app01.admin.UserConfig object at 0x000002777735C4A8>,
<class 'app01.models.Room'>: <django.contrib.admin.options.ModelAdmin object at 0x000002777735C4E0>,
<class 'app01.models.GF'>: <django.contrib.admin.options.ModelAdmin object at 0x000002777735C518>,
<class 'app02.models.Book'>: <django.contrib.admin.options.ModelAdmin object at 0x000002777735C438>}
2.设计 url:
注意:
1.
path('yuan/',(get_urls(),None,None)),
path('yuan/',include(get_urls())) 2.
for model,admin_class_obj in admin.site._registry.items():
print('****',model) # **** <class 'app01.models.Book'> model_name = model._meta.model_name # book
app_label = model._meta.app_label # app01 3.
temp.append(path('%s/%s/'%(app_label,model_name),(get_urls2(),None,None))) 4.
temp.append(path('add/',add))
temp.append(re_path(r'(\d+)/delete/',delete))
temp.append(re_path(r'(\d+)/change/',change))
temp.append(re_path(r'^$',list_view)) 5.
# 24条 url 。。。
# http://127.0.0.1:8020/yuan/app01/book/
# http://127.0.0.1:8020/yuan/app01/userinfo/add/
# http://127.0.0.1:8020/yuan/app01/book/5/delete/
# http://127.0.0.1:8020/yuan/app02/book/
。。。
。。。
6 admin(注册设计)源码解析、单例模式的更多相关文章
- Django 之 admin组件使用&源码解析
admin组件使用 Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.可以在项目的 settings.py 中的 INSTALLED ...
- Android 源码解析:单例模式-通过容器实现单例模式-懒加载方式
本文分析了 Android 系统服务通过容器实现单例,确保系统服务的全局唯一. 开发过 Android 的用户肯定都用过这句代码,主要作用是把布局文件 XML 加载到系统中,转换为 Android 的 ...
- springboot ---> spring ioc 注册流程 源码解析 this.prepareContext 部分
现在都是在springboot 中 集成 spirng,那我们就从springboot 开始. 一:springboot 启动main 函数 public static void main(Strin ...
- admin源码解析及自定义stark组件
admin源码解析 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单 ...
- django -admin 源码解析
admin源码解析 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单 ...
- Django框架 之 admin管理工具(源码解析)
浏览目录 单例模式 admin执行流程 admin源码解析 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在 ...
- [源码解析] PyTorch 分布式 Autograd (5) ---- 引擎(上)
[源码解析] PyTorch 分布式 Autograd (5) ---- 引擎(上) 目录 [源码解析] PyTorch 分布式 Autograd (5) ---- 引擎(上) 0x00 摘要 0x0 ...
- [源码解析] PyTorch 分布式 Autograd (6) ---- 引擎(下)
[源码解析] PyTtorch 分布式 Autograd (6) ---- 引擎(下) 目录 [源码解析] PyTtorch 分布式 Autograd (6) ---- 引擎(下) 0x00 摘要 0 ...
- [源码解析] PyTorch分布式优化器(2)----数据并行优化器
[源码解析] PyTorch分布式优化器(2)----数据并行优化器 目录 [源码解析] PyTorch分布式优化器(2)----数据并行优化器 0x00 摘要 0x01 前文回顾 0x02 DP 之 ...
- [源码解析] PyTorch 分布式 Autograd (3) ---- 上下文相关
[源码解析] PyTorch 分布式 Autograd (3) ---- 上下文相关 0x00 摘要 我们已经知道 dist.autograd 如何发送和接受消息,本文再来看看如何其他支撑部分,就是如 ...
随机推荐
- SQL点点滴滴_聪明的小写法(持续更新中)
1.生成序列号 SELECT number + 1 ,number FROM master..spt_values WHERE type = 'P' ORDER BY number 说明: maste ...
- sql server单个字段列转行由,隔开
SELECT STUFF((SELECT ','+字段名 FROM 表名 for xml path('')),1,1,'')
- [转] iOS文字排版(CoreText)那些事儿
文章转载自 http://www.cocoachina.com/applenews/devnews/2014/0521/8504.html iOS文字排版(CoreText)那些事儿 转自阿毛的蛋疼地 ...
- 工具类-vim在shell中卡死的情况
time:2015/11/35 在xshell下面使用vim编辑,有时候会出现突然卡死的情况.但是如果重新开一个终端的话,打开文件又是一大堆问题,今天又碰到了,搜了一下就找到一个帮助了[1] 原因:按 ...
- Redis学习---Redis操作之List
List操作,redis中的List在在内存中按照一个name对应一个List来存储 lpush(name,values) --> 实际上是左添加 # 在name对应的list中添加元素,每个新 ...
- PSR规范学习笔记
PSR已经经历了5次变革,如今PSR4就是最新的标准,但是还是有必要了解下5个版本的内容的,于是去php-fig网站看了下英文原版: 大概看了遍,发现这规范很多的必须很多时候只是建议,但是PHP解析器 ...
- GitBlit集成AD域LDAP
GitBlit的配置文件: gitlblit安装目录下的 /data/gitblit.properties ,用记事本或其他编译器打开即可. 集成AD域的LDAP操作步骤 打开配置文件,添加以下内 ...
- Java基础 之软引用、弱引用、虚引用 ·[转载]
Java基础 之软引用.弱引用.虚引用 ·[转载] 2011-11-24 14:43:41 Java基础 之软引用.弱引用.虚引用 浏览(509)|评论(1) 交流分类:Java|笔记分类: Ja ...
- Leuze BCL308i 使用方法整理
1 硬件连接关系 1.1 接口盒 BCL308i一般选配MK308/MK348/MK358系列接口盒, 单独使用(不组成扫描集群)时需要连接3根线,分别为SERVICE .SW/PWR.HOST/BU ...
- 个人技术博客二之apk反编译与加密
根据原文郭霖大神的博客Android安全攻防战,反编译与混淆技术完全解析 本人亲测反编译真的没有什么卵用,个人纯属好奇就去搜了一下,偷窃有罪,抄袭可耻. 1.手机上的apk都是打包好的,直接安装使用. ...