Django -- 视图和URL配置

时间:2022-05-27 19:15:05

一个人行走的范围,就是他的世界;    -- 北岛《青灯》

一个人吟唱的语调,就是他的生活。    -- 小Q《小曲》

-------------------------------------------------------------------------------------------------

前一节我们建立了一个Django项目,这一节我们来了解视图和url的关系;

【第一个视图 根目录】

当我们搭建好django时,urls.py内没有url,我们会看到一个欢迎页面,但当我们设定了几个url时我们直接访问http://10.0.18.33:8002/将会看到404,因为正常情况下django不会添加任何东西在根目录,因为所有url都不是特殊的需要被指定。

所以根目录也需要如下指定,才会有视图显示,配置类似:url('^$',my_homepage_view),

【第二个视图:静态hello world】

正如我们每学一门语言,创建的第一个界面hello world;首先要明白页面内容是靠view functioin(视图函数)和URLconf定义的url。当然视图文件对于名字没有一定的要求,不过尽量规范点命名为view.py

视图函数:

cat /HelloWorld/HelloWorld/view.py

from django.http import HttpResponse  
def hello(request):  
return HttpResponse("Hello  World !!!") 

#在django.http模块内导入HttpResponse类
#定义hello视图函数,视图函数至少有一个函数request,类的实例
#返回HttpResponse对象,对象包含了hello world文本
##即一个视图就是一个Python函数,为了使django识别,要包含以下两个参数:
##函数第一个参数类型是HttpResponse;返回一个HttpResponse实例。

URLconf:配置完视图函数后,我们要给此视图一个访问路径,去绑定这个视图函数

cat /HelloWorld/HelloWorld/urls.py

from django.conf.urls import url  from django.contrib import admin  ** from HelloWorld.view import hello  urlpatterns = [    **    url('^hello/$', hello),  url(r'^admin/', admin.site.urls),  ]#导入django.conf.urls下所有url#django.contrib将会在后面介绍,管理工具#在HelloWorld.view模块中调用hello视图函数#urlpatterns变量,django在ROOT_URLCONF模块寻找它#元祖,第一元素URLpattern模式匹配,第二元素是视图函数名#r是正则,告诉oython这是一个原始字符串,不需处理转义符

urlpatterns = patterns('',  

)

有的版本的django,urls.conf默认是此配置,调用patterns函数

默认没有url指向,所以django会认定你创建好新项目,显示it work 欢迎界面

Django -- 视图和URL配置


===============================================================================================

附加1:关于import调用,举例调用hello模块

1、python去找当前路径有没有hello.py

2、python去sys.path出的路径找hello.py

附加2:关于域名hello后面的'/',访问时要不要加

我们urls.conf中正则规定的是必须加'/',但是默认的尾部没有'/'的将会自动被重定向至添加'/';测试,如果我们在urls.conf中将hello后'/'去掉,我们将访问不到hello world。

关键在:settings.py中的APPEND_SLASH = False/True,喜欢以'/'结尾的可设为True,喜欢自己结尾定义'/'的设为False(即web端不会自动追加'/')。

附加3:我们是把hello函数作为对象传递,而不是调用

这是python重要特性:函数是一级对象,即可以像传递变量似的传递它们。

【请求处理过程】

访问存在的url时,有的人就会想,django是怎么工作的,接下来我们用hello world来向大家讲解一下:

(所有始于settings.py,django-admin.py startproject时生成的,文件中包含了django配置信息,均大写)

1、当我们python manage.py  runserver 0.0.0.0:8002运行时,脚本将在同一个额目录下找settings.py

2、settings.py去查看ROOT_URLCONF,此时它指向'HelloWorld.urls';

3、访问/hello/时,django将去遍历~/HelloWorld/urls.py下的url,直至找到,否则就404;

4、找到匹配的hello,就会调用相应的视图函数;

5、然后视图函数返回HttpResponse;

6、django转换HttpResponse对象为一个HTTP response,并以web page显示出来;

(有人会认为一系列正则将urls映射到函数会比较慢,但事实会让你惊讶,官网是这么说,哈哈哈,,)

================================================================================================

【第三个视图:动态 datetime】

我们用hello视图来演示基本的django工作形式,这一小节我们将利用动态内容,在网页上显示:当前日期和时间。

from django.http import HttpResponse**import datetime   #调用datetime函数def hello(request):return HttpResponse("Hello  World !!!")**def current_time(request):   #定义视图函数**    now = datetime.datetime.now()   #python语法,取当前值**    html =  "<html><body>It is now %s.</body></html>" % now **    return HttpResponse(html)   #返回HttpResponse对象html值

cat ~/HelloWorld/HelloWorld/urls.py

from django.conf.urls import urlfrom django.contrib import admin**from HelloWorld.view import hello,current_time   #调用current_time视图函数urlpatterns = [url('^hello/$', hello),**    url('^time/$',current_time),   #定义urlurl(r'^admin/', admin.site.urls),]

Django -- 视图和URL配置

===============================================================================================

注:此时时间和本地时间差好多,因为django默认是UTC时区,改为TIME_ZONE = 'Asia/Shanghai' 即可。

【url配置和松耦合】

松耦合原则:(django和url配置背后的哲学)即重要的保证互换性的软件开发方法,url和视图函数之间就是松耦合的。

比如:决定url返回哪个视图函数和实现这个视图函数实在两个不同的地方,使得开发人员修改一块而不会影响另一块;

例如:第二视图中,我们想把URL的/time/变成/currenttime/,我们只需快速修改url配置即可;同样我们想修改函数内部实现,也不会担心会影响到url。

===============================================================================================

【第四个视图 动态URL】

在我们“current_time”视图举例中,尽管内容是动态的,但是URL还是静态的,在大多数web程序中,URL通常包含相关参数,如/books/654,/books/7868.......

设计:显示当前时间+时间偏移量,即

/time/plus/1 = 当前时间+1

/time/plus/2 = 当前时间+2

/time/plus/3 = 当前时间+3

.........

如果我们依据上面的方式来定义的话,就会是如下配置:

urlpatterns = [url('^hello/$', hello),url('^time/$',current_time),   #定义url**    ('^time/plus/1/$', one_hour_ahead),**    ('^time/plus/2/$', two_hours_ahead),**    ('^time/plus/3/$', three_hours_ahead),url(r'^admin/', admin.site.urls),]

很明显,这样配置繁琐而冗余,而且我们还要不断定义新的视图函数;所以我们要做一点抽象,提取共同的东西出来。

有web开发经验(php或java)的会想:用查询字符串吧!就像/time/plus?hours=3里面的小时应该在查询字符串中呗hours参数指定。当然django也可以这么做,但是django的核心理念就是URL看起来必须漂亮,漂亮的URL是高质量web应用的一个标志。

答案:通配符。(正如之前提到一个URL就是一个正则表达式,因此可以用d+匹配一个以上数字)

cat ~/HelloWorld/HelloWorld/urls.py

from django.conf.urls import urlfrom django.contrib import admin**from HelloWorld.view import hello,current_time,hours_aheadurlpatterns = [    url('^hello/$', hello),    url('^time/$',current_time),#   (r'^time/plus/\d+/$', hours_ahead), #此模式可以匹配/time/plus/1到/time/plus/100000/任何url**   (r'^time/plus/\d{1,2}/$', hours_ahead), #限制一下,匹配偏差100小时以内的    url(r'^admin/', admin.site.urls),]

现在开始写hours_ahead视图(当然我们也可以用先写视图,再写url的自底向上开发,无所谓):

cat ~/HelloWorld/HelloWorld/view.py

from django.http import Http404,HttpResponseimport datetimedef hello(request):return HttpResponse("Hello  World !!!")def current_time(request):now = datetime.datetime.now()html =  "<html><body>It is now %s.</body></html>" % nowreturn HttpResponse(html)def hours_ahead(request,offset):try:offset = int(offset)except ValueError:raise Http404()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)

解读代码:

视图函数hours_ahead带有两个参数:

request 是HttpRequest对象,再说一次,每个视图总要以一个HttpRequest对象作为第一个参数;

offset 是从匹配的URL提取出来的,例如/time/plus/3/,则offset就是3,并且捕获的值都是字符串类型(更准确的说是Unicode objects类型)。

如果我们在不能转换成int类型的值上调用int,会产生ValueError异常

dt计算时间操作,将offset变量值赋予hours,也可以是days,变量名也可以是offds等等

最终返回一个HttpResponse,如今这种方式已经过时了。

================================================================================================

Error:TypeError: hours_ahead() takes exactly 2 arguments (1 given)

解 决:url 加上括号改为url(r'^time/plus/(\d{1,2})/$',hours_ahead)即可,因为括号的\d{1,2}内容代表了视图函数第二个参数位置

================================================================================================

Django -- 视图和URL配置

Django -- 视图和URL配置

【错误页面】

第一种:dbug模式下,访问不存在页面

此时我们定义了一个hello的url页面,自带一个admin页面,如果我们访问其他url会怎么样?

Django -- 视图和URL配置

第二种:dbug模式下语法错误

用上面的视图举例,我们将转换整型步骤注释,如下,然后访问:

def hours_ahead(request, offset):    # try:    #     offset = int(offset)    # except ValueError:    #     raise Http404()    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)

Django -- 视图和URL配置

错误解读:

页面顶部,我们可以看到关键信息,异常数据类型、异常的参数 (如本例中的 "unsupported type" )、在哪个文件中引发了异常、出错的行号等等;

关键信息下方,显示了对异常完整的python追踪信息,不过后者更具有交互性,对栈中每一帧,均显示了文件名、函数、方法名、行号、源代码;

任何一帧中"local vars"可以看到所有局部变量的列表,以及出错时那一帧他们的值;

"Traceback"下面的"Switch to copy-and-paste view"文字。 点击会切换另一个视图,它让你很容易地复制和粘贴这些内容,方便去分享;点击"Share this traceback on a public Web site"你可以获得单独的URL方便去跟别人分享;

接下来的"Request information"部分包含了有关产生错误的 Web 请求的大量信息: GET 和 POST、cookie 值、元数据(象 CGI 头),下面setting里除了django的配置信息。

================================================================================================

附加:有的程序员习惯于放置print语句调试,其实完全可以用django出错页来调试,在视图的任何位置插入assert False 触发出错页,来查看局部变量和程序语句;

dt = datetime.datetime.now() + datetime.timedelta(hours=offset)

**    assert False

html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)

================================================================================================

第三种:关闭dbug模式,因为我们会发现上面出现的这些敏感信息,不应该呈现给用户

更改DEBUG = True 为 DEBUG = False(settings.py中即关闭dbug模式)将得到如下返回

Django -- 视图和URL配置

-----------------------------------------------------------------------------------------------------



本文出自 “滕先生” 博客,请务必保留此出处http://tengxiansheng.blog.51cto.com/10693373/1882887