在Django中创建第一个静态视图
正如我们的第一个目标,创建一个网页,用来输出这个著名的示例信息:
Helloworld.
如果你曾经发布过Helloworld页面,但是没有使用网页框架,只是简单的在hello.html文本文件中输入HelloWorld,然后上传到任意的一个网页服务器上。注意,在这个过程中,你已经说明了两个关于这个网页的关键信息:它包括(字符串"Helloworld")和它的URL(http://www.example.com/hello.html,如果你把文件放在子目录,也可能是http://www.example.com/files/hello.html)。
使用Django,你会用不同的方法来说明这两件事页面的内容是靠viewfunction(视图函数)来产生,URL定义在URLconf中。首先,我们先写一个HelloWorld视图函数。
在上一章使用django-admin.pystartproject制作的mysite文件夹中,创建一个叫做views.py的空文件。这个Python模块将包含这一章的视图。请留意,Django对于view.py的文件命名没有特别的要求,它不在乎这个文件叫什么。但是根据约定,把它命名成view.py是个好主意,这样有利于其他开发者读懂你的代码,正如你很容易的往下读懂本文。
我们的Helloworld视图非常简单。这些是完整的函数和导入声明,你需要输入到views.py文件:
fromdjango.httpimportHttpResponse defhello(request): returnHttpResponse("Helloworld")
我们逐行逐句地分析一遍这段代码:
- 首先,我们从django.http模块导入(import)HttpResponse类。参阅附录H了解更多关于HttpRequest和HttpResponse的细节。我们需要导入这些类,因为我们会在后面用到。
- 接下来,我们定义一个叫做hello的视图函数。
- 每个视图函数至少要有一个参数,通常被叫作request。这是一个触发这个视图、包含当前Web请求信息的对象,是类django.http.HttpRequest的一个实例。在这个示例中,我们虽然不用request做任何事情,然而它仍必须是这个视图的第一个参数。
- 注意视图函数的名称并不重要;并不一定非得以某种特定的方式命名才能让Django识别它。在这里我们把它命名为:hello,是因为这个名称清晰的显示了视图的用意。同样地,你可以用诸如:hello_wonderful_beautiful_world,这样难看的短句来给它命名。在下一小节(YourFirstURLconf),将告诉你Django是如何找到这个函数的。
- 这个函数只有简单的一行代码:它仅仅返回一个HttpResponse对象,这个对象包含了文本“Helloworld”。
这里主要讲的是:一个视图就是Python的一个函数。这个函数第一个参数的类型是HttpRequest;它返回一个HttpResponse实例。为了使一个Python的函数成为一个Django可识别的视图,它必须满足这两个条件。(也有例外,但是我们稍后才会接触到。
你的第一个URLconf
现在,如果你再运行:pythonmanage.pyrunserver,你还将看到Django的欢迎页面,而看不到我们刚才写的Helloworld显示页面。那是因为我们的mysite项目还对hello视图一无所知。我们需要通过一个详细描述的URL来显式的告诉它并且激活这个视图。(继续我们刚才类似发布静态HTML文件的例子。现在我们已经创建了HTML文件,但还没有把它上传至服务器的目录。)为了绑定视图函数和URL,我们使用URLconf。
URLconf就像是Django所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表。你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。例如,当用户访问/foo/时,调用视图函数foo_view(),这个视图函数存在于Python模块文件view.py中。
前一章中执行django-admin.pystartproject时,该脚本会自动为你建了一份URLconf(即urls.py文件)。默认的urls.py会像下面这个样子:
fromdjango.conf.urls.defaultsimport* #Uncommentthenexttwolinestoenabletheadmin: #fromdjango.contribimportadmin #admin.autodiscover() urlpatterns=patterns('', #Example: #(r'^mysite/',include('mysite.foo.urls')), #Uncommenttheadmin/doclinebelowandadd'django.contrib.admindocs' #toINSTALLED_APPStoenableadmindocumentation: #(r'^admin/doc/',include('django.contrib.admindocs.urls')), #Uncommentthenextlinetoenabletheadmin: #(r'^admin/',include(admin.site.urls)), )
默认的URLconf包含了一些被注释起来的Django中常用的功能,仅仅只需去掉这些注释就可以开启这些功能.下面是URLconf中忽略被注释的行后的实际内容
fromdjango.conf.urls.defaultsimport* urlpatterns=patterns('', )
让我们逐行解释一下代码:
- 第一行导入django.conf.urls.defaults下的所有模块,它们是DjangoURLconf的基本构造。这包含了一个patterns函数。
- 第二行调用patterns()函数并将返回结果保存到urlpatterns变量。patterns函数当前只有一个参数—一个空的字符串。(这个字符串可以被用来表示一个视图函数的通用前缀。具体我们将在第八章里面介绍。)
当前应该注意是urlpatterns变量,Django期望能从ROOT_URLCONF模块中找到它。该变量定义了URL以及用于处理这些URL的代码之间的映射关系。默认情况下,URLconf所有内容都被注释起来了——Django应用程序还是白版一块。(注:那是上一节中Django怎么知道显示欢迎页面的原因。如果URLconf为空,Django会认定你才创建好新项目,因此也就显示那种信息。
如果想在URLconf中加入URL和view,只需增加映射URL模式和view功能的Pythontuple即可.这里演示如何添加view中hello功能.
fromdjango.conf.urls.defaultsimport* frommysite.viewsimporthello urlpatterns=patterns('', ('^hello/$',hello), )
请留意:为了简洁,我们移除了注释代码。如果你喜欢的话,你可以保留那些行。)
我们做了两处修改。
- 首先,我们从模块(在Python的import语法中,mysite/views.py转译为mysite.views)中引入了hello视图。(这假设mysite/views.py在你的Python搜索路径上。关于搜索路径的解释,请参照下文。)
- 接下来,我们为urlpatterns加上一行:(‘^hello/$',hello),这行被称作URLpattern,它是一个Python的元组。元组中第一个元素是模式匹配字符串(正则表达式);第二个元素是那个模式将使用的视图函数。
简单来说,我们只是告诉Django,所有指向URL/hello/的请求都应由hello这个视图函数来处理。
Python搜索路径
Python搜索路径就是使用import语句时,Python所查找的系统目录清单。
举例来说,假定你将Python路径设置为['','/usr/lib/python2.4/site-packages','/home/username/djcode/']。如果执行代码fromfooimportbar,Python将会首先在当前目录查找foo.py模块(Python路径第一项的空字符串表示当前目录)。如果文件不存在,Python将查找/usr/lib/python2.4/site-packages/foo.py文件。
如果你想看Python搜索路径的值,运行Python交互解释器,然后输入:
>>>importsys >>>printsys.path
通常,你不必关心Python搜索路径的设置。Python和Django会在后台自动帮你处理好。
讨论一下URLpattern的语法是值得的,因为它不是显而易见的。虽然我们想匹配地址/hello/,但是模式看上去与这有点差别。这就是为什么:
- Django在检查URL模式前,移除每一个申请的URL开头的斜杠(/)。这意味着我们为/hello/写URL模式不用包含斜杠(/)。(刚开始,这样可能看起来不直观,但这样的要求简化了许多工作,如URL模式内嵌,我们将在第八章谈及。)
- 模式包含了一个尖号(^)和一个美元符号($)。这些都是正则表达式符号,并且有特定的含义:上箭头要求表达式对字符串的头部进行匹配,美元符号则要求表达式对字符串的尾部进行匹配。
- 最好还是用范例来说明一下这个概念。如果我们用尾部不是$的模式'^hello/',那么任何以/hello/开头的URL将会匹配,例如:/hello/foo和/hello/bar,而不仅仅是/hello/。类似地,如果我们忽略了尖号(^),即'hello/$',那么任何以hello/结尾的URL将会匹配,例如:/foo/bar/hello/。如果我们简单使用hello/,即没有^开头和$结尾,那么任何包含hello/的URL将会匹配,如:/foo/hello/bar。因此,我们使用这两个符号以确保只有/hello/匹配,不多也不少。
- 你大多数的URL模式会以^开始、以$结束,但是拥有复杂匹配的灵活性会更好。
- 你可能会问:如果有人申请访问/hello(尾部没有斜杠/)会怎样。因为我们的URL模式要求尾部有一个斜杠(/),那个申请URL将不匹配。然而,默认地,任何不匹配或尾部没有斜杠(/)的申请URL,将被重定向至尾部包含斜杠的相同字眼的URL。(这是受配置文件setting中APPEND_SLASH项控制的,参见附件D。)
- 如果你是喜欢所有URL都以'/'结尾的人(Django开发者的偏爱),那么你只需要在每个URL后添加斜杠,并且设置”APPEND_SLASH”为”True”.如果不喜欢URL以斜杠结尾或者根据每个URL来决定,那么需要设置”APPEND_SLASH”为”False”,并且根据你自己的意愿来添加结尾斜杠/在URL模式后.
另外需要注意的是,我们把hello视图函数作为一个对象传递,而不是调用它。这是Python(及其它动态语言的)的一个重要特性:函数是一级对象(first-classobjects),也就是说你可以像传递其它变量一样传递它们。很酷吧?
启动Django开发服务器来测试修改好的URLconf,运行命令行pythonmanage.pyrunserver。(如果你让它一直运行也可以,开发服务器会自动监测代码改动并自动重新载入,所以不需要手工重启)开发服务器的地址是http://127.0.0.1:8000/,打开你的浏览器访问http://127.0.0.1:8000/hello/。你就可以看到输出结果了。开发服务器将自动检测Python代码的更改来做必要的重新加载,所以你不需要重启Server在代码更改之后。服务器运行地址``http://127.0.0.1:8000/``,所以打开浏览器直接输入``http://127.0.0.1:8000/hello/``,你将看到由你的Django视图输出的Helloworld。
万岁!你已经创建了第一个Django的web页面。