[Django入门知识浅介]用Django实现动态URL

        注:以下内容转载自 现代魔法学院 网站的 用Django实现动态URL 一文,仅供学习使用。

       前一小节学习了如何用 Django 做动态页面,就是用 Python 显示实时时间。但是是不是觉得这样的动态页面不太实际?一般的 URL 形如 http://www.nowamagic.net/librarys/topics/detail/188 这样的,如何用 Django 实现这种动态 URL 呢?

       这里我们来尝试下实现这样的 URL 。还是先上程序,再解释。

       程序实现

       我们创建第三个视图来显示当前时间和加上时间偏差量的时间,设计是这样的: /time/plus/1/ 显示当前时间+1个小时的页面 /time/plus/2/ 显示当前时间+2个小时的页面 /time/plus/3/ 显示当前时间+3个小时的页面,以此类推。

       1. urls.py

from django.conf.urls,defaults import *
from views import hours_ahead

urlpatterns = patterns('',
	('^time/plus/(\d{1,2})/$', hours_ahead),
)

       2. views.py

from django.http import Http404, HttpResponse
import datetime

def hours_ahead(request, offset):
	offset = int(offset)
	dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
	html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)
	return HttpResponse(html)

       现在访问 http://127.0.0.1:8000/time/plus/3/,比实际时间多了 3 小时。OK,程序通过。

       程序解释

       新手可能会考虑写不同的视图函数来处理每个时间偏差量,URL配置看起来就象这样:

urlpatterns = patterns('',
    ('^time/plus/1/$', one_hour_ahead),
    ('^time/plus/2/$', two_hours_ahead),
    ('^time/plus/3/$', three_hours_ahead),
    ('^time/plus/4/$', four_hours_ahead),
)

       很明显,这样处理是不太妥当的。不但有很多冗余的视图函数,而且整个应用也被限制了只支持预先定义好的时间段,2小时,3小时,或者4小时。如果哪天我们要实现5小时,我们就不得不再单独创建新的视图函数和配置URL,既重复又混乱。我们需要在这里做一点抽象,提取一些共同的东西出来。

       那么,我们如何设计程序来处理任意数量的时差?答案是:使用通配符(wildcard URLpatterns)。正如我们之前提到过,一个 URL 模式就是一个正则表达式。因此,这里可以使用d+来匹配1个以上的数字。

urlpatterns = patterns('',
    # ...
    (r'^time/plus/\d+/$', hours_ahead),
    # ...
)

       这个URL模式将匹配类似 /time/plus/2/ , /time/plus/25/ ,甚至 /time/plus/100000000000/ 的任何URL。更进一步,让我们把它限制在最大允许99个小时,这样我们就只允许一个或两个数字,正则表达式的语法就是 \d{1,2} :

(r'^time/plus/\d{1,2}/$', hours_ahead),

       另外一个重点,正则表达式字符串的开头字母“r”。它告诉 Python 这是个原始字符串,不需要处理里面的反斜杠(转义字符)。 在普通Python字符串中,反斜杠用于特殊字符的转义。比如n转义成一个换行符。 当你用 r 把它标示为一个原始字符串后,Python不再视其中的反斜杠为转义字符。也就是说,“n”是两个字符串:“”和“n”。由于反斜杠在 Python 代码和正则表达式中有冲突,因此建议你在 Python 定义正则表达式时都使用原始字符串。从现在开始,本文所有 URL 模式都用原始字符串。

       现在我们已经设计了一个带通配符的 URL,我们需要一个方法把它传递到视图函数里去,这样我们只用一个视图函数就可以处理所有的时间段了。我们使用圆括号把参数在 URL 模式里标识出来。在这个例子中,我们想要把这些数字作为参数,用圆括号把 \d{1,2} 包围起来:

(r'^time/plus/(\d{1,2})/$', hours_ahead),

       如果你熟悉正则表达式,那么你应该已经了解,正则表达式也是用圆括号来从文本里提取数据的。

       让我们逐行分析一下 views.py 的代码:

       视图函数,hours_ahead,有两个参数:request 和 offset。

       request 是一个 HttpRequest 对象,就像在 current_datetime 中一样。再说一次好了:每一个视图总是以一个 HttpRequest 对象作为它的第一个参数。

       offset 是从匹配的 URL 里提取出来的。 例如:如果请求 URL 是/time/plus/3/,那么 offset 将会是3;如果请求 URL 是/time/plus/21/,那么 offset 将会是21。请注意:捕获值永远都是字符串(string)类型,而不会是整数(integer)类型,即使这个字符串全由数字构成(如:“21”)。

       从技术上来说,捕获值总是 Unicode objects,而不是简单的 Python 字节串,但目前不需要担心这些差别。

       在这里我们命名变量为 offset,你也可以任意命名它,只要符合 Python 的语法。变量名是无关紧要的,重要的是它的位置,它是这个函数的第二个参数(在 request 的后面)。你还可以使用关键字来定义它,而不是用位置。

       我们在这个函数中要做的第一件事情就是在 offset 上调用 int()。这会把这个字符串值转换为整数。

       请留意:如果你在一个不能转换成整数类型的值上调用int(),Python 将抛出一个 ValueError 异常。如:int(‘foo’)。在这个例子中,如果我们遇到 ValueError 异常,我们将转为抛出 django.http.Http404 异常——正如你想象的那样:最终显示404页面(提示信息:页面不存在)。

       机灵的读者可能会问:我们在URL模式中用正则表达式 (d{1,2}) 约束它,仅接受数字怎么样?这样无论如何,offset都是由数字构成的。答案是:我们不会这么做,因为 URLpattern 提供的是”适度但有用”级别的输入校验。万一这个视图函数被其它方式调用,我们仍需自行检查 ValueError。实践证明,在实现视图函数时,不臆测参数值的做法是比较好的。松散耦合,还记得么?

       下一行,计算当前日期/时间,然后加上适当的小时数。在 current_datetime 视图中,我们已经见过 datetime.datetime.now()。这里新的概念是执行日期/时间的算术操作。我们需要创建一个 datetime.timedelta 对象和增加一个 datetime.datetime 对象。结果保存在变量 dt 中。

       这一行还说明了,我们为什么在 offset 上调用 int() —— datetime.timedelta 函数要求 hours 参数必须为整数类型。

       这行和前面的那行的一个微小差别就是,它使用带有两个值的 Python 的格式化字符串功能,而不仅仅是一个值。因此,在字符串中有两个 %s 符号和一个以进行插入的值的元组:(offset, dt) 。

       最终,返回一个HTML的HttpResponse。

       OK,程序解释完毕。用 Django 实现动态 URL 大概就这样。       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值