本文主要是介绍Django URL调度详述,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
对高质量的 WEB 应用程序来说, 有一个干净优雅的 URL 调度机制是至关重要的. Django 允许你根据需要设计 URLs ,没有任何框架层的限制.不需要 .php 或 .cgi 扩展名, 也没有象 0,2097,1-1-1928,00 那样的丑陋东西.
参阅 WWW 的缔造者 Tim Berners-Lee 所写的 Cool URIs don't change, 这篇文章的主题就是为什么 URL 应该是干净并且便于使用的.
1 概述
要为一个应用程序设计 URLs, 要生成一个称为 URLconf (URL 配置) 的非正式的 Python 模块. 该模块为纯 Python 代码, 它的作用就是在 URL 模式(简单的正则表达式)及 Python 回调函数( 你的 views) 之间建立映射.
这个映射根本需要可以很短,也可以很长. 它能够引用其它的映射. 由于是纯 Python 代码, 就有能力动态的创建这种映射.
2 Django 如何处理一个请求 (request)
当用户请求一个页面时,通过以下运算法则决定执行哪一段 Python代码:
Django首先检查 settings file 中的 ROOT_URLCONF 设置. 这是一个表示 Python 导入 URLconf 需要的绝对路径字符串. 例如: "mydjangoapps.urls".
Django 载入这个 Python 模块并寻找变量 urlpatterns. 该变量是一个 django.conf.urls.defaults.patterns() 函数返回值格式的元素组成的列表.
Django 顺序处理每个 URL 模式, 直到找到一个与请求URL的相匹配的模式为止.
一旦匹配成功, Django 导入并调用对应的 view, 也就是相应的 Python 函数. 这个 view 函数会得到一个 request object 作为它的第一个参数, 在正则表达式匹配中得到的其它值也传递给 view 作为其它的参数.
3 例子
这里有一个 URLconf 的示例:
from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^articles/2003/$', 'news.views.special_case_2003'), (r'^articles/(d{4})/$', 'news.views.year_archive'), (r'^articles/(d{4})/(d{2})/$', 'news.views.month_archive'), (r'^articles/(d{4})/(d{2})/(d+)/$', 'news.views.article_detail'), )
注意:
from django.conf.urls.defaults import * 使得 patterns() 函数可用.
要从 URL 中捕获值, 用小括号将其括起来即可.
不要添加一个前导反斜线, 因为每个 URL 都有. 举例来说,写成 ^articles, 而不要写成 ^/articles.
每个正则表达式前面的 'r' 是可选的,不过我们推荐使用原始字符串来表达正则表达式.参阅 Dive Into Python's explanation.
请求示例:
一个 /articles/2005/03/ 请求将匹配列表中的第三个入口. Django 自动调用函数 news.views.month_archive(request, '2005', '03').
/articles/2005/3/ 不匹配任何一个 URL 模式,因为第三个入口要求月份必须是两位数.
/articles/2003/ 将与列表的第一个入口匹配, 而不是第二个.因为模式是按顺序处理的,第一个入口匹配成功即停止处理. 这是很好的特性,你可以方便的添加一些特定项.
/articles/2003 不匹配任何模式, 因为每个模式都要求以一个反斜线结尾.
/articles/2003/03/3/ 匹配最后一个模式. Django 自动调用函数 news.views.article_detail(request, '2003', '03', '3').
4 命名分组
上面的例子使用了简单的, 非命名的 正则表达式分组 (使用小括号) 来从 URL 中捕获传递给 view 函数的 位置相关的 参数. 作为高级一点的用法,可以使用 命名 正则表达式分组来捕获传递给 view 函数的 关键字 参数.
在 Python 正则表达式里, 命名分组的语法是 (?P pattern), 这里 name 是分组的名字而 pattern 是要匹配的模式.
下面用命名分组重写上面的例子:
urlpatterns = patterns('', (r'^articles/2003/$', 'news.views.special_case_2003'), (r'^articles/(?P d{4})/$', 'news.views.year_archive'), (r'^articles/(?P d{4})/(?P d{2})/$', 'news.views.month_archive'), (r'^articles/(?P d{4})/(?P d{2})/(?P d+)/$', 'news.views.article_detail'), )
上面的代码与前面的代码功能完全相同, 不过传递给 view 函数的不再是位置相关参数,而变成了关键字参数.比如:
页面请求 /articles/2005/03/ 会自动调用函数 news.views.month_archive(request, year='2005', month='03'), 而不是 news.views.month_archive(request, '2005', '03').
页面请求 /articles/2003/03/3/ 会自动调用函数 news.views.article_detail(request, year='2003', month='03', day='3').
实际上, 这意味着 URLconfs 更清晰,而且避免了参数顺序错误引发的 bug -- 定义 view 函数时不必特别在意参数的顺序.当然有些开发人员认为命名分组的语法很丑并且繁琐.
4.1 匹配/分组算法
下面是 URLconf 解析遵循的算法:
只要存在命名参数, 就使用命名参数,非命名参数将被忽略.否则将所有非命名参数顺序传递给 view 函数.
不论哪种情况, 它都会传递一些额外的关键字参数给 view 函数.参阅下文中的 "传递额外参数给 view 函数" .
5 URLconf 搜索依据
URLconf 根据请求 URL (作为标准 Python 字符串处理) 进行搜索. 不包括任何 GET 或 POST 参数,也不包括域名.
比如,页面请求 http://www.example.com/myapp/, URLconf 将查找 /myapp/.
对页面请求 http://www.example.com/myapp/?page=3, URLconf 将查找 /myapp/.
URLconf 不考虑请求的方法. 也就是说,同一 URL 不论使用何种请求方法 -- POST, GET, HEAD, 等等. -- 都会导向同一个 view 函数.
6 urlpatterns 变量的语法
urlpatterns 是一个 Python 列表, 格式与函数 django.conf.urls.defaults.patterns() 的返回值相同. 每个人都应该使用 patterns() 来创建 urlpatterns 变量.
习惯在 URLconf 的顶部使用 from django.conf.urls.defaults import * 语句, 这将导入以下对象到 URLconf:
6.1 patterns
是一个函数, 它接受一个 前缀 参数及任意个 URL 模式, 返回一个满足 Django 要求格式的 URL 模式的列表.
patterns() 的第一个参数 prefix 必须是一个字符串. 参阅下文中的 "The view prefix" .
其它的参数应该是下面格式的 tuple:
(regular expression, Python callback function [, optional dictionary])
... 这里 optional dictionary 是可选的. (参阅下文中的 传递额外参数给 view 函数 )
6.2 handler404
是一个 view 函数的字符串表示. 若没有任何 URL 模式匹配, 调用该 view 函数.
默认值为: 'django.views.defaults.page_not_found'. 通常没有必要修改这个默认值.
6.3 handler500
是一个 view 函数的字符串表示. 当发生服务器错误时调用该 view 函数. 当 view 代码发生运行时代码时会发生服务器错误..
默认值为: 'django.views.defaults.server_error'. 通常没有必要修改这个默认值.
6.4 include
是一个函数, 它接受一个指向另一个 URLconf 的 python 路径作为参数. 该路径应该被 "included" 到当前位置.参阅下文中的 Including other URLconfs .
7 在 URLs 中捕获文本要注意的问题
每个捕获的参数都以 Python 字符串的形式被发送给 view 函数作参数, 而不管正则表达式的匹配类型. 举个例子,下面的 URLconf 行:
(r'^articles/(?P d{4})/$', 'news.views.year_archive'),
... 传递给 news.views.year_archive() 的 year 参数会是一个字符串,而不是一个整数,尽管 d{4} 只匹配整数字符串.
一个小技巧是在 view 函数中为参数指定默认值. 下面是一个 URLconf 及 view 的例子:
# URLconf urlpatterns = patterns('', (r'^blog/$', 'blog.views.page'), (r'^blog/page(?P d+)/$', 'blog.views.page'), ) # View (in blog/views.py) def page(request, num="1"): # Output the appropriate page of blog entries, according to num.
在上面的例子里, 所有的 URL 模式指向同一个 view 函数 -- blog.views.page -- 不过第一个模式并不从 URL 中捕获任何值. 在匹配第一个模式时, page() 函数使用 num 参数的默认值: "1". 如果匹配第二个模式, page() 将使用从正则表达式中捕获的 num 值.
8 性能
一个 urlpatterns 中的每一个正则表达式都在其第一次被访问时编译, 这使得 Django URL 调度起来象闪电一样快!
9 view 前缀
你可在 patterns() 调用时指定一个通用的 view 前缀, 以减少代码重复.
下面是来自 Django overview 的一个 URLconf 示例:
from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^articles/(d{4})/$', 'myproject.news.views.year_archive'), (r'^articles/(d{4})/(d{2})/$', 'myproject.news.views.month_archive'), (r'^articles/(d{4})/(d{2})/(d+)/$', 'myproject.news.views.article_detail'), )
在这个例子里,每个 view 都有同样的前缀 -- 'myproject.news.views'.你可以利用 patterns() 函数的第一个参数来指定一个 view 前缀, 该前缀将应用在每一个 view 函数上.
下面重写上面的例子,两者对比一下,后者简明的多:
from django.conf.urls.defaults import * urlpatterns = patterns('myproject.news.views', (r'^articles/(d{4})/$', 'year_archive'), (r'^articles/(d{4})/(d{2})/$', 'month_archive'), (r'^articles/(d{4})/(d{2})/(d+)/$', 'article_detail'), )
注意不要放一个句点给前缀结尾 ("."). Django 能自动处理这一切.
10 包括其它的 URLconfs
在任意位置, urlpatterns 可以 "include" 其它的 URLconf 模块. This essentially "roots" a set of URLs below other ones.
举例来说, 下面是 Django website 的 URLconf. 它包括了一系列其它 URLconfs:
from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^weblog/', include('django_website.apps.blog.urls.blog')), (r'^documentation/', include('django_website.apps.docs.urls.docs')), (r'^comments/', include('django.contrib.comments.urls.comments')), )
注意上例中的正则表达式以一个反斜线而不是 $ 字符(表示字符串结束)结尾.只要 Django 遇到 include(), 它就在该点砍掉任何匹配的 URL 部分,并将剩余的部分发送到 URLconf 以进行下一步处理.
10.1 捕获参数
被包含的 URLconf 自动接收任何父 URLconfs 捕获的所有参数, 因此下面的例子是合法的:
# In settings/urls/main.py urlpatterns = patterns('', (r'^(?P w+)/blog/', include('foo.urls.blog')), ) # In foo/urls/blog.py urlpatterns = patterns('foo.views', (r'^$', 'blog.index'), (r'^archive/$', 'blog.archive'), )
在上面的例子里, 被捕获的 "username" 变量被传递给被包括的 URLconf, 就象预期的一样.
11 传递额外参数给 view 函数
URLconfs 允许以 Python 字典的形式传递额外的参数给 view 函数.
任何 URLconf tuple 都可以有可选的第三个元素, 一个传递给 view 函数的额外的字典参数.
示例:
urlpatterns = patterns('blog.views', (r'^/blog/(?P d{4})/$', 'year_archive', {'foo': 'bar'}), )
在这个例子里, 页面请求 /blog/2005/, Django 会自动调用 blog.views.year_archive() 函数, 并传递给它以下关键字参数:
year='2005', foo='bar'
该技术在 generic views 及 syndication framework 中得到了广泛应用, 用来传递元数据及选项给 view 函数.
相关热门文章
- python 自动化测试平台 Robot ...
- python 自动化测试平台 Robot ...
- python snmp 自动化2-在python...
- 自动化测试详细测试计划 模板...
- python snmp 自动化3-修改pyth...
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
这篇关于Django URL调度详述的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!