Django 路由控制的实现代码


Posted in Python onNovember 08, 2018

一、URL路由基础

URL是web服务的路口,用户通过浏览器发送过来的任何请求都会被发送到一个指定的URL地址里,然后被响应。

在django项目中编写路由就是向外暴露我们接收哪些URL的请求,除此之外任何的URL都不会被处理,URL路由就是web服务对外暴露的API

二、Django处理请求

确定要使用的 URLconf 模块,通常是settings中 ROOT_URLCONF 设置的值,如果传入的 HttpRequest 对象具有 urlconf 属性(中间件设置),则使用其值代替settings中 ROOT_URLCONF

Django加载模块并查找可用的 urlpatterns ,它是 django.conf.urls.url() 实例的一个列表

按顺序运行每个URL模式,匹配成功就停下来,所以 顺序很关键

匹配成功导入给定的视图,它是一个python函数,或基于类的视图,视图将获得如下参数

  • 一个HttpRequest实例
  • 如果匹配的正则表达式返回了无名分组,那么它将作为位置参数提供给视图
  • 关键字参数由正则的有名分组组成,但是可以被django.conf.urls.url()的可选参数kwargs覆盖

如果没有URL模式匹配,或者过程出错了,将调用错误处理视图

三、简单的路由配置
from django.conf.urls import url

urlpatterns=[
  url(正则表达式,view视图函数,参数,别名)
]

示例的URLconf:

from django.urls import url

from . import views

urlpatterns = [
  url(r'^articles/2003/$', views.special_case_2003),
  url(r'^articles/([0-9]{4})/$', views.year_archive),
  url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
  url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

注:

  • 从URL中捕获一个值,可以加园括号或者尖括号
  • 不要添加前导的防斜杠,因为每个URL都有,例如,应该是 ^articles 而不是 ^/articles
  • 每个正则表达式前面的'r'是可选的,建议添加上,它告诉python这个字符串中的任何字符都不应该被转义

请求的例子及匹配的url

/articles/2005/03/将匹配列表中的第三个模式。Django将调用函数views.month_archive(request, '2005', '03')。
/articles/2005/3/不匹配任何URL模式,因为列表中的第三个模式要求月份是两个数字。
/articles/2003/将匹配列表中的第一个模式不是第二个,因为模式按顺序从上往下匹配,第一个会首先被匹配。Django会调用函数views.special_case_2003(request)
/articles/2003不匹配任何一个模式,因为每个模式都要求URL以一个斜杠结尾。
/articles/2003/03/03/将匹配最后一个模式。Django将调用函数views.article_detail(request, '2003', '03', '03')。

是否开启URL访问地址后面 不为/跳转至带有/路径的配置项

APPEND_SLASH=True

Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加'/'。

四、有名分组

有名分组的语法是 (?P<name>pattern) ,其中name是组的名字,pattern是匹配的模式

使用有名分组重写上面的URLconf:

from django.conf.urls import url

from . import views

urlpatterns = [
  url(r'^articles/2003/$', views.special_case_2003),
  url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
  url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
  url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]

注:捕获的值作为关键字参数而不是位置参数传递给视图函数。

/articles/2005/03/ 请求将调用 views.month_archive(request, year='2005', month='03') 函数,而不是 views.month_archive(request, '2005', '03') 。

五、无名分组有名分组总结

1.无名分组

按位置传参

分组之后,将分组好的数据当做位置传参到视图函数,所以视图函数需要定义形参

示例:

​ url: (r'^articles/([0-9]{4})/([0-9]{2})$', views.article_detail)

​ 视图函数: def article_detail(request,*args)

2.有名分组

按关键字传参

分组后,会把分组出来的数据当做关键字参数传到视图函数,所以视图函数需要定义形参,形参名字和分组的名字相对应,与顺序无关

示例:

​ url: (r'^articles/(?P<year>[0-9]{4})/(?P<mounth>[0-9]{2})/$', views.article_detail),

​ 视图函数: def article_detail(request,mounth,year)

注:有名分组和无名分组最好不要混用

六、反向解析

在django项目中,一个常见的需求是获得URL的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向)。不希望通过硬编码URL

Django提供了一种解决方案,只需在URL中提供一个name参数,并赋值一个你自定义的、好记的、直观的字符串。

  • 在模板中:使用url模板标签
  • 在python代码中,使用reverse()函数

示例:

url配置:

  • 无参数:url(r'^publishadd111/$',views.publishadd,name='ddd'),
  • 无名分组:url(r'^publishadd/([0-9]{4})/([0-9]{2})/$', views.publishadd,name='ddd'),
  • 有名分组:url(r'^publishadd/(?P<year>[0-9]{4})/(?P<mounth>[0-9]{2})/$',views.publishadd,name='ddd'),

模板层:

  • 无参数: {% url 'ddd' %}
  • 无名分组: {% url 'ddd' 2018 12 %} 空格隔开,传多个值
  • 有名分组: {% url 'ddd' 2018 12 %} 还可以 {% url 'ddd' year=2018 mounth=12 %}

视图层:

from django.shortcuts import reverse
  • 无参数: url=reverse('ddd')
  • 无名分组: url=reverse('ddd',args=(2018,12,))
  • 有名分组: url=reverse('ddd',args=(2018,12,)) 还可以 url=reverse('ddd',kwargs={'year':2018,'mounth':12})

七、路由分发

在每个app里各自创建一个urls.py路由模块,然后从根路由出发,将app所属的url请求全部转发到相应的urls.py模块中。

Django1.1版本的分发

from django.conf.urls import url,include

例子:

总路由:

  • -from django.conf.urls import include
  • -url(r'^blog/',include('blog.urls')),
  • -url(r'^app01/',include('app01.urls')),

各自路由配置url

  • app01--url(r'^publish/$', views.publish,name='app01_test'),
  • blog--url(r'^blogtest/$', views.test,name='blog_test'),

路由分发使用的是include()方法,需要提前导入,他的参数是转发目的地地路径的字符串。

重点:总路由后面不能加 $

两个不同的app,在各自的urlconf中为某一条url取了相同的name,这就会带来麻烦。为了解决这个问题,又引出了下面的命名空间。

八、命名空间

由于name没有作用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,立即返回。URL命名空间可以保证反查到唯一的URL,即使不同的app使用相同的URL名称。

示例:

urls.py

url(r'^blog/',include('blog.urls')),
url(r'^app01/',include('app01.urls')),

blog的urls.py

url(r'^blogtest/$', views.test,name='test'),

app01的urls.py

url(r'^publish/$', views.publish,name='test'),

blog的视图函数

def test(request):
  url=reverse('test')
  return HttpResponse('blog test)

app01的视图函数

def test(request):
  url=reverse('test')
  return HttpResponse('app01 test)

无论如何找index都是找的app01的index。

解决方法:在总路由分发的时候指定名称空间,实现命名空间的做法很简单,在urlconf文件中添加 namespace='xxx' 即可。

url(r'^blog/',include('blog.urls',namespace='blog')),
url(r'^app01/',include('app01.urls',namespace='app01')),

在视图函数反向解析的时候,指定是哪个名称空间下的

url = reverse('blog:test')

在模板里也指定是

{% url 'blog:test'%}

不是很推荐使用名称空间,推荐的是在子路由的name中加入app的前缀

url(r'^publish/$', views.publish,name='app01_test'),

九、伪静态

和真静态URL类似。他是通过伪静态规则把动态URL伪装成静态网址。

在urls.py文件中自己添加匹配 .html

url(r'^book/(?P<id>\d+.html)',views.book),

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python使用xmlrpc实例讲解
Dec 17 Python
python 多进程通信模块的简单实现
Feb 20 Python
Python中logging模块的用法实例
Sep 29 Python
Python中使用装饰器时需要注意的一些问题
May 11 Python
Python的Django中django-userena组件的简单使用教程
May 30 Python
Python实用技巧之列表、字典、集合中根据条件筛选数据详解
Jul 11 Python
Python入门Anaconda和Pycharm的安装和配置详解
Jul 16 Python
使用django和vue进行数据交互的方法步骤
Nov 11 Python
Python获取统计自己的qq群成员信息的方法
Nov 15 Python
利用matplotlib实现根据实时数据动态更新图形
Dec 13 Python
python之openpyxl模块的安装和基本用法(excel管理)
Feb 03 Python
python如何获取网络数据
Apr 11 Python
Python求两个圆的交点坐标或三个圆的交点坐标方法
Nov 07 #Python
在Python中分别打印列表中的每一个元素方法
Nov 07 #Python
对python中数组的del,remove,pop区别详解
Nov 07 #Python
对Python中plt的画图函数详解
Nov 07 #Python
python使用matplotlib绘制热图
Nov 07 #Python
Django objects的查询结果转化为json的三种方式的方法
Nov 07 #Python
Python将一个Excel拆分为多个Excel
Nov 07 #Python
You might like
无数据库的详细域名查询程序PHP版(1)
2006/10/09 PHP
一个php作的文本留言本的例子(三)
2006/10/09 PHP
php一个文件搞定微信jssdk配置
2016/12/12 PHP
php图形jpgraph操作实例分析
2017/02/22 PHP
Laravel5框架添加自定义辅助函数的方法
2018/08/01 PHP
IE与firefox下Dhtml的一些区别小结
2009/12/02 Javascript
让IE8支持DOM 2(不用框架!)
2009/12/31 Javascript
对javascript的一点点认识总结《javascript高级程序设计》读书笔记
2011/11/30 Javascript
js自定义鼠标右键的实现原理及源码
2014/06/23 Javascript
js获取数组的最后一个元素
2015/04/14 Javascript
jQuery实现鼠标经过提示信息的地图热点效果
2015/04/26 Javascript
javascript实现别踩白块儿小游戏程序
2015/11/22 Javascript
javascript for-in有序遍历json数据并探讨各个浏览器差异
2015/11/30 Javascript
jQuery入门之层次选择器实例简析
2015/12/11 Javascript
jQuery Dialog对话框事件用法实例分析
2016/05/10 Javascript
javascript实现起伏的水波背景效果
2016/05/16 Javascript
JS实现拖动滚动条评分的效果代码分享
2016/09/29 Javascript
解析JavaScript数组方法reduce
2016/12/12 Javascript
基于JavaScript实现本地图片预览
2017/02/08 Javascript
Node.js中多进程模块Cluster的介绍与使用
2017/05/27 Javascript
VUE中使用Vue-resource完成交互
2017/07/21 Javascript
vue 修改 data 数据问题并实时显示的方法
2018/08/27 Javascript
基于mpvue小程序使用echarts画折线图的方法示例
2019/04/24 Javascript
浅谈在vue-cli3项目中解决动态引入图片img404的问题
2020/08/04 Javascript
nodejs+express最简易的连接数据库的方法
2020/12/23 NodeJs
python+tkinter编写电脑桌面放大镜程序实例代码
2018/01/16 Python
pyqt5 QProgressBar清空进度条的实例
2019/06/21 Python
python代码编写计算器小程序
2020/03/30 Python
python 浅谈serial与stm32通信的编码问题
2019/12/18 Python
Python concurrent.futures模块使用实例
2019/12/24 Python
Virtualenv 搭建 Py项目运行环境的教程详解
2020/06/22 Python
Django url 路由匹配过程详解
2021/01/22 Python
Html5实现移动端、PC端 刮刮卡效果
2016/06/30 HTML / CSS
Unix如何在一行中运行多个命令
2015/05/29 面试题
教师暑期培训感言
2014/08/15 职场文书
Win11局域网共享权限在哪里设置? Win11高级共享的设置技巧
2022/04/05 数码科技