django学习记录,动态url,另外发现django的时区问题

按上次的经验,现在要想实现动态url,肯定先需要修改urls.py。

使用一个数字来显示为了几小时的日期和时间 
如/now/plus1hour/显示未来1小时的时间,/now/plus3hour/显示未来3小时的时间 

那么就是

 

 
  
1 urlpatterns = patterns( '' ,
2 (r ' ^now/$ ' , current_datetime),
3 (r ' ^now/plus1hour/$ ' , one_hour_ahead),
4 (r ' ^now/plus2hour/$ ' , two_hours_ahead),
5 (r ' ^now/plus3hour/$ ' , three_hours_ahead),
6 {r ' ^now/plus4hour/$ ' , four_hours_ahead),
7 )

 

但是这样的方法显得很笨拙。不仅会产生大量的视图方法,还将程序局限在预先定义的小时范围内 ,如果我们想显示5小时后的时间,我们还得再添加一行 ,所以我们应该在这里做出一点抽象 。

 

 

关于良好的URL 
如果你使用过PHP或Java,你可能会说“让我们使用一个查询参数”,类似于像/now/plus?hours=3 
你也可以使用Django这样做,但是Django的一个核心哲学是,URL应该是优雅的 
/now/plus3hours/更干净、更简单、更可读、更朗朗上口 
良好的URL是Web程序质量的一个显示 
Django的URL配置系统提供容易配置的良好的URL定义 

 

URL模式通配符 
继续我们的例子,让我们在URL模式中添加一个通配符 
上面提到,URL模式是一个正则表达式,这里我们可以使用\d+来匹配1个或多个数字: 

 

 
  
1 from django.conf.urls.defaults import *
2   from mysite.views import corruent_datetime, hours_ahead
3
4 urlpatterns = patterns( '' ,
5 (r ' ^now/$ ' , current_datetime),
6 (r ' ^now/plus\d+hours/$ ' , hours_ahead),
7 )

 

这个URL模式可以匹配任何URL,例如/now/plus2hours/,/now/plus25hours/,甚至/now/plus100000000000hours/ 
让我们限制最多99小时,即我们只允许1个或2个数字,在正则表达式里就是\d{1,2}: 
(r'^now/plus\d{1,2}hours/, hours_ahead), 

当我们构建web程序的时候,考虑可能出现的不合常理的输入, 并且决定是否处理这些输入是非常重要的。 
我们在这里限制时间的偏移量<=99小时。顺便啰嗦一句,Outlandishness Curtailers是个超级棒的乐队。 
正则表达式是一个在文本里面指定模式的简洁方式 
Django的URL配置允许任意的正则表达式来提供强大的URL匹配能力,下面是一些常用的模式:

 

 
  
1 Symbol Matches
2 .(dot) 任意字符
3 \d 任意数字
4 [A - Z] 从A到Z的任意字符(大写)
5 [a - z] 从a到z的任意字符(小写)
6 [A - Za - z] 从a到z的任意字符(大小写不敏感)
7 [ ^ / ]+ 任意字符直到一个前斜线(不包含斜线本身)
8   + 一个或多个前面的字符
9   ? 零个或多个前面的字符
10 { 1 , 3 } 1个到3个之间前面的字符(包括1和3)

 

 
更多的正则表达式信息请查看Appendix 9,正则表达式 
好了,我们已经在URL里设计了一个通配符,但我们需要把信息传递给视图方法 
这样我们才能使用一个单独的视图方法来处理任意的小时参数 
我们把我们在URL模式里希望保存的数据用括号括起来,即把\d{1,2}括起来 
(r'^now/plus(\d{1,2})hours/, hours_ahead), 

如果你熟悉正则表达式,你会觉得非常亲切:我们正是在使用括号从匹配的文本中获得我们想要的数据。 
最终的URL配置如下: 

 

 

 

 

 
  
1 from django.conf.urls.defautls import *
2 form mysite.views import current_datetime, hours_ahead
3
4 urlpatterns = patterns( '' ,
5 (r ' ^now/$ ' , current_datetime),
6 (r ' ^now/plus(\d{1,2})hours/$ ' , hours_ahead),
7 )

 

 

 

下面我们定义hours_ahead方法: 
告诫:关于编码的顺序 
在这个例子里面,我们先定义了URL模式,然后才开始撰写view代码,但是在前一个例子里,编码的顺序正好相反。那么哪一种方式更好呢? 
当然,每一个开发人员都有不一样的习惯。 
如果你是一个大局观很好的人,一次性就定义好所有的URL模式,然后再来实现view的代码,这是非常不错的。 
这种方式能够展现一个非常清晰的to-do list,因为它从根本上定义了将要实现的view函数所需的参数。 
如果你是一个有着自底向上的习惯的程序员,你也许更愿意写一个view,然后把它和某一个URL模式绑定起来。这样做也不错。 
两种方式当然都是正确的,使用哪一个取决于哪一种更加符合你思考的模式。 

(我发现我把教材都拷贝过来了,不过留着吧,觉得很有用。)

 

ContractedBlock.gifExpandedBlockStart.gif代码
1 from django.http import HttpResponse
2  import datetime
3
4  def hours_ahead(request, offset):
5 offset = int(offset)
6 dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
7 html = "In %s hour(s), it will be %s." % (offset, dt)
8 return HttpResponse(html)

 


 

 

我们还是一次一行的解读这些代码: 
跟我们在current_datetime里所做的一样,我们导入了django.http.HttpResponse和datetime模块 
view函数hours_ahead接受两个参数:request和offset。 
request是一个HttpRequest对象,和在current_datetime中一样。我们要重申一点:每一个view函数的第一个参数总是HttpRequest对象。 
offset是一个string,它的值是通过URL模式里的那一对括号从请求的URL中得到的。比如请求的URL是/now/plus3hours/ 
offset的值就是一个string‘3’。请注意从URL中得到的值始终是string而不是integer,即使这个string是由纯数字构成的。 
我们把这个变量命名为offset,但是你可以用任何合法的Python变量名来命名它。变量的名字并不重要,但是必须是view函数的第二个参数。 
在函数里我们做的第一件事就是调用int(),把offset转换成整形。 
如果一个值不能被转换成为一个整型数(像字符串'foo'), Python将会抛出ValueError。 
但是我们对此并不担心,因为我们可以肯定offset一定可以被转换,正则表达式\d{1,2}一定会从URL中获得数字。 
这也从另一个侧面证明了URLconf的优雅:它相当清楚地提供了一个对输入的校验。 
程序的下一行揭示了我们对offset做类型转换的原因,这行代码计算了当前的时间加上一个时间偏移量,这个偏移量的值就是offset 
保存计算的结果在变量dt.datetime.timedelta函数需要的输入参数就是整型。 
下一行我们构造一个html的输出,和在current_datetime函数中类似。 
最后,和current_datetime函数一样,我们返回一个HttpResponse对象。 
好了,我们访问http://127.0.0.1:8000/now/plus3hours/可以验证它工作了 
然后我们试试http://127.0.0.1:8000/now/plus100hours/,Django显示“Page not found”错误 
http://127.0.0.1:8000/plushours/也会显示404错误,因为我们只接受1个或2个数字的参数 

 

Django良好的出错页面 
我们将offset = int(offset)注释掉 
# offset = int(offset) 
然后重新访问/now/plus3hours,你将看到一个很多信息的出错页面,包括TypeError信息在最上面: 
“unsupported type for timedelta hours component: str” 
发生了什么? 
datetime.timedelta函数预期hours参数为integer类型,但我们注释掉了把offset转化为integer的代码 
这导致datetime.timedelta产生TypeError,只是典型的每个程序员容易出现的小bug 
中一些需要注意的地方: 
1,页面的顶端显示的是关于异常的主要信息:异常的类型,异常的参数,导致异常的文件和行数 
2,接下来页面显示完整的异常的Python traceback,在stack的每个frame里Django都显示了文件名、方法名、行数和该行代码 
点击暗灰色的代码,你可以看到出错行前后的几行代码,让你得到上下文 
点击“Local vars”可以看到所有的本地变量的列表,变量值,出错点等,这个debug信息是很有价值的 
3,点击在“Traceback”下面的“Switch to copy-and-paste view”将切换到可以很容易复制粘贴的版本 
当你想同他人分享异常信息或得到技术支持时(Django IRC聊天室或者Django用户邮件列表)可以很好的利用它 
4,“Request information”包括大量的产生错误的Web请求的信息,GET和POST信息,cookie值和meta信息如CGI头部等 
下面的“Settings”部分列出了当前Django安装的所有设置信息,后面我们会慢慢解释这些 
Django错误页面在模板语法错误等情况下会显示更丰富的信息,现在去掉注释offset=int(offset) 
你是那种喜欢用print语句debug 的程序员吗?使用Django错误页面就可以做到这点,不需要print语句 
你可以临时插入assert False来触发错误页面,后面我们会解释更高级的debug方法 
很显然大部分这些错误信息是敏感的,它暴露了你的Python代码和Django配置的五脏六腑 
把这些信息显示到网上是愚蠢的,心怀恶意的人可能会在你的网站里面做肮脏的事情 
无论如何,后面我们会提到怎样去除debug模式 

 

另外,在做这道题的同时发现一个问题,那就是django的时区问题,如果我直接在Python下查看datetime.datetime.now(),和本地系统时间是一样的,但是在django下获取datetime.datetime.now()却有时间差。后来知道需要在settings.py里面把TIME_ZONE设为:Etc/GMT-8,这也是一个很基础的问题啊。

又学完了一章,加油加油~再快点

转载于:https://www.cnblogs.com/Phenix_Yang/archive/2010/05/26/1744473.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值