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

在Django项目中编写路由,就是向外暴露我们接收哪些URL的请求,除此之外的任何URL都不被处理,也没有返回。通俗地理解,不恰当的形容,URL路由是你的Web服务对外暴露的API。

Django奉行DRY主义,提倡使用简洁、优雅的URL,没有.php.cgi这种后缀,更不会单独使用0、2097、1-1-1928、00这样无意义的东西,让你随心所欲设计你的URL,不受框架束缚。

一、概述

URL路由在Django项目中的体现就是urls.py文件,这个文件可以有很多个,但绝对不会在同一目录下。实际上Django提倡项目有个根urls.py,各app下分别有自己的一个urls.py,既集中又分治,是一种解耦的模式。

随便新建一个Django项目,默认会自动为我们创建一个/project_name/urls.py文件,并且自动包含下面的内容,这就是项目的根URL:

"""mysite URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin urlpatterns = [
url(r'^admin/', admin.site.urls),
]

前面一堆帮助性的文字,我们不用管,关键是默认导入了url和admin,然后有一条指向admin后台的url路径。

我们自己要编写的url路由,基本也是这个套路。

二、Django如何处理请求

当用户请求一个页面时,Django根据下面的逻辑执行操作:

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

三、简单示例

下面是一个简单的 URLconf:

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),
]

我们要编写的就是上面urlpatterns列表中的一条条url,每条url,都是urlpatterns列表的一个元素。先后顺序有重要关系,不能随意摆放。最后一条的末尾建议添加一个逗号。

urlpatterns中的每条正则表达式在第一次访问时被自动编译,因此其匹配速度是非常快的。

注意:

  • 若要从URL中捕获一个值,只需要在它周围放置一对圆括号。
  • 不需要添加前导的反斜杠,因为每个URL都有。 例如,应该是^articles而不是^/articles
  • 每个正则表达式前面的'r'是可选的但是建议加上。它告诉Python这个字符串是“原始的” —— 字符串中任何字符都不应该转义。

根据上面的urlconf,下面是一些请求的例子,以及它们将匹配到的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中的一些片段,作为参数,传递给处理请求的视图。

上面的示例使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL中的值并以位置参数的形式传递给视图。

可以使用命名的正则表达式组来捕获URL中的值并以关键字参数传递给视图。

在Python的正则表达式中,命名组的语法是(?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')
  • /articles/2003/03/03/请求将调用函数views.article_detail(request, year='2003', month='03', day='03')

在实际应用中,这让你的URLconf更加明晰且不容易产生参数顺序问题的错误。当然,这不是强制性的,也牺牲了一些简洁性。

针对命名组和非命名组:

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

五、URLconf匹配请求URL中的哪些部分

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

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

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

URLconf不检查使用何种HTTP请求方法,所有请求方法POST、GET、HEAD等都将路由到同一个URL的同一个视图。在视图中,才根据具体请求方法的不同,进行不同的处理。

六、URL中捕获的参数为字符串类型

每个捕获的参数都作为一个普通的Python字符串传递给视图,即便被捕获的‘100’看起来像个整数,但实际上是个字符串‘100’。 例如,下面这行URLconf中:

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

传递给views.year_archive()的year参数将是一个字符串,不是整数,即使[0-9]{4}只匹配整数字符串。

七、指定视图参数的默认值

有一个小技巧,我们可以指定视图参数的默认值。 下面是一个URLconf和视图的示例:

# URLconf
from django.conf.urls import url from . import views urlpatterns = [
url(r'^blog/$', views.page),
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
] # View (in blog/views.py)
def page(request, num="1"):
# Output the appropriate page of blog entries, according to num.
...

在上面的例子中,两个URL模式指向同一个视图views.page。但是第一个模式不会从URL中捕获任何值。 如果第一个模式匹配,page()函数将使用num参数的默认值"1"。 如果第二个模式匹配,page()将使用捕获的num值。

八、自定义错误页面

当Django找不到与请求匹配的URL时,或者当抛出一个异常时,将调用一个错误处理视图。错误视图包括400、403、404和500,分别表示请求错误、拒绝服务、页面不存在和服务器错误。它们分别位于:

  • handler400 —— django.conf.urls.handler400。
  • handler403 —— django.conf.urls.handler403。
  • handler404 —— django.conf.urls.handler404。
  • handler500 —— django.conf.urls.handler500。

这些值可以在根URLconf中设置。在其它app中的二级URLconf中设置这些变量无效。

Django有内置的HTML模版,用于返回错误页面给用户,但是这些403,404页面实在丑陋,通常我们都自定义错误页面。

首先,在根URLconf中额外增加下面的条目:

# URLconf
from django.conf.urls import url from . import views urlpatterns = [
url(r'^blog/$', views.page),
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
] # 增加的条目
handler400 = views.bad_request
handler403 = views.permission_denied
handler404 = views.page_not_found
handler500 = views.page_error

然后在,views.py文件中增加四个处理视图:

def page_not_found(request):
return render(request, '404.html') def page_error(request):
return render(request, '500.html') def permission_denied(request):
return render(request, '403.html') def bad_request(request):
return render(request, '400.html')

再根据自己的需求,创建404.html、400.html等四个页面文件,就可以了。

django URL路由基础的更多相关文章

  1. Django的URL路由基础

    一.概述 URL路由在Django项目中的体现就是urls.py文件,这个文件可以有很多个,但绝对不会在同一目录下.实际上Django提倡项目有个根urls.py,各app下分别有自己的一个urls. ...

  2. 第二章:视图层 - 1:URL路由基础

    路由的编写方式是Django2.0和1.11最大的区别所在.Django官方迫于压力和同行的影响,不得不将原来的正则匹配表达式,改为更加简单的path表达式,但依然通过re_path()方法保持对1. ...

  3. django url 路由设置技巧

    Django的url使用方法 利用Django开发站点.能够设计出很优美的url规则,假设url的匹配规则(包括正則表達式)组织得比較好,view的结构就会比較清晰.比較easy维护. 最简单的形式 ...

  4. Django URL (路由系统)

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

  5. django url路由参数错误

    出现错误: TypeError get() got an unexpected keyword argument 'teacher_id 出错原因: view类中,get方法获得了一个多余的额参数,这 ...

  6. URL路由系统-命名空间

    命名空间 1.工程Django下的urs.py from django.conf.urls import url,include from django.urls import path,re_pat ...

  7. python :Django url /views /Template 文件介绍

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

  8. day 66 Django基础二之URL路由系统

    Django基础二之URL路由系统   本节目录 一 URL配置 二 正则表达式详解 三 分组命名匹配 四 命名URL(别名)和URL反向解析 五 命名空间模式 一 URL配置 Django 1.11 ...

  9. day 53 Django基础二之URL路由系统

    Django基础二之URL路由系统   本节目录 一 URL配置 二 正则表达式详解 三 分组命名匹配 四 命名URL(别名)和URL反向解析 五 命名空间模式 一 URL配置 Django 1.11 ...

随机推荐

  1. [LeetCode] 133. Clone Graph_ Medium tag: BFS, DFS

    Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. OJ's ...

  2. Genymotion虚拟镜像下载慢或者失败的解决办法

    Genymotion虚拟镜像下载慢或者失败的解决办法 http://files2.genymotion.com/dists/8.0.0/ova/genymotion_vbox86p_8.0_18061 ...

  3. random随机数应用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Django初级手册5-自动化测试

    什么是自动化测试 每次更新完系统后,可自动进行测试,而不是手工从头测试一遍: 从长远和全局的角度看,测试能节约我们的时间: 测试是一种积极的行为,它能预防问题,而不仅仅是识别问题: 测试有助于代码美观 ...

  5. GNU

    1983年,理查德.斯托曼提出GNU计划(革奴计划),希望发展出一套完整的开放源代码操作系统来取代Unix,计划中的操作系统,名为GNU. 1989年,发表GNU通用公共许可协议(GPL).GPL条款 ...

  6. webp格式

    有时候你右键保存了一张图片,然后好气啊,打不开.这要么是webp格式,要么,,,,要么有问题啊. WebP格式,谷歌大法开发的一种旨在加快图片加载速度的图片格式.图片压缩体积大约只有JPEG的2/3, ...

  7. zw版【转发·台湾nvp系列Delphi例程】HALCON HistoToThresh1

    zw版[转发·台湾nvp系列Delphi例程]HALCON HistoToThresh1 procedure TForm1.Button1Click(Sender: TObject);var imag ...

  8. POJ3608

    计算两个凸包之间的最小距离,旋转卡壳法详解在旋转卡壳的用法之计算两个凸 包上的最近距离 #include <iostream> #include<cstdio> #includ ...

  9. 20154312 曾林 EXP9 Web安全基础

    目录 -0.webgoat Could not find source file -1.基础问题回答 -2.环境配置 -3.Injection Flaws ----3.1.Numeric SQL In ...

  10. ORTP编译为静态库的问题

    项目中需要用到ORTP,我采用的编译环境是 VC2013,当我在项目设置中将设置为静态库是,发现没有导出函数,比如在需要连接 oRTP.lib库时提示 找不到 ORTP_init; 解决办法是 :在O ...