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程序设计入门(5)类的使用简介
Jun 16 Python
列举Python中吸引人的一些特性
Apr 09 Python
Python浅拷贝与深拷贝用法实例
May 09 Python
在Python中用has_key()方法查找键是否存在的教程
May 21 Python
在Python中操作日期和时间之gmtime()方法的使用
May 22 Python
分享一下Python 开发者节省时间的10个方法
Oct 02 Python
浅谈Python使用Bottle来提供一个简单的web服务
Dec 27 Python
flask中主动抛出异常及统一异常处理代码示例
Jan 18 Python
详解Python locals()的陷阱
Mar 26 Python
Python基于BeautifulSoup和requests实现的爬虫功能示例
Aug 02 Python
Python使用uuid库生成唯一标识ID
Feb 12 Python
python+selenium+PhantomJS抓取网页动态加载内容
Feb 25 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
DC宇宙的第一个英雄,堪称动漫史鼻祖,如今成为美国文化的象征
2020/04/09 欧美动漫
为php4加入动态flash文件的生成的支持
2006/10/09 PHP
在Win2003(64位)中配置IIS6+PHP5.2.17+MySQL5.5的运行环境
2016/04/04 PHP
php监测数据是否成功插入到Mysql数据库的方法
2016/11/25 PHP
YII框架中使用memcache的方法详解
2017/08/02 PHP
PHP生成推广海报的方法分享
2018/04/22 PHP
Jquery实现自定义弹窗示例
2014/03/12 Javascript
jQuery实现新消息闪烁标题提示的方法
2015/03/11 Javascript
JS中mouseover和mouseout多次触发问题如何解决
2016/06/06 Javascript
Three.js学习之文字形状及自定义形状
2016/08/01 Javascript
jQuery实现的简单排序功能示例【冒泡排序】
2017/01/13 Javascript
validationEngine 表单验证插件使用实例代码
2017/06/15 Javascript
基于Vue过渡状态实例讲解
2017/09/14 Javascript
微信小程序开发之IOS和Android兼容的问题
2017/09/26 Javascript
jQuery插件实现的日历功能示例【附源码下载】
2018/09/07 jQuery
在vue项目中使用Jquery-contextmenu插件的步骤讲解
2019/01/27 jQuery
使用JQuery自动完成插件Auto Complete详解
2019/06/18 jQuery
让 babel webpack vue 配置文件支持智能提示的方法
2019/06/22 Javascript
js判断在哪个浏览器打开项目的方法
2020/01/21 Javascript
Node.js中的异步生成器与异步迭代详解
2021/01/31 Javascript
[35:26]DOTA2上海特级锦标赛B组小组赛#2 VG VS Fnatic第三局
2016/02/26 DOTA
Python实现大文件排序的方法
2015/07/10 Python
python模块之sys模块和序列化模块(实例讲解)
2017/09/13 Python
python批量读取txt文件为DataFrame的方法
2018/04/03 Python
python 用 xlwings 库 生成图表的操作方法
2019/12/22 Python
基于python实现数组格式参数加密计算
2020/04/21 Python
pycharm激活码2020最新分享适用pycharm2020最新版亲测可用
2020/11/22 Python
Europcar英国:英国汽车和货车租赁
2017/01/21 全球购物
设计师珠宝:Ylang 23
2018/05/11 全球购物
幸福家庭事迹材料
2014/02/03 职场文书
合作协议书范本
2014/10/25 职场文书
2015年中学体育教师工作总结
2015/10/23 职场文书
初中团支书竞选稿
2015/11/21 职场文书
2016年百日安全生产活动总结
2016/04/06 职场文书
Elasticsearch6.2服务器升配后的bug(避坑指南)
2022/09/23 Servers
python如何利用cv2.rectangle()绘制矩形框
2022/12/24 Python