在一个请求到达的时候,最先达到的就是视图层,然后根据url映射到视图函数。这一部分我们来说明url的配置。

概述

为了给一个应用设计URL,你需要创建一个Python 模块,通常称为URLconf(URL configuration)。 这个模块是纯粹的Python 代码,包含URL 模式(简单的正则表达式)到Python 函数(你的视图)的简单映射。

映射可短可长,随便你。 它可以引用其它的映射。 而且,因为它是纯粹的Python 代码,它可以动态构造。

django如何处理请求

当一个用户请求Django 站点的一个页面,下面是Django 系统决定执行哪个Python 代码遵循的算法:

  1. Django 决定要使用的根URLconf 模块。 通常,这是ROOT_URLCONF设置的值,但是如果传入的HttpRequest对象具有urlconf属性(由中间件设置),则其值将被用于代替ROOT_URLCONF设置。
  2. Django 加载该Python 模块并寻找可用的urlpatterns。 它是django.conf.urls.url() 实例的一个Python 列表。
  3. Django 依次匹配每个URL 模式,在与请求的URL 匹配的第一个模式停下来。
  4. 一旦正则表达式匹配,Django将导入并调用给定的视图,该视图是一个简单的Python函数(或基于类的class-based view)。 视图将获得如下参数:
    • 一个HttpRequest 实例。
    • 如果匹配的正则表达式返回了没有命名的组,那么正则表达式匹配的内容将作为位置参数提供给视图。
    • 关键字参数由正则表达式匹配的命名组组成,但是可以被django.conf.urls.url()的可选参数kwargs覆盖。
  5. 如果没有匹配到正则表达式,或者如果过程中抛出一个异常,Django 将调用一个适当的错误处理视图。

在官网上有一个实例和说明,来说明url是怎么匹配的,如下:

from django.conf.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 这个字符串是“原始的” —— 字符串中任何字符都不应该转义。 #一些请求实例 /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 中的值并以位置 参数传递给视图。 在更高级的用法中,可以使用命名的正则表达式组来捕获URL 中的值并以关键字 参数传递给视图。

在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中name 是组的名称,pattern 是要匹配的模式。

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')
  • /articles/2003/03/03/ 请求将调用函数views.article_detail(request, year='2003', month='03', day='03')

需要注意的是,无论捕获的参数是什么类型,总是作为字符串传递给视图函数。譬如上面捕获了年份为整型,但是仍然是作为字符串传递的。

匹配/分组算法

下面是URLconf 解析器使用的算法,针对正则表达式中的命名组和非命名组:

  1. 如果有命名参数,则使用这些命名参数,忽略非命名参数。
  2. 否则,它将以位置参数传递所有的非命名参数。

URLconf的查找

请求的URL被看做是一个普通的Python 字符串, URLconf在其上查找并匹配。 进行匹配时将不包括GET或POST请求方式的参数以及域名。

例如,在https://www.example.com/myapp/的请求中,URLconf将查找myapp/

https://www.example.com/myapp/?page=3的请求中,URLconf将查找myapp/

URLconf 不检查使用了哪种请求方法。 换句话说,所有请求方法 - POSTGETHEAD等 - 将路由到同一个URL的相同功能。

通过一个实例,来说明上面的参数传递:

url映射如下:
url(r'^sign/([0-9]{4})/([0-9]{2})/$', sign), #传递位置参数
url(r'^sign/(?P<year>[0-9]{4})/(?P<mon>[0-9]{2})/(?P<day>[0-9]{2})/$', sign), #传递关键字参数 #视图函数如下:
def sign(request, year, mon, day="02"): #需要形参来接收url传递过滤的实参
return render(request, "sign.html", {"year": year, "month": mon, "day": day}) #前端代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试参数传递</title>
</head>
<body>
<h3>年份是: {{ year }}</h3>
<h3>月份是:{{ month }}</h3>
<h3>多少号:{{ day }}</h3>
</body>
</html>

错误处理

当Django 找不到一个匹配请求的URL 的正则表达式时,或者当抛出一个异常时,Django 将调用一个错误处理视图。

这些情况发生时使用的视图通过4个变量指定。 它们的默认值足以满足大多数项目,但可以通过覆盖其默认值进一步进行自定义。

Django中默认的错误视图对于大多数web应用已经足够了,但是如果你需要任何自定义行为,重写它很容易。 只要在你的根URLconf中指定下面的处理器(在其他任何地方设置它们不会有效)。

handler404覆盖了page_not_found()视图:
handler404 = 'mysite.views.my_custom_page_not_found_view'
handler500覆盖了server_error()视图:
handler500 = 'mysite.views.my_custom_error_view'
handler403覆盖了permission_denied()视图:
handler403 = 'mysite.views.my_custom_permission_denied_view'
handler400覆盖了bad_request()视图:
handler400 = 'mysite.views.my_custom_bad_request_view'

URL的扩展

当一个django工程中有多个app应用时,我们可以为每一个app单独设置其对应的url映射,然后再把对应app的urls.py文件包含在根urlconf中即可。

urlpatterns = [
url(r'^test', include("app01.urls")),
url(r'^bk', include("backend.urls")),
url(r'^cmdb', include("cmdb.urls")),
] #我们只需要在对应的app中定义urls.py文件即可,文件内容和根ruls.py文件类似。
#在根urlconf中捕获的任何参数,都可以传递给对应的子urlconf,进而可以传递给对应的视图函数。

URL传递额外的参数

urlpatterns = [
url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
] #这个实例中不仅传递了关键字参数year,还传递了后面大括号中的关键字残血foo="bar", url中使用include包含子url映射时,用法一样,可以直接跟在父url映射后,也可以直接跟在子url映射后面。

URL反向解析

在 Django 项目中经常需要获取最终形式的 URL,这么做是为了在生成的内容中嵌入 URL(视图和素材资源网址,呈现给用户的网址,等等), 或者用于在服务器端处理导航流程(重定向等)。

此时,一定不能硬编码 URL(费时、不可伸缩,而且容易出错), 或者参照 URL 配置创造一种生成 URL 的机制,因为这样非常容易导致线上 URL 失效。

换句话讲,我们需要的是一个 DRY 机制。 这种机制的一个优点是,当改进 URL 设计之后无需在项目源码中大范围搜索、替换失效的 URL。

Django 提供了一种方案,只需在 URL 映射中设计 URL。 我们为其提供 URL 配置,然后就可以双向使用:

  • 根据用户/浏览器发起的URL 请求,它调用正确的Django 视图,并从URL 中提取它的参数需要的值。
  • 根据Django 视图的标识和将要传递给它的参数的值,获取与之关联的URL。

第一种方式是我们在前面的章节中一直讨论的用法。 第二种方式叫做反向解析URL反向URL匹配反向URL查询或者简单的URL反查

在需要URL 的地方,对于不同层级,Django 提供不同的工具用于URL 反查:

  • 在模板中:使用url 模板标签。
  • 在Python代码中:使用reverse()函数。
  • 在更高层的与处理Django 模型实例相关的代码中:使用get_absolute_url() 方法。

上面摘自官网,直白一点,在form表单提交的时候action指向,我们不用再使用直接的url方式,而是在urlconf中给映射定义一个名字,然后再form表单中使用这个名字。有点就是当url映射关系更改时,只要名字不变,我们的form表单就不用更改。

一个简单的实例应用如下:

#url映射如下
url(r'^main/', main, name="enter_site"), #html代码中form提交如下:
<form action="{% url "enter_site" %}" method="post"> #注意格式的写法,名字要加上双引号。

在视图函数中,return返回的时候,要么返回的HttpResponse对象,要么返回的是经过render渲染过的html代码文件,还可以返回HttpResponseRedirect对象,指向一个url,而这个url就是在urlconf中配置的url,因此这里引用的时候我们可以直接返回url,也可以通过reverse函数返回。

urlconf中配置如下:
url(r'^info/', info, name="list_info"), 在视图函数中引用如下:
第一种直接引用url:
return HttpResponseRedirect("/info/")
第二种使用reverse函数:
from django.urls import reverse
return HttpResponseRedirect(reverse("list_info")) #这两种方法的返回是一样的,推荐使用第二种。

使用name还有一个好处就是,我们知道在url解析时,可能有多个url可以指向一个视图,这是可以的,但是在反解析时,就会出问题了同一个视图有两个结果进行匹配。因此我们引入了name函数,给每一个url定义一个名字,在反解析时使用名字即可。

上面提到过在一个django工程中可能会有很多app,每个app下的url映射可能是重名的,这样即便定义了name(因为name重名)也会出问题,因此引入了命名空间的概念。

以下实例:

#根urlconf配置
urlpatterns = [
url(r'^mysite/', include("mysite.urls", namespace="mysite")), ] #mysite应用中url配置
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^main/', main, name="enter_site"),
url(r'^info/', info, name="list_info"),
url(r'^sign/([0-9]{4})/([0-9]{2})/$', sign),
url(r'^sign/(?P<year>[0-9]{4})/(?P<mon>[0-9]{2})/(?P<day>[0-9]{2})/$', sign),
] #form表单中url配置
<form action="{% url "mysite:enter_site" %}" method="post">
#注意这里的格式,命名空间与url名字之间用冒号隔开。 #视图函数中的应用
return HttpResponseRedirect(reverse("mysite:list_info"))

django的url配置的更多相关文章

  1. Django里URL配置中name参数的作用

    先看一下URL配置,新增了如下内容: 修改视图views.py 增加一个页面 现在要求是在name页面里面增加一个链接,显示详细信息.修改name页面 这个功能实现了,可是之前添加的那个name参数是 ...

  2. Django中的 动态URL配置

    举个例子,一家在线书店会为每一本书提供一个URL,如:/books/243/./books/81196/. 让我们创建第三个视图来显示当前时间和加上时间偏差量的时间,设计是这样的: /time/plu ...

  3. Django之视图和URL配置

    1.在创建项目时,Django会自动创建URL配置,在urls.py文件中 文件的默认内容如下所示: """mysite URL Configuration The ur ...

  4. Django框架1——视图和URL配置

    三个命令 1.创建一个django项目 在cmd中:django-admin.py startproject project_name D:\python\django_site>django- ...

  5. 【二】Django 视图和url配置

    在新建的Django项目下,新建一个views的python文件,编辑如下代码 from django.http import HttpResponse def hello(request): ret ...

  6. 视图和URL配置

    视图和URL配置 实验简介 上一章里我们介绍了如何创建一个Django项目并启动Django的开发服务器.本章你将学到用Django创建动态网页的基本知识. 同时,也教会大家怎么在本地机器上建立一个独 ...

  7. python测试开发django-3.url配置

    前言 我们在浏览器访问一个网页是通过url地址去访问的,django管理url配置是在urls.py文件.当一个页面数据很多时候,通过会有翻页的情况,那么页数是不固定的,如:page=1.也就是url ...

  8. django(二)视图和URL配置

    创建一份视图: 在上一节,使用django-admin.py startproject制作的mysite文件夹中,创建一个叫做views.py的空文件.这个Python模块健柏寒这一章的视图. vie ...

  9. django中url路由配置及渲染方式

    今天我们学习如何配置url.如何传参.如何命名.以及渲染的方式,内容大致有以下几个方面. 创建视图函数并访问 创建app django中url规则 捕获参数 路径转换器 正则表达式 额外参数 渲染方式 ...

随机推荐

  1. IOT-web替换某一个前台版本

    比如 替换endpoint 1,首先改写 package.json文件,记得去掉^,改写成某一个版本 2.删除相应的内容 3.执行 npm install 4.最后 build

  2. Python爬虫常用模块安装

    安装:pip3 install requestspip3 install seleniumpip3 install bs4pip3 install pyquerypip3 install pymysq ...

  3. Pycharm进行版本管理

    即然pycharm为python提供了这么强大的IDE,那么,我们代码管理,没理由不用版本管理工具Git,SVN等等 在pychram中使用GitHub进行代码管理;需要准备: 1)GitHub帐号: ...

  4. 实验验证sys和system用户全库导出的区别

    我们在做逻辑数据泵全库导出的时候,有两种流行的写法,一种是sys用户导出,一种是使用system用户导出. 现在想知道二者之间有什么区别?实验验证之前不妨先思考一下: sys和system用户的权限区 ...

  5. 39.css3----button按钮点击时出现蓝色边框

    css控制Button 按钮的点击时候出现蓝色边框http://www.inbeijing.org/archives/1139 Button 按钮的点击时候出现蓝色边框的问题 添加css属性,这样在点 ...

  6. 利用css伪类编写冒泡小三角

    HTML代码 <div class="lf otherLogin"> <span>其他方式注册</span> <div class=&qu ...

  7. fang99-三号线与四号线新盘

    三号线与四号线新盘 http://www.fang99.com/buycenter/buildingsearch_map.aspx?projectid=0000011104 http://www.fa ...

  8. Mockito/PowerMockito Straige Issues

    http://blog.csdn.net/xiaoyaoyulinger/article/details/52415494 http://breezylee.iteye.com/blog/208843 ...

  9. mac快捷键留存查看

    基本的快捷键 Command是Mac里最重要的修饰键,在大多数情况下相当于Windows下的Ctrl.所以以下最基本操作很好理解: Command-Z 撤销 Command-X 剪切 Command- ...

  10. 详解Linux下iptables中的DNAT与SNAT设置(转)

    详解Linux下iptables中的DNAT与SNAT设置 这篇文章主要介绍了Linux下iptables中的DNAT与SNAT设置,是Linux网络配置中的基础知识,需要的朋友可以参考下   原文连 ...