在文章stark组件前戏中已经提到过,django的注册功能是通过AdminSite的单例进行组册的,所以在这里也可以进行单例模式。

class AdminSite(object):

    def __init__(self):
self._registry=[]
self.app_name='stark'
self.namespace='stark' def register(self,model_class,stark_class=None,prev=None): if not stark_class:
stark_class=BaseStark self._registry.append(ModelStarkMapping(model_class,stark_class(model_class,self,prev),prev))
#self._registry.append({'model':model_class,'stark_class':stark_class(model_class,self,prev),prev})
# for k,v in self._registry.items():
# print(k,v)0
"""
    之前
_registry={
'UserInfo':BaseStark(UserInfo,site) 封装UserInfo类和site
'Role':RoleStark(Role,site) 封装 Role类和site
}
""" def get_urls(self):
urlpatterns=[] for item in self._registry: #循环得到的是每一个ModelStarkMapping对象
app_label=item.model_class._meta.app_label
model_name=item.model_class._meta.model_name
if item.prev:
temp = path('%s/%s/%s/' % (app_label, model_name,item.prev), (item.stark_class.urls, None, None))
else:
temp = path('%s/%s/' % (app_label, model_name,), (item.stark_class.urls, None, None))
urlpatterns.append(temp)
return urlpatterns @property
def urls(self):
return self.get_urls(),self.app_name,self.namespace

可以看到之前_registry是一个字典,现在变成了一个列表,为什么要这样做呢?

(1)这是因为如果是字典的话,一个model只能注册一次,现在是model可以注册多次,只需要将model对应的类按照需要表换,这样在一个页面上来实现一个model不同的数据展示。

(2)pre前缀的功能是为了将不同model注册的url加以区别,如下所示:

site.register(models.Customer,PersonalCustomerStark,'per')
site.register(models.Customer,CustomerStark)

另外将一个个字典的内容封存为一个对象,这样取值方便,当然,字典也是没问题的。

class ModelStarkMapping(object):

    def __init__(self,model_class,stark_class,prev):
self.model_class=model_class
self.stark_class=stark_class
self.prev=prev

这就是注册功能的实现过程,接下来就是路由系统的构建。

可以看到上述在返回urlpatterns列表时,第二个元素是三个参数组成的元组,按理说应该是include()进行二级路由分发才对呀,其实这是include()方法的本质,在include()方法中返回的就是这么三个参数的元组。

def include(arg, namespace=None):
app_name = None
if isinstance(arg, tuple):
# Callable returning a namespace hint.
try:
urlconf_module, app_name = arg
except ValueError:
if namespace:
raise ImproperlyConfigured(
'Cannot override the namespace for a dynamic module that '
'provides a namespace.'
)
raise ImproperlyConfigured(
'Passing a %d-tuple to include() is not supported. Pass a '
'2-tuple containing the list of patterns and app_name, and '
'provide the namespace argument to include() instead.' % len(arg)
)
else:
# No namespace hint - use manually provided namespace.
urlconf_module = arg if isinstance(urlconf_module, str):
urlconf_module = import_module(urlconf_module)
patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
app_name = getattr(urlconf_module, 'app_name', app_name)
if namespace and not app_name:
raise ImproperlyConfigured(
'Specifying a namespace in include() without providing an app_name '
'is not supported. Set the app_name attribute in the included '
'module, or pass a 2-tuple containing the list of patterns and '
'app_name instead.',
)
namespace = namespace or app_name
# Make sure the patterns can be iterated through (without this, some
# testcases will break).
if isinstance(patterns, (list, tuple)):
for url_pattern in patterns:
pattern = getattr(url_pattern, 'pattern', None)
if isinstance(pattern, LocalePrefixPattern):
raise ImproperlyConfigured(
'Using i18n_patterns in an included URLconf is not allowed.'
)
return (urlconf_module, app_name, namespace)

include()

然后可以看看二级路由,在BaseStark这个基类中定义了二级路由。

...   
def get_urls(self):
urlpatterns = [
re_path('list/$', self.wrapper(self.changelist_view), name=self.get_list_url_name ),
re_path('add/$', self.wrapper(self.add_view), name=self.get_add_url_name),
re_path('(?P<pk>\d+)/change/$', self.wrapper(self.change_view), name=self.get_edit_url_name),
re_path('(?P<pk>\d+)/del/$', self.wrapper(self.del_view), name=self.get_del_url_name), ]
extra_urls = self.extra_urls() if extra_urls:
urlpatterns.extend(extra_urls) return urlpatterns def extra_urls(self): # 用于扩展url 返回的是一个列表,一次性扩展多个值
pass @property
def urls(self): return self.get_urls()
...

这样就完成了注册与路由构建。

最新文章

  1. [APUE]文件和目录(上)
  2. 二十五、JDK1.5新特性---枚举
  3. devexpress xaf 开发中遇到的问题.
  4. Javascript中构造函数与new命令2
  5. 谈谈Delphi中的类和对象1---介绍几个概念 &amp;&amp; 对象是一个地地道道的指针
  6. MySQL基础 - 如何系统地学习数据库?
  7. Bootstrap页面布局7 - Bootstrap响应式布局的实用类
  8. APMServ本地搭建网站最好用的软件
  9. (转)总结PLSQL的快捷键以及使用技巧
  10. Atitit.Gui控件and面板----数据库区-mssql 2008 权限 配置 报表查看成员
  11. MYSQL正式环境主从复制(不锁表,不停服务)
  12. poj 3487 稳定婚姻
  13. 【TensorFlow 官网 可以直接访问】让中国开发者更容易地使用TensorFlow打造人工智能应用
  14. web安全基础第一天
  15. button样式的demo
  16. 2PC(Two Phase Commitment Protocol)原理
  17. 认识socket
  18. plink: 等位型计数(allele count)
  19. nginx_upstream_check_module监控后端服务器http
  20. Cenos6.6 升级 python3.5.2 安装配置 django1.10

热门文章

  1. 【爬坑系列】之解读kubernetes的认证原理&amp;实践
  2. 暴力 Codeforces Round #183 (Div. 2) A. Pythagorean Theorem II
  3. 题解报告:hdu 1159 Common Subsequence(最长公共子序列LCS)
  4. 题解报告:hdu 1166 敌兵布阵(线段树or树状数组)
  5. ORA-28002错误原因及解决办法
  6. YUM报错及解决办法
  7. AJPFX简述可变参数概述和使用
  8. 【JavaScript】随机生成10个0~100的数字
  9. 关于Android软键盘把布局顶上去的问题(一)
  10. iOS微信页面 长按图片出现【存储图像】和【拷贝】不出现【发送朋友】【保存图片】