我们解释了如何建立一个 Django项目并启动 Django
开发服务器。当然,那个网站实际并没有干什么有用的事情,它所做的只是显示 It worked!消息。让我们来做些改变。本章将介绍如何使用 Django创建动态网页。
第一份视图:动态内容
我们的第一个目标是创建一个显示当前日期和时间的网页。这是一个不错的动态网页范例,因为该页面的内容不是静态的。相反,其内容是随着计算(本例中是对当前时间的计算)的结果而变化的。这个简单的范例既不涉及数据库,也不需要任何用户输入,仅输出服务器的内部时钟。
我们将编写一个视图函数以创建该页面。所谓的视图函数(或视图),只不过是一个接受
Web 请求并返回 Web
响应的 Python 函数。实际上,该响应可以是一份网页的 HTML内容、一次重定向、一条 404错误、一份
XML 文档、一幅图片,或其它任何东西。视图本身包含返回该响应所需的任意逻辑。该段代码可以随意放置,只要在 Python的路径设置中就可以了。没有其它要求——也可以说是没有任何奇特之处。为了给这些代码一个存身之处,让我们在上一章所创建的mysite目录中新建一份名为views.py的文件。
以下是一个以HTML方式返回当前的日期与时间的视图 (view),:
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
我们逐行逐句地分析一遍这段代码:
首先,我们从django.http模块导入(import)HttpResponse类。参阅附录
H 了解更多关于HttpRequest和HttpResponse的细节。
然后我们从 Python标准库(Python
自带的实用模块集合)中导入(import)datetime模块。datetime模块包含几个处理日期和时间的函数(functions)和类(classes),其中就包括返回当前时间的函数。
接下来,我们定义了一个叫做current_datetime的函数。这就是所谓的视图函数(view function)。每个视图函数都以一个HttpRequest对象为第一个参数,该参数通常命名为request。
注意视图函数的名称并不重要;并不一定非得以某种特定的方式命名才能让 Django识别它。此处,我们称之为current_datetime,只是因为该名字明确地指出了它的功能,而它也可以被命名为super_duper_awesome_current_time或者其它同样莫名其妙的名字。Django并不关心其名字。下一节将解释
Django如何查找该函数。
函数中的第一行代码计算当前日期和时间,并以datetime.datetime对象的形式保存为局部变量now。
函数的第二行代码用 Python的格式化字符串(format-string)功能构造了一段
HTML响应。字符串里面的%s是占位符,字符串之后的百分号表示使用变量now的值替换%s。(是的,这段
HTML 不合法,但我们只不过是想让范例尽量保持简短而已。)
最后,该视图返回一个包含所生成响应的HttpResponse对象。每个视图函数都负责返回一个HttpResponse对象。(也有例外,但是我们稍后才会接触到。)
Django 时区 (Time Zone)
Django 包含一个默认为America/Chicago的TIME_ZONE设置。这可能不是你所居住的时区,因此你可以在settings.py文件中修改它。请参阅附录
E 了解更多细节。
将 URL映射到视图
那么概括起来,该视图函数返回了包含当前日期和时间的一段 HTML页面。但是如何告诉 Django使用这段代码呢?这就是URLconfs粉墨登场的地方了。
URLconf就像是 Django所支撑网站的目录。它的本质是 URL模式以及要为该
URL 模式调用的视图函数之间的映射表。你就是以这种方式告诉 Django,对于这个 URL调用这段代码,对于那个
URL调用那段代码。但必须记住的是视图函数必须位于 Python搜索路径之中。
Python 搜索路径
Python 搜索路径就是使用import语句时,Python所查找的系统目录清单。
举例来说,假定你将 Python路径设置为[‘‘,‘/usr/lib/python2.4/site-packages‘,‘/home/username/djcode/‘]。如果执行代码from
foo import bar,Python将会首先在当前目录查找foo.py模块( Python路径第一项的空字符串表示当前目录)。如果文件不存在,Python将查找/usr/lib/python2.4/site-packages/foo.py文件。如果文件也不存在,它将尝试/home/username/djcode/foo.py。最后,如果这个文件还不存在,它将引发ImportError异常。
如果对了解 Python搜索路径值感兴趣,可以启动 Python交互式解释程序,输入import
sys,接着输入print sys.path。
通常,你不必关心 Python搜索路径的设置。Python
和 Django
会在后台自动帮你处理好。(如果有兴趣了解的话,Python搜索路径的设置工作是manage.py文件的职能之一。)
前一章中执行django-admin.py startproject时,该脚本会自动为你建了一份 URLconf(即urls.py文件)。让我们编辑一下这份文件。缺省情况下它是下面这个样子:
from django.conf.urls.defaults import *
urlpatterns = patterns(‘‘,
# Example:
# (r‘^mysite/‘, include(‘mysite.apps.foo.urls.foo‘)),
# Uncomment this for admin:
# (r‘^admin/‘, include(‘django.contrib.admin.urls‘)),
)
让我们逐行逐句分析一遍这段代码:
§ 第一行从django.conf.urls.defaults模块引入了所有的对象,其中包括了叫做patterns的函数。
§ 第二行调用patterns()函数并将返回结果保存到urlpatterns变量。patterns()函数只传入了一个空字符串参数。其他代码行都被注释掉了。
(该字符串可用作视图函数的通用前缀,但目前我们将略过这种高级用法。)
当前应该注意是urlpatterns变量, Django期望能从ROOT_URLCONF模块中找到它。该变量定义了
URL以及用于处理这些 URL
的代码之间的映射关系。
默认情况下,URLconf所有内容都被注释起来了——Django应用程序还是白版一块。(旁注:这也就是上一章中
Django显示“It worked!”页面的原因。如果 URLconf为空,Django
会认定你才创建好新项目,因此也就显示那种信息。)
现在编辑该文件以展示我们的current_datetime视图:
from django.conf.urls.defaults import *
from mysite.views import current_datetime
urlpatterns = patterns(‘‘,
(r‘^time/$‘, current_datetime),
)
我们做了两处修改。首先,我们从模块 (在 Python的 import
语法中,mysite/views.py转译为mysite.views)中引入了current_datetime视图。接着,我们加入了(r‘^time/$‘,
current_datetime),这一行。该行就是所谓的URLpattern
,它是一个 Python元组,其第一个元素是简单的正则表达式,第二个元素是为该模式应用的视图函数。
简单来说,我们只是告诉 Django,所有指向 URL/time/的请求都应由current_datetime这个视图函数来处理。
下面是一些需要注意的地方:
注意,该例中,我们将current_datetime视图函数作为对象传递,而不是调用它。这是Python(及其它动态语言的)的一个重要特性:函数是一级对象(first-class objects),也就是说你可以像传递其它变量一样传递它们。很酷吧?
r‘^time/$‘中的r表示‘^time/$‘是一个原始字符串。这样一来就可以避免正则表达式有过多的转义字符。
不必在‘^time/$‘前加斜杠(/)来匹配/time/,因为
Django 会自动在每个表达式前添加一个斜杠。乍看起来,这好像有点奇怪,但是 URLconfs可能由其它的 URLconfs所引用,
所以不加前面的斜杠可让事情简单一些。这一点在第 8章中将有进一步阐述。
上箭头^和美元符号$符号非常重要。上箭头要求表达式对字符串的头部进行匹配,美元符号则要求表达式对字符串的尾部进行匹配。
最好还是用范例来说明一下这个概念。如果我们用‘^time/‘(结尾没有$),那么以time/开始的任意URL都会匹配,比如/time/foo和/time/bar,不仅仅是/time/。同样的,如果我们去掉最前面的
^ (‘time/$‘), Django一样会匹配由time/结束的任意URL/time/,比如/foo/bar/time/。因此,我们必须同时用上
^ 和 $
来精确匹配 URL/time/。不能多也不能少。
你可能想如果有人请求/time也可以同样处理。如果APPEND_SLASH的设置是True的话,系统会重定向到/time/,这样就可以一样处理了。
(有关内容请查看附录 E )
启动Django开发服务器来测试修改好的 URLconf,运行命令行python manage.py
runserver。 (如果你让它一直运行也可以,开发服务器会自动监测代码改动并自动重新载入,所以不需要手工重启)开发服务器的地址是http://127.0.0.1:8000/,打开你的浏览器访问http://127.0.0.1:8000/time/。你就可以看到输出结果了。
万岁!你已经创建了第一个Django的web页面。
正则表达式
正则表达式(或regexes
) 是通用的文本模式匹配的方法。Django URLconfs允许你使用任意的正则表达式来做强有力的URL映射,不过通常你实际上可能只需要使用很少的一部分功能。下面就是一些常用通用模式:
符号 |
匹配 |
. (dot) |
任意字符 |
\d |
任意数字 |
[A-Z] |
任意字符, A-Z (大写) |
[a-z] |
任意字符, a-z (小写) |
[A-Za-z] |
任意字符, a-z (不区分大小写) |
+ |
匹配一个或更多 (例如, \d+匹配一个或 多个数字字符) |
[^/]+ |
不是/的任意字符 |
* |
匹配0个或更多 (例如, \d*匹配0个 或更多数字字符) |
{1,3} |
匹配1个到3个(包含)2 |
有关正则表达式的更多内容,请访问http://www.djangoproject.com/r/python/re-module/.
Django是怎么处理请求的
我们必须对刚才所发生的几件事情进行一些说明。它们是运行Django开发服务器和构造Web页面请求的本质所在。
命令python manage.py runserver从同一目录载入文件settings.py。该文件包含了这个特定的Django实例所有的各种可选配置,其中一个最重要的配置就是ROOT_URLCONF。ROOT_URLCONF告诉Django哪个Python模块应该用作本网站的
URLconf。
还记得django-admin.py startproject创建的文件settings.py和urls.py吗?这时系统自动生成的settings.py里ROOT_URLCONF默认设置是urls.py。
当访问 URL/time/时,Django根据ROOT_URLCONF的设置装载
URLconf。然后按顺序逐个匹配URLconf里的URLpatterns,直到找到一个匹配的。当找到这个匹配的URLpatterns就调用相关联的view函数,并把HttpRequest对象作为第一个参数。(稍后再给出HttpRequest的更多信息)
该 view函数负责返回一个HttpResponse对象。
你现在知道了怎么做一个 Django-powered页面了,真的很简单,只需要写视图函数并用 URLconfs把它们和URLs对应起来。你可能会认为用一系列正则表达式将URLs映射到函数也许会比较慢,但事实却会让你惊讶。
Django如何处理请求:完整细节
除了刚才所说到的简明URL-to-view映射方式之外,Django在请求处理方面提供了大量的灵活性。
通过 URLconf解析到哪个视图函数来返回HttpResponse可以通过中间件(middleware)来短路或者增强。关于中间件的细节将在第十五章详细谈论,这里给出图3-1让你先了解大体概念.
图3-1:Django请求回应流程
当服务器收到一个HTTP请求以后,一个服务器特定的handler
会创建HttpRequest并传递给下一个组件并处理。
这个 handler然后调用所有可用的Request或者View中间件。这些类型的中间件通常是用来增强HttpRequest对象来对一些特别类型的request做些特别处理。只要其中有一个返回HttpResponse,系统就跳过对视图的处理。
即便是最棒的程序员也会有出错的时候,这个时候异常处理中间件(exception middleware)可以帮你的大忙。如果一个视图函数抛出异常,控制器会传递给异常处理中间件处理。如果这个中间件没有返回HttpResponse,意味着它不能处理这个异常,这个异常将会再次抛出。
即便是这样,你也不用担心。Django包含缺省的视图来生成友好的404和 500
回应(response)。
最后,
response middleware 做发送HttpResponse给浏览器之前的后处理或者清除请求用到的相关资源。
URL配置和松耦合
现在是好时机来指出Django和URL配置背后的哲学:松耦合原则。简单的说,松耦合是一个重要的保证互换性的一个软件开发方法。如果两段代码是松耦合的,那么改动其中一段代码不会影响另一段代码,或者只有很少的一点影响。
Django的URL配置就是一个很好的例子。在Django的应用程序中,URL的定义和视图函数之间是松耦合的,换句话说,决定URL返回哪个视图函数和实现这个视图函数是在两个不同的地方。这使得开发人员可以修改一块而不会影响另一块。
相比之下,其他的Web开发平台紧耦合和URL到代码中。在典型的PHP (http://www.php.net/)应用,URL的设计是通过放置代码的目录来实现。在早期的
CherryPy Python Web framework (http://www.cherrypy.org/)中,URL对应处理的的方法名。这可能在短期看起来是便利之举,但是长期会带来难维护的问题。
比方说,考虑有一个以前写的视图函数,这个函数显示当前日期和时间。如果我们想把它的URL从原来的/time/改变到/currenttime/,我们只需要快速的修改一下URL配置即可,不用担心这个函数的内部实现。同样的,如果我们想要修改这个函数的内部实现也不用担心会影响到对应的URL。此外,如果我们想要输出这个函数到一些URL,我们只需要修改URL配置而不用去改动视图的代码。
Django大量应用松耦合。我们将在本书中继续给出这一重要哲学的相关例子。
404 错误
在我们当前的这个URL配置中,我们之定义了一个URL模式:处理URL/time/。当请求其他URL会怎么样呢?
让我们试试看,运行Django开发服务器并访问类似http://127.0.0.1:8000/hello/或者http://127.0.0.1:8000/does-not-exist/,甚至http://127.0.0.1:8000/(网站根目录)。你将会看到一个
“Page not found” 页面(图 3-2)。(挺漂亮的,是吧?你会喜欢上我们的配色方案的;-)如果请求的URL没有在URL配置里设置,Django就会显示这个页面。
图 3-2. Django的 404页面
这个页面的功能不只是显示404的基本错误信息,它同样精确的告诉你Django使用了哪个URL配置和这个配置里的每一个模式。这样,你应该能了解到为什么这个请求会抛出404错误。
当然,这些敏感的信息应该只呈现给你-开发者。如果是部署到了因特网上的站点就不应该暴露这些信息。出于这个考虑,这个“Page not found”页面只会在调试模式(debug
mode)下显示。我们将在以后说明怎么关闭调试模式。现在,你只需要知道所有的Django项目在创建后都是在调试模式下的,如果关闭了调试模式,结果将会不一样。
第二个视图:动态URL
在我们的第一个视图范例中,尽管内容是动态的,但是URL(/time/)是静态的。在大多数动态web应用程序,URL通常都包含有相关的参数。
让我们创建第二个视图来显示当前时间和加上时间偏差量的时间,设计是这样的:/time/plus/1/显示当前时间+1个小时的页面/time/plus/2/显示当前时间+2个小时的页面/time/plus/3/显示当前时间+3个小时的页面,以此类推。
新手可能会考虑写不同的视图函数来处理每个时间偏差量,URL配置看起来就象这样:
urlpatterns = patterns(‘‘,
(r‘^time/$‘, current_datetime),
(r‘^time/plus/1/$‘, one_hour_ahead),
(r‘^time/plus/2/$‘, two_hours_ahead),
(r‘^time/plus/3/$‘, three_hours_ahead),
(r‘^time/plus/4//$‘, four_hours_ahead),
)
很明显,这样处理是不太妥当的。不但有很多冗余的视图函数,而且整个应用也被限制了只支持预先定义好的时间段,2小时,3小时,或者4小时。如果哪天我们要实现5
小时,我们就不得不再单独创建新的视图函数和配置URL,既重复又混乱。我们需要在这里做一点抽象,提取一些共同的东西出来。
关于漂亮URL的一点建议
如果你有其他Web开发平台的经验,例如PHP或者JAVA,你可能会想,好吧,让我们来用一个查询字符串参数来表示它们吧,例如/time/plus?hours=3,哪个时间段用hours参数代表,URL的查询字符串(query
string)是URL里?后面的字符串。
你可以在Django里也这样做 (如果你真的想要这样做,我们稍后会告诉你怎么做),但是Django的一个核心理念就是URL必须看起来漂亮。URL/time/plus/3/更加清晰,更简单,也更有可读性,可以很容易的大声念出来,因为它是纯文本,没有查询字符串那么复杂。漂亮的URL就像是高质量的Web应用的一个标志。
Django的URL配置系统可以使你很容易的设置漂亮的URL,而尽量不要考虑它的反面。
带通配符的URL匹配模式
继续我们的hours_ahead范例,让我们在URL模式里使用通配符。我们前面讲到,URL模式是一个正则表达式,因此,我们可以使用正则表达式模式\d+来匹配一个或多个数字:
from django.conf.urls.defaults import *
from mysite.views import current_datetime, hours_ahead
urlpatterns = patterns(‘‘,
(r‘^time/$‘, current_datetime),
(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),
备注
在建造Web应用的时候,尽可能多考虑可能的数据输入是很重要的,然后决定哪些我们可以接受。在这里我们就设置了99个小时的时间段限制。
现在我们已经设计了一个带通配符的URL,我们需要一个方法把它传递到视图函数里去,这样我们只用一个视图函数就可以处理所有的时间段了。我们使用圆括号把参数在URL模式里标识出来。在这个例子中,我们想要把这些数字作为参数,用圆括号把\d{1,2}包围起来:
(r‘^time/plus/(\d{1,2})/$‘, hours_ahead),
如果你熟悉正则表达式,那么你应该已经了解,正则表达式也是用圆括号来从文本里提取数据的。
最终的current_datetimeURLconf,包含我们前面的视图,看起来像这样:
from django.conf.urls.defaults import *
from mysite.views import current_datetime, hours_ahead
urlpatterns = patterns(‘‘,
(r‘^time/$‘, current_datetime),
(r‘^time/plus/(\d{1,2})/$‘, hours_ahead),
)
现在开始写hours_ahead视图。
编码次序
这个例子中,我们先写了URLpattern,然后是视图,但是在前面的例子中,我们先写了视图,然后是URLpattern。哪种技术更好?嗯,怎么说呢,每个开发者是不一样的。
如果你是喜欢从总体上来把握事物(注:或译为“大局观”)类型的人,你应该会想在项目开始的时候就写下所有的URL配置。这会给你带来一些好处,例如,给你一个清晰的to-do列表,让你更好的定义视图所需的参数。
如果你从更像是一个自底向上的开发者,你可能更喜欢先写视图,然后把它们挂接到URL上。这同样是可以的。
最后,取决与你喜欢那种技术,两种方法都是可以的。
hours_ahead和我们以前写的current_datetime很象,关键的区别在于:它多了一个额外参数,时间差。views.py修改如下:
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)
让我们一次一行通一下这些代码:
就像我们在我们的current_datetime视图中所作的一样,我们导入django.http.HttpResponse类和datetime模块。
视图函数,hours_ahead,有两个参数:request和offset.
request是一个HttpRequest对象,就像在current_datetime中一样.再说一次好了:
每一个视图总是以一个HttpRequest对象作为它的第一个参数。
offset是从匹配的URL里提取出来的。例如:如果URL是/time/plus/3/那么offset是字符串‘3‘,如果URL是/time/plus/21/,那么offset是字符串‘21‘,注意,提取的字符串总是字符串,不是整数,即便都是数字组成,就象‘21‘。
在这里我们命名变量为offset,你也可以任意命名它,只要符合Python的语法。变量名是无关紧要的,重要的是它的位置,它是这个函数的第二个参数
(在request的后面)。你还可以使用关键字来定义它,而不是用位置。详情请看第八章。
我们在这个函数中要做的第一件事情就是在offset上调用int().这会把这个字符串值转换为整数。
注意Python可能会在你调用int()来转换一个不能转换成整数时抛出ValueError异常,例如字符串‘foo‘。当然,在这个范例中我们不用担心这个问题,因为我们已经确定offset是只包含数字字符的字符串。因为正则表达式(\d{1,2})只提取数字字符。这也是URL配置的另一个好处:提供了清晰的输入数据有效性确认。
下一行显示了我们为什么调用int()来转换offset。这一行我们要计算当前时间加上这个时间差offset小时,保存结果到变量dt。datetime.timedelta函数的参数hours必须是整数类型。
这行和前面的那行的的一个微小差别就是,它使用带有两个值的Python的格式化字符串功能,而不仅仅是一个值。因此,在字符串中有两个%s符号和一个以进行插入的值的元组:(offset,
dt)。
最后,我们再一次返回一个HTML的HttpResponse,就像我们在current_datetime做的一样。
在完成视图函数和URL配置编写后,启动Django开发服务器,用浏览器访问http://127.0.0.1:8000/time/plus/3/来确认它工作正常。然后是http://127.0.0.1:8000/time/plus/5/。再然后是http://127.0.0.1:8000/time/plus/24/。最后,访问http://127.0.0.1:8000/time/plus/100/来检验URL配置里设置的模式是否只接受一个或两个数字;Django会显示一个
Page not found error 页面,和以前看到的 404
错误一样。访问URLhttp://127.0.0.1:8000/time/plus/(没有定义时间差)也会抛出404错误。
你现在已经注意到views.py文件中包含了两个视图,views.py看起来象这样:
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
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)
Django 漂亮的出错页面
花几分钟时间欣赏一下我们写好的Web应用程序,然后我们再来搞点小破坏。我们故意在views.py文件中引入一项
Python 错误,注释掉hours_ahead视图中的offset = int(offset)一行。
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)
启动开发服务器,然后访问/time/plus/3/。你会看到一个包含大量信息的出错页,最上面的一条TypeError信息是:"unsupported
type for timedelta hours component: str"。
怎么回事呢?是的,datetime.timedelta函数要求hours参数必须为整型,而我们注释掉了将offset转为整型的代码。这样导致datetime.timedelta弹出TypeError异常。这是所有程序员某个时候都可能碰到的一种典型错误。
这个例子是为了展示 Django的出错页面。我们来花些时间看一看这个出错页,了解一下其中给出了哪些信息。
以下是值得注意的一些要点:
在页面顶部,你可以得到关键的异常信息:异常数据类型、异常的参数 (如本例中的"unsupported type")、在哪个文件中引发了异常、出错的行号等等。
在关键异常信息下方,该页面显示了对该异常的完整 Python追踪信息。这类似于你在 Python命令行解释器中获得的追溯信息,只不过后者更具交互性。对栈中的每一帧,Django均显示了其文件名、函数或方法名、行号及该行源代码。
点击该行代码 (以深灰色显示),你可以看到出错行的前后几行,从而得知相关上下文情况。
点击栈中的任何一帧的“Local vars”可以看到一个所有局部变量的列表,以及在出错那一帧时它们的值。这些调试信息是无价的。
注意“Traceback”下面的“Switch to copy-and-paste view”文字。点击这些字,追溯会切换另一个视图,它让你很容易地复制和粘贴这些内容。当你想同其他人分享这些异常追溯以获得技术支持时(比如在
Django 的 IRC聊天室或邮件列表中),可以使用它。
接下来的“Request information”部分包含了有关产生错误的 Web请求的大量信息:
GET和 POST、cookie值、元数据(象 CGI头)。在附录H里给出了request的对象的完整参考。
Request信息的下面,“Settings”列出了 Django使用的具体配置信息。同样在附录E给出了settings配置的完整参考。现在,大概浏览一下,对它们有个大致印象就好了。
Django 的出错页某些情况下有能力显示更多的信息,比如模板语法错误。我们讨论 Django模板系统时再说它们。现在,取消offset = int(offset)这行的注释,让它重新正常工作。
不知道你是不是那种使用小心放置的print语句来帮助调试的程序员?你其实可以用 Django出错页来做这些,而不用print语句。在你视图的任何位置,临时插入一个assert
False来触发出错页。然后,你就可以看到局部变量和程序语句了。(还有更高级的办法来调试 Django
视图,我们后来再说,但这个是最快捷最简单的办法了。)
最后,很显然这些信息很多是敏感的,它暴露了你 Python代码的内部结构以及 Django配置,在
Internet 上公开这信息是很愚蠢的。不怀好意的人会尝试使用它攻击你的 Web应用程序,做些下流之事。因此,Django出错信息仅在
debug 模式下才会显现。我们稍后说明如何禁用 debug模式。现在,你只要知道 Django服务器在你开启它时默认运行在
debug模式就行了。(听起来很熟悉?“Page not found”错误,“404错误”一节也这样描述过。)
转载请注明文章出处:http://blog.csdn.net/wolaiye320/article/details/51819151