本站首页    管理页面    写新日志    退出


«October 2025»
1234
567891011
12131415161718
19202122232425
262728293031


公告
 本博客在此声明所有文章均为转摘,只做资料收集使用。

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:1304
评论数量:2242
留言数量:5
访问次数:7633290
建立时间:2006年5月29日




[Django]URL 调度程序
软件技术

lhwork 发表于 2007/2/3 13:46:54

目录 1   概述2   Django 如何处理一个请求 (request)3   例子4   命名分组4.1   匹配/分组算法 5   URLconf 搜索依据6   urlpatterns 变量的语法6.1   patterns6.2   handler4046.3   handler5006.4   include 7   在 URLs 中捕获文本要注意的问题8   性能9   view 前缀10   包括其它的 URLconfs10.1   捕获参数 11   传递额外参数给 view 函数 对高质量的 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<name>pattern), 这里 name 是分组的名字而 pattern 是要匹配的模式. 下面用命名分组重写上面的例子: urlpatterns = patterns('', (r'^articles/2003/$', 'news.views.special_case_2003'), (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'), (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'), (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\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<year>\d{4})/$', 'news.views.year_archive'), ... 传递给 news.views.year_archive() 的 year 参数会是一个字符串,而不是一个整数,尽管 \d{4} 只匹配整数字符串. 一个小技巧是在 view 函数中为参数指定默认值. 下面是一个 URLconf 及 view 的例子: # URLconfurlpatterns = patterns('', (r'^blog/$', 'blog.views.page'), (r'^blog/page(?P<num>\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.pyurlpatterns = patterns('', (r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),)# In foo/urls/blog.pyurlpatterns = 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<year>\d{4})/$', 'year_archive', {'foo': 'bar'}),) 在这个例子里, 页面请求 /blog/2005/, Django 会自动调用 blog.views.year_archive() 函数, 并传递给它以下关键字参数: year='2005', foo='bar' 该技术在 generic views 及 syndication framework 中得到了广泛应用, 用来传递元数据及选项给 view 函数.


阅读全文(2926) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 1.284 second(s), page refreshed 144817791 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号