一、路由系统理解

系统功能:根据用户访问的不同url,执行对应的视图函数。

web服务器可以根据用户访问的url地址的不同,返回相应的html页面,而html的页面渲染由视图函数处理,这就需要有一个模块负责分析用户访问的url地址,并根据预先定义的映射规则,将请求分发到不同的视图函数中进一步处理,负责这个工作的模块就是web框架中的路由系统。路由系统的工作总结起来就是:制定路由规则,分析url,分发请求到响应视图函数中

路由系统的路由功能基于路由表,路由表是预先定义好的url和视图函数的映射记录,换句话说,可以理解成将url和视图函数做了绑定,映射关系有点类似一个python字典:

url_to_view_dic = {
'路径1': view_func_1,
'路径2': view_func_2,
'路径n': view_func_n,
...
}

路由表的建立是控制层面,需要在实际业务启动前就准备完毕,即:先有路由,后有业务。

一旦路由准备完毕,业务的转发将会完全遵从路由表的指导:

去往路径1的request --> 被路由器分发到view_func_1函数处理
去往路径2的request --> 被路由器分发到view_func_2函数处理
去往路径n的request --> 被路由器分发到view_func_n函数处理
...

二、路由系统功能划分

路由系统的本质功能是:指路,针对一次路由请求,返回下一跳转发地址。

任何路由系统都将涵盖至少如下两个核心功能:

路由器的核心功能:(非常重要!!!!)

1、创建路由表(控制层面) ----> 用户定义

2、路由分发(转发层面) ----> django框架自动处理


三、路由表创建

创建工具

django框架中的工具:re_pathpath

所有的web请求都将以django项目目录下的urls.py文件作为路由分发主入口,所以如果要完成最简单的路由功能,只需要在此文件中预先配置好路由表即可。re_pathdjango v1的工具,pathdjango v2的工具,后者兼容前者。

# 项目urls.py文件, 目前两种工具可以任选使用
re_path(r'home/', views.index)
path('articles/<int:id>', views.show_article)

路由的匹配顺序是自上而下,一旦匹配即执行对应视图函数,便不再继续匹配

所以路由表条目的顺序很重要,有严格要求的路径应该放前面,宽松要求甚至可以聚合的路径应该放后面。匹配成功后的视图函数以如下形式执行:

# 执行接口: view_func(request, *args, **kw)
# 参数是固定的request对象以及由re_path或path捕获的无名分组/有名分组参数 views.index(request)
views.show_article(request, id)

如下是一张简单的路由表配置:

# urls.py文件

urlpatterns = [
# 自带后台管理页面路由
path('admin/', admin.site.urls), # 新增
re_path(r'^add/author/$', views.add_author),
re_path(r'^add/book/$', views.add_book), # 删除
re_path(r'delete/author/(\d+)', views.delete_author),
re_path(r'delete/book/(\d+)', views.delete_book), # 修改
re_path(r'edit/author/(\d+)', views.edit_author),
re_path(r'edit/book/(\d+)', views.edit_book),
]

特别注意1,django路由系统只会针对url进行匹配,并不会再额外考虑method或者其他request中的属性,这也意味着仅仅只需考虑url即可。(当然,我觉得后续如有需要,可以增加匹配因子,以便做到更精准的匹配)

特别注意2,在浏览器中访问某一个url,如果路径结尾没有添加/,在django框架中会被自动添加结尾的/。在路由表中,匹配路径的时候要关注/,即:re_path(r'home/'),换句话说,可以认为在django的环境下,路径pathinfo是必须有后导/的。


二级路由

二级路由的意思就是把项目urls文件中的路由整理划分,分布到各自的应用目录urls文件中,以此实现:

1、降低项目urls路由文件中路由数量,由各自应用urls路由文件承担

2、解耦整个项目的路由表,出现路由问题的时候可以单独在二级路由表中处理

3、多级路由以树形结构执行查询,在路由数量很大的时候,可以比单路由表有更快的查询速度

include实现二级路由表,二级路由会将在一级路由匹配到的url截断后再发送给子路由表继续匹配。以如下一级路由表为例,如果服务器收到一个http://www.xxx.com:8080/game/user/add/?name=a&pswd=b的请求,首先会匹配一级路由表中的game/并将截断后的user/add/发送到二级路由表继续匹配。

re_path(r'game/', include('game_app.urls')),
re_path(r'chat/', include('chat_app.urls')),
re_path(r'vidio/', include('vidio_app,urls'),

路由别名

因为路由url会被频繁引用,所以会带来修改时工作量过大的问题,解决办法是启用一个别名来代替url原始url,在所有引用的地方使用别名,这样原始url不论如何修改,都会被正确指向。当然,这个前提是,别名不能发生修改,否则同样要变动所有引用此别名的地方,所以别名的定义非常重要。此外,路由别名的作用域是全局,它是一个全局变量,这也意味着使用路由别名也有重名覆盖的风险。

使用路由别名的目的是获取原始url,如果原url有动态部分,需要在解析的时候传入对应参数来明确动态部分。

路由别名重名覆盖风险的解决方法:

1、在全局urls中定义每一个二级路由的namespace

2、在每一个二级路由urls中定义app_name

3、在别名定义的时候加上区分前缀如:app01-home, app02-home

别名的使用场景:

# 在模板中使用:
{% url '别名' *args, **kw %} # 在视图函数中使用:
reverse('别名', *args, **kw)

动态路由及重定向

动态路由

所谓的动态路由,其实就是聚合大量同类的url,并用re规则执行匹配并获取动态数据部分。

# re_path:
re_path(r'articles/(?P<id>\d+)'), show_article) ---> show_article(request, id=id) # path:
path('articles/<int:id>', show_article) ---> show_article(request, id=id)

重定向

return redirect(某一个具体网址,可来自于反向解析的结果)


四、自定义错误页面

固定流程如下:

settings.pyDEBUG改为FalseALLOWD_HOSTS改为['*']

templates中新建对应的404.html, 500.html

urls中定义:

handler404 = views.page_not_found
handler500 = views.server_error

views中配置对应函数:

def page_not_found(request):
return render(request, '404.html') def server_error(request):
return render(request, '500.html')

五、图示路由系统在框架中的定位

每次请求到服务器,执行路由的流程图

伪代码实现以上图示

# 启动路由分发过程
def route(environ, route_table):
url = environ.url
view_func = None # 遍历路由表
for map in route_table:
if url == map[0]:
view_func= map[1]
break return view_func # 执行视图函数处理过程
def start_handle(environ, view_func):
if view_func:
return view_func(environ)
else:
return page_not_found(environ) # web服务器主循环
def run():
# 循环处理每一次的请求
while True:
# 从tcp中获取当前客户端请求的http字节数据
request_bytes = server.recv(1024) # 根据http协议解析,得到http数据
request_http_data = http_parse(request_bytes.decode('utf-8')) # web框架进一步处理http数据,封装成方便使用的environ对象
environ = build_environ(request_http_data) # 根据当前请求的url,在路由表中找到对应的视图函数 ---> 路由系统的工作界面
view_func = route(environ, route_table) # 启动视图函数,处理当前请求的具体内容, 返回处理结果
response = start_handle(environ, view_func) # 按照http协议拆解web框架封装好的response对象,得到http字符串
response_http_data = http_encapsulation(response) # 发送http字节数据给客户端
server.send(response_http_data.encode('utf-8')) if __name__ == '__main__':
run()

六、路由系统的进阶想法

进阶考虑:

路由器收到请求request后,转发到后端另一台机器上执行,然后使用协程异步,处理其他的reqeust请求。如果请求得到的响应,再切换回协程,然后执行响应。这样可以实现入口服务器作为所有请求的承接者,然后转发到对应的后面不同业务服务器处理各自的业务,可以把业务分离到不同的机器上,而且此时入口服务器也可以处理并发请求。

即:多个服务器上均部署django,多台服务器之间的django可以相互通信,这样可以实现一个类似服务器集群的效果,可以完成负载均衡和备份的效果。

django框架--路由系统的更多相关文章

  1. Django框架----路由系统(详细)

    Django的路由系统 Django 1.11版本 URLConf官方文档 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表. ...

  2. python 之 Django框架(路由系统、include、命名URL和URL反向解析、命名空间模式)

    12.36 Django的路由系统 基本格式: from django.conf.urls import url urlpatterns = [ url(正则表达式, views视图函数,参数,别名) ...

  3. Django框架----路由系统、视图和模板(简单介绍)

    一.路由配置系统(urls) URL配置(URLconf)就像Django所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表: 你就是以这种方式告诉Django,对于这个URL ...

  4. Python学习(三十一)—— Django之路由系统

    转载自:http://www.cnblogs.com/liwenzhou/p/8271147.html Django的路由系统 Django 1.11版本 URLConf官方文档 URL配置(URLc ...

  5. Django之路由系统 Dj

    Django之路由系统   Django的路由系统 Django 1.11版本 URLConf官方文档 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调 ...

  6. Django 基础 路由系统

    Django框架简介 MVC框架和MTV框架(了解即可) MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图 ...

  7. 6月19日 python学习总结 Django之路由系统

    Django之路由系统   Django的路由系统 Django 1.11版本 URLConf官方文档 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调 ...

  8. Django之 路由系统

    Django的路由系统 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于这个URL调用这 ...

  9. Django 的 路由系统

    Django 的路由系统 URL 配置(URLconf)就像Django 锁支撑网站的目录. 它的本质就是URL 与要为该URL 调用的视图函数之间的映射表. 你就是以这种方式告诉Django, 对于 ...

随机推荐

  1. flask_数据库

    我们将使用 Flask-SQLAlchemy扩展来管理我们应用程序的数据.这个扩展封装了SQLAlchemy 项目,这是一个 对象关系映射器 或者 ORM.ORMs 允许数据库应用程序与对象一起工作, ...

  2. 学习前端的菜鸡对JS的call,apply,bind的通俗易懂理解

       call,apply,bind 在JavaScript中,call.apply和bind是Function对象自带的三个方法,都是为了改变函数体内部 this 的指向.            a ...

  3. Git客户端命令总结

    一:常用命令 1.先进入项目目录,然后git init:则会为此 项目/目录 创建一个本地仓库(或重新初始化这个本地仓库),可以用ls -a ./看到多了.git目录: 或者git init /hom ...

  4. (网络流) Island Transport --Hdu -- 4280

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=4280 源点是West, 汇点是East, 用Dinic带入求就好了 代码:要用c++提交 #pragma ...

  5. DFS剪枝处理HDU1010

    http://acm.hdu.edu.cn/showproblem.php?pid=1010 题意很好理解,不是最短路,而是dfs,虽然地图不算大,稍微注意一点的dfs也能险过,但是700+ms和78 ...

  6. Redis 慢查询

    Redis 慢查询   许多存储系统提供慢查询日志帮助开发和运维人员定位系统的慢操作.慢查询日志就是系统在命令执行前后计算每条命令的执行时间,当超过预设阈值就将这条命令的相关信息记录下来Redis提供 ...

  7. SMINT:单页网站的免費jQuery插件

    最近为了做一个静态网页版的数据报告,不希望花很多时间去设计网页,或者花时间去调整布局,于是找到了一个名为Smint的免費jQuery插件.几乎不需要写什么代码就可以完成一个一页式网站.这非常适合用来制 ...

  8. ClsoSee(v2) Alpha测试中!这是一个临时的帮助页面...

    Clso See 测试中,最新的更新信息会显示在这里,欢迎您随时关注新版本动态. 您可以单击这里让程序打开本地帮助文件(新说明.txt) 等程序完成后,会制作专门的帮助页面. 因为采用了键盘Hook技 ...

  9. 【mysql】使用Navicat连接数据库

    1 连接数据库 点击左下角测试一下 提示 输入 select host,user,plugin,authentication_string from mysql.user; 查看用户信息 注意这里我们 ...

  10. Windows下安装NTP服务器

    NTP服务器介绍 NTP服务器[Network Time Protocol(NTP)]是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高 ...