| ID | English原文 | 中文翻译 | 最近翻译记录 | 状态 | 操作 |
|---|---|---|---|---|---|
| 0#翻译 | Chapter 3: Views and URLconfs | 第三章:视图和URL配置 | 翻译 | ||
| 3#翻译 | In the previous chapter, we explained how to set up a Django project and run the Django development server. | 前一章中,我们解释了如何建立一个 Django 项目并运行 Django 开发服务器。 | 翻译 | ||
| 4#翻译 | In this chapter, you'll learn the basics of creating dynamic Web pages with Django. | 在这一章,你将会学到用Django创建动态网页的基本知识。 | 翻译 | ||
| 6#翻译 | Your First Django-Powered Page: | 你的第一个Django驱动的页面: | 翻译 | ||
| 7#翻译 | Hello World | Hello World | 翻译 | ||
| 9#翻译 | As our first goal, let's create a Web page that outputs that famous example message: | 作为我们的第一个目标,让我们创建一个网页,用来输出这个著名的示例消息: | 翻译 | ||
| 10#翻译 | Hello world. | Hello world. | 翻译 | ||
| 12#翻译 | If you were publishing a simple Hello world Web page without a Web framework, you'd simply type Hello world into a text file, call it <literal>hello.html</literal> , and upload it to a directory on a Web server somewhere. | 如果你不使用网页框架来发布一个Hello world页面,只要简单的在一个文本文件中输入Hello World,然后将其命名为<literal>hello.html</literal>,再上传到任意的一个网页服务器上就行了。 | 翻译 | ||
| 13#翻译 | Notice, in that process, you've specified two key pieces of information about that Web page: | 注意,在这个过程中,你已经说明了两个关于这个网页的关键信息: | 翻译 | ||
| 14#翻译 | its contents (the string <literal>"Hello world"</literal> ) and its URL ( <literal>http://www.example.com/hello.html</literal> , or maybe <literal>http://www.example.com/files/hello.html</literal> if you put it in a subdirectory). | 它包括(字符串 <literal>"Hello world"</literal>)和它的URL( <literal>http://www.example.com/hello.html</literal> , 如果你把文件放在子目录,也可能是 <literal>http://www.example.com/files/hello.html</literal>)。 | 翻译 | ||
| 16#翻译 | With Django, you specify those same two things, but in a different way. | 使用Django的话,你会用不同的方法来说明这两件事。 | 翻译 | ||
| 17#翻译 | The contents of the page are produced by a <emphasis>view function</emphasis> , and the URL is specified in a <emphasis>URLconf</emphasis> . First, let's write our Hello world view function. | 页面的内容由<emphasis>view function(视图函数)</emphasis> 产生,URL定义在 <emphasis>URLconf</emphasis> 中。首先,我们先写一个Hello world视图函数。 | 翻译 | ||
| 19#翻译 | Your First View | 第一份视图: | 翻译 | ||
| 21#翻译 | Within the <literal>mysite</literal> directory that <literal>django-admin.py startproject</literal> made in the last chapter, create an empty file called <literal>views.py</literal> . This Python module will contain our views for this chapter. | 在上一章使用<literal>django-admin.py startproject</literal>生成的<literal>mysite</literal>文件夹中,创建一个叫做<literal>views.py</literal>的空文件。这一Python模块将包含本章中我们使用的视图。 | 翻译 | ||
| 22#翻译 | Note that there's nothing special about the name <literal>views.py</literal> Django doesn't care what the file is called, as you'll see in a bit but it's a good idea to call it <literal>views.py</literal> as a convention, for the benefit of other developers reading your code. | 请留意,Django对于<literal>views.py</literal> 的文件名没有特别的要求,它并不在乎这个文件叫什么。但是作为约定(有利于其他开发者读懂你的代码),把它命名成views.py确实是个好主意。 | 翻译 | ||
| 24#翻译 | Our Hello world view is simple. | 我们的Hello world视图非常简单。 | 翻译 | ||
| 25#翻译 | Here's the entire function, plus import statements, which you should type into the <literal>views.py</literal> file: | 这就是你需要键入到<literal>views.py</literal>文件中的整个函数和导入声明: | 翻译 | ||
| 28#翻译 | Let's step through this code one line at a time: | 我们逐行逐句地分析一遍这段代码: | 翻译 | ||
| 30#翻译 | First, we import the class <literal>HttpResponse</literal> , which lives in the <literal>django.http</literal> module. | 首先,我们从 <literal>django.http</literal> 模块中导入(import) <literal>HttpResponse</literal> 类。 | 翻译 | ||
| 31#翻译 | We need to import this class because it's used later in our code. | 我们需要导入这些类,因为我们会在后面用到。 | 翻译 | ||
| 33#翻译 | Next, we define a function called <literal>hello</literal> the view function. | 接下来,我们定义一个叫做<literal>hello</literal> 的视图函数。 | 翻译 | ||
| 35#翻译 | Each view function takes at least one parameter, called <literal>request</literal> by convention. | 每个视图函数至少要有一个参数,通常被叫作<literal>request</literal>。 | 翻译 | ||
| 36#翻译 | This is an object that contains information about the current Web request that has triggered this view, and it's an instance of the class <literal>django.http.HttpRequest</literal> . In this example, we don't do anything with <literal>request</literal> , but it must be the first parameter of the view nonetheless. | 这是一个包含触发此视图的当前Web请求信息的对象,并且它是<literal>django.http.HttpRequest</literal>类的一个实例。在这个示例中,我们虽然不用<literal>request</literal>做任何事情,但它仍必须是这个视图的第一个参数。 | 翻译 | ||
| 38#翻译 | Note that the name of the view function doesn't matter; it doesnt have to be named in a certain way in order for Django to recognize it. | 注意视图函数的名称并不重要;并不一定非得以某种特定的方式命名才能让 Django 识别它。 | 翻译 | ||
| 39#翻译 | We're calling it <literal>hello</literal> here, because that name clearly indicates the gist of the view, but it could just as well be named <literal>hello_wonderful_beautiful_world</literal> , or something equally revolting. | 在这里我们把它命名为:hello,是因为这个名称清晰的显示了视图的用途。当然,你也可以叫它:hello_wonderful_beautiful_world,或其它类似的啰嗦形式。 | 翻译 | ||
| 40#翻译 | The next section, Your First URLconf, will shed light on how Django finds this function. | 在下一小节: 你的第一个 URLconf,将聚焦在Django是如何找到这个函数的。 | 翻译 | ||
| 42#翻译 | The function is a simple one-liner: | 这个函数只有简单的一行代码: | 翻译 | ||
| 43#翻译 | it merely returns an <literal>HttpResponse</literal> object that has been instantiated with the text <literal>"Hello world"</literal> . | 它仅仅返回一个HttpResponse对象,此处用文本“Hello world”做了个实例。 | 翻译 | ||
| 45#翻译 | The main lesson here is this: | 这里主要讲的是: | 翻译 | ||
| 46#翻译 | a view is just a Python function that takes an <literal>HttpRequest</literal> as its first parameter and returns an instance of <literal>HttpResponse</literal> . In order for a Python function to be a Django view, it must do these two things. | 视图不过是一个Python函数,它采用HttpRequest作为它的第一个参数并且返回一个HttpResponse的实例。为了使一个Python函数成为一个Django视图,它必须干这俩件事。 | 翻译 | ||
| 47#翻译 | (There are exceptions, but we'll get to those later.) | (也有例外,但是我们稍后才会接触到。) | 翻译 | ||
| 49#翻译 | Your First URLconf | 你的第一个URLconf | 翻译 | ||
| 51#翻译 | If, at this point, you ran <literal>python manage.py runserver</literal> again, you'd still see the Welcome to Django message, with no trace of our Hello world view anywhere. | 现在,如果你再运行:python manage.py runserver,你还将看到Django的欢迎页面,而不是我们刚才写的Hello world视图。 | 翻译 | ||
| 52#翻译 | That's because our <literal>mysite</literal> project doesn't yet know about the <literal>hello</literal> view; we need to tell Django explicitly that we're activating this view at a particular URL. | 那是因为我们的mysite项目还对hello视图一无所知。我们需要明确地告诉Django: 我们要用一个特定的URL来激活这个视图。 | 翻译 | ||
| 53#翻译 | (Continuing our previous analogy of publishing static HTML files, at this point we've created the HTML file but haven't uploaded it to a directory on the server yet.) To hook a view function to a particular URL with Django, use a URLconf. | (继续我们刚才类似发布静态HTML文件的例子。现在我们已经创建了HTML文件,但还没有把它上传至服务器的目录。)为了在Django中绑定视图函数和URL,我们使用一个URLconf。 | 翻译 | ||
| 55#翻译 | A <emphasis>URLconf</emphasis> is like a table of contents for your Django-powered Web site. | <emphasis> URLconf</emphasis> 就好像是基于Django的Web站点的一张内容表。 | 翻译 | ||
| 56#翻译 | Basically, it's a mapping between URLs and the view functions that should be called for those URLs. | 它本质上是 URL 模式以及要为该 URL 模式调用的视图函数之间的映射表。 | 翻译 | ||
| 57#翻译 | It's how you tell Django, For this URL, call this code, and for that URL, call that code. | 你就是以这种方式告诉 Django,对于这个 URL 调用这段代码,对于那个 URL 调用那段代码。 | 翻译 | ||
| 58#翻译 | For example, When somebody visits the URL <literal>/foo/</literal> , call the view function <literal>foo_view()</literal> , which lives in the Python module <literal>views.py</literal> . | 例如,当用户访问/foo/时,调用视图函数foo_view(),这个视图函数存在于Python模块文件views.py中。 | 翻译 | ||
| 60#翻译 | When you executed <literal>django-admin.py startproject</literal> in the previous chapter, the script created a URLconf for you automatically: | 前一章中执行 <literal>django-admin.py startproject</literal> 时,该脚本会自动为你建了一份 URLconf(即 <literal>urls.py</literal> 文件)。 | 翻译 | ||
| 61#翻译 | the file <literal>urls.py</literal> . By default, it looks something like this: | 默认的urls.py会像下面这个样子: | 翻译 | ||
| 64#翻译 | This default URLconf includes some commonly used Django features commented out, so that activating those features is as easy as uncommenting the appropriate lines. | 默认的URLconf包含了一些被注释起来的Django常用的功能,只需去掉这些注释就可以开启这些功能. | 翻译 | ||
| 65#翻译 | If we ignore the commented-out code, here's the essence of a URLconf: | 下面是URLconf中忽略被注释的行后的实际内容 | 翻译 | ||
| 68#翻译 | Let's step through this code one line at a time: | 让我们逐行解释一下代码: | 翻译 | ||
| 70#翻译 | The first line imports all objects from the <literal>django.conf.urls.defaults</literal> module, which is Django's URLconf infrastructure. | 第一行导入django.conf.urls.defaults下的所有模块,它们是Django URLconf的基本构造。 | 翻译 | ||
| 71#翻译 | This includes a function called <literal>patterns</literal> . | 这包含了一个patterns函数。 | 翻译 | ||
| 73#翻译 | The second line calls the function <literal>patterns</literal> and saves the result into a variable called <literal>urlpatterns</literal> . The <literal>patterns</literal> function gets passed only a single argument the empty string. | 第二行调用 <literal>patterns()</literal> 函数并将返回结果保存到 <literal>urlpatterns</literal> 变量。patterns函数当前只有一个参数--一个空的字符串。 | 翻译 | ||
| 74#翻译 | (The string can be used to supply a common prefix for view functions, which we'll cover in Chapter 8.) | (这个字符串可以被用来表示一个视图函数的通用前缀。具体我们将在第八章里面介绍。) | 翻译 | ||
| 76#翻译 | The main thing to note here is the variable <literal>urlpatterns</literal> , which Django expects to find in your URLconf module. | 当前应该注意是 <literal>urlpatterns</literal> 变量, Django 期望能从 URLconf 模块中找到它。 | 翻译 | ||
| 77#翻译 | This variable defines the mapping between URLs and the code that handles those URLs. | 该变量定义了 URL 以及用于处理这些 URL 的代码之间的映射关系。 | 翻译 | ||
| 78#翻译 | By default, as we can see, the URLconf is empty your Django application is a blank slate. | 默认情况下,URLconf 所有内容都被注释起来了——Django 应用程序还是白版一块。 | 翻译 | ||
| 79#翻译 | (As a side note, that's how Django knew to show you the Welcome to Django page in the last chapter. | (注:那是上一节中Django怎么知道显示欢迎页面的原因。 | 翻译 | ||
| 80#翻译 | If your URLconf is empty, Django assumes you just started a new project and, hence, displays that message.) | 如果 URLconf 为空,Django 会认定你刚创建好新项目,因此也就显示那个欢迎信息。) | 翻译 | ||
| 82#翻译 | To add a URL and view to the URLconf, just add a Python tuple mapping a URL pattern to the view function. | 如果想在URLconf中加入URL和view,只需增加映射URL模式和view功能的Python 元组即可. | 翻译 | ||
| 83#翻译 | Here's how to hook in our <literal>hello</literal> view: | 这里是演示如何在我们的 <literal>hello</literal> 视图中挂上 url. | 翻译 | ||
| 86#翻译 | (Note that we've removed the commented-out code for brevity. | (请留意:为了简洁,我们移除了注释代码。 | 翻译 | ||
| 87#翻译 | You can choose to leave those lines in, if you'd like.) | 如果你喜欢的话,你可以保留那些行。) | 翻译 | ||
| 89#翻译 | We made two changes here: | 我们改了两处。 | 翻译 | ||
| 91#翻译 | First, we imported the <literal>hello</literal> view from its module <literal>mysite/views.py</literal> , which translates into <literal>mysite.views</literal> in Python import syntax. | 首先,我们从模块 <literal>mysite/views.py</literal> 中引入了 <literal>hello</literal> 视图。(在 Python 的 import 语法中, <literal>mysite/views.py</literal> 转译为 <literal>mysite.views</literal> ) | 翻译 | ||
| 92#翻译 | (This assumes <literal>mysite/views.py</literal> is on your Python path; see the sidebar for details.) | (这假设mysite/views.py在你的Python搜索路径上。关于搜索路径的解释,请参照下文。) | 翻译 | ||
| 94#翻译 | Next, we added the line <literal>('^hello/$', hello),</literal> to <literal>urlpatterns</literal> . This line is referred to as a <emphasis>URLpattern</emphasis> . It's a Python tuple in which the first element is a pattern-matching string (a regular expression; more on this in a bit) and the second element is the view function to use for that pattern. | 接下来,我们为urlpatterns加上一行: ('^hello/$', hello), 这行被称作URLpattern,它是一个Python的元组。元组中第一个元素是模式匹配字符串(正则表达式);第二个元素是那个模式将使用的视图函数。 | 翻译 | ||
| 96#翻译 | In a nutshell, we just told Django that any request to the URL <literal>/hello/</literal> should be handled by the <literal>hello</literal> view function. | 简单来说,我们只是告诉 Django,所有指向 URL <literal>/hello/</literal> 的请求都应由 <literal>hello</literal> 这个视图函数来处理。 | 翻译 | ||
| 98#翻译 | Your Python Path | Python 搜索路径 | 翻译 | ||
| 100#翻译 | Your <emphasis>Python path</emphasis> is the list of directories on your system where Python looks when you use the Python <literal>import</literal> statement. | <emphasis>Python 搜索路径</emphasis> 就是使用 <literal>import</literal> 语句时,Python 所查找的系统目录清单。 | 翻译 | ||
| 102#翻译 | For example, let's say your Python path is set to <literal>['', '/usr/lib/python2.4/site-packages', '/home/username/djcode']</literal> . If you execute the Python statement <literal>from foo import bar</literal> , Python will look for a module called <literal>foo.py</literal> in the current directory. | 举例来说,假定你将 Python 路径设置为 <literal>['','/usr/lib/python2.4/site-packages','/home/username/djcode/']</literal> 。如果执行代码 <literal>from foo import bar</literal> ,Python 将会首先在当前目录查找 <literal>foo.py</literal> 模块( Python 路径第一项的空字符串表示当前目录)。 | 翻译 | ||
| 103#翻译 | (The first entry in the Python path, an empty string, means the current directory.) If that file doesn't exist, Python will look for the file <literal>/usr/lib/python2.4/site-packages/foo.py</literal> . If that file doesn't exist, it will try <literal>/home/username/djcode/foo.py</literal> . Finally, if <emphasis>that</emphasis> file doesn't exist, it will raise <literal>ImportError</literal> . | 如果文件不存在,Python将查找 <literal>/usr/lib/python2.4/site-packages/foo.py</literal> 文件。如果仍然不存在,Python会尝试<literal>/home/username/djcode/foo.py</literal>。最后,如果还是找不到,Python会抛出一个<literal>ImportError</literal>异常。 | 翻译 | ||
| 105#翻译 | If you're interested in seeing the value of your Python path, start the Python interactive interpreter and type this: | 如果你想看Python搜索路径的值,运行Python交互解释器,然后输入: | 翻译 | ||
| 108#翻译 | Generally you don't have to worry about setting your Python path Python and Django take care of things for you automatically behind the scenes. | 通常,你不必关心 Python 搜索路径的设置。Python 和 Django 会在后台自动帮你处理好。 | 翻译 | ||
| 109#翻译 | (Setting the Python path is one of the things that the <literal>manage.py</literal> script does.) | (设置Python路径是<literal>manage.py</literal>脚本完成的工作之一。) | 翻译 | ||
| 111#翻译 | It's worth discussing the syntax of this URLpattern, as it may not be immediately obvious. | 讨论一下URLpattern的语法是值得的,因为它不是显而易见的。 | 翻译 | ||
| 112#翻译 | Although we want to match the URL <literal>/hello/</literal> , the pattern looks a bit different than that. | 虽然我们想匹配地址/hello/,但是模式看上去与这有点差别。 | 翻译 | ||
| 113#翻译 | Here's why: | 这就是为什么: | 翻译 | ||
| 115#翻译 | Django removes the slash from the front of every incoming URL before it checks the URLpatterns. | Django在检查URL模式前,移除每一个申请的URL开头的斜杠(/)。 | 翻译 | ||
| 116#翻译 | This means that our URLpattern doesn't include the leading slash in <literal>/hello/</literal> . (At first, this may seem unintuitive, but this requirement simplifies things such as the inclusion of URLconfs within other URLconfs, which we'll cover in Chapter 8.) | 这意味着我们为/hello/写URL模式不用包含斜杠(/)。(刚开始,这样可能看起来不直观,但这样的要求简化了许多工作,如URL模式内嵌,我们将在第八章谈及。) | 翻译 | ||
| 118#翻译 | The pattern includes a caret (<literal>^</literal> ) and a dollar sign (<literal>$</literal> ). These are regular expression characters that have a special meaning: | 模式包含了一个尖号(^)和一个美元符号($)。这些都是正则表达式符号,并且有特定的含义: | 翻译 | ||
| 119#翻译 | the caret means require that the pattern matches the start of the string, and the dollar sign means require that the pattern matches the end of the string. | 上箭头要求表达式对字符串的头部进行匹配,美元符号则要求表达式对字符串的尾部进行匹配。 | 翻译 | ||
| 121#翻译 | This concept is best explained by example. | 最好还是用范例来说明一下这个概念。 | 翻译 | ||
| 122#翻译 | If we had instead used the pattern <literal>'^hello/'</literal> (without a dollar sign at the end), then <emphasis>any</emphasis> URL starting with <literal>/hello/</literal> would match, such as <literal>/hello/foo</literal> and <literal>/hello/bar</literal> , not just <literal>/hello/</literal> . Similarly, if we had left off the initial caret character (i.e., <literal>'hello/$'</literal> ), Django would match <emphasis>any</emphasis> URL that ends with <literal>hello/</literal> , such as <literal>/foo/bar/hello/</literal> . If we had simply used <literal>hello/</literal> , without a caret <emphasis>or</emphasis> dollar sign, then any URL containing <literal>hello/</literal> would match, such as <literal>/foo/hello/bar</literal> . Thus, we use both the caret and dollar sign to ensure that only the URL <literal>/hello/</literal> matches nothing more, nothing less. | 如果我们用尾部不是$的模式'^hello/',那么任何以/hello/开头的URL将会匹配,例如:/hello/foo 和/hello/bar,而不仅仅是/hello/。类似地,如果我们忽略了尖号(^),即'hello/$',那么任何以hello/结尾的URL将会匹配,例如:/foo/bar/hello/。如果我们简单使用hello/,即没有^开头和$结尾,那么任何包含hello/的URL将会匹配,如:/foo/hello/bar。因此,我们使用这两个符号以确保只有/hello/匹配,不多也不少。 | 翻译 | ||
| 124#翻译 | Most of your URLpatterns will start with carets and end with dollar signs, but it's nice to have the flexibility to perform more sophisticated matches. | 你大多数的URL模式会以^开始、以$结束,但是拥有复杂匹配的灵活性会更好。 | 翻译 | ||
| 126#翻译 | You may be wondering what happens if someone requests the URL <literal>/hello</literal> (that is, <emphasis>without</emphasis> a trailing slash). | 你可能会问:如果有人申请访问/hello(尾部没有斜杠/)会怎样。 | 翻译 | ||
| 127#翻译 | Because our URLpattern requires a trailing slash, that URL would <emphasis>not</emphasis> match. | 因为我们的URL模式要求尾部有一个斜杠(/),那个申请URL将不匹配。 | 翻译 | ||
| 128#翻译 | However, by default, any request to a URL that <emphasis>doesn't</emphasis> match a URLpattern and <emphasis>doesn't</emphasis> end with a slash will be redirected to the same URL with a trailing slash. | 然而,默认地,任何不匹配或尾部没有斜杠(/)的申请URL,将被重定向至尾部包含斜杠的相同URL。 | 翻译 | ||
| 129#翻译 | (This is regulated by the <literal>APPEND_SLASH</literal> Django setting, which is covered in Appendix D.) | (这是受配置文件setting中APPEND_SLASH项控制的,参见附件D。) | 翻译 | ||
| 131#翻译 | If you're the type of person who likes all URLs to end with slashes (which is the preference of Django's developers), all youll need to do is add a trailing slash to each URLpattern and leave <literal>APPEND_SLASH</literal> set to <literal>True</literal> . If you prefer your URLs <emphasis>not</emphasis> to have trailing slashes, or if you want to decide it on a per-URL basis, set <literal>APPEND_SLASH</literal> to <literal>False</literal> and put trailing slashes in your URLpatterns as you see fit. | 如果你是喜欢所有URL都以'/'结尾的人(Django开发者的偏爱),那么你只需要在每个URL后添加斜杠,并且设置"APPEND_SLASH"为"True". 如果不喜欢URL以斜杠结尾或者根据每个URL来决定,那么需要设置"APPEND_SLASH"为"False",并且根据你自己的意愿来添加结尾斜杠/在URL模式后. | 翻译 | ||
| 133#翻译 | The other thing to note about this URLconf is that we've passed the <literal>hello</literal> view function as an object without calling the function. | 另外需要注意的是,我们把hello视图函数作为一个对象传递,而不是调用它。 | 翻译 | ||
| 134#翻译 | This is a key feature of Python (and other dynamic languages): | 这是 Python (及其它动态语言的) 的一个重要特性: | 翻译 | ||
| 135#翻译 | functions are first-class objects, which means you can pass them around just like any other variables. | 函数是一级对象(first-class objects), 也就是说你可以像传递其它变量一样传递它们。 | 翻译 | ||
| 136#翻译 | Cool stuff, eh? | 很酷吧? | 翻译 | ||
| 138#翻译 | To test our changes to the URLconf, start the Django development server, as you did in Chapter 2, by running the command <literal>python manage.py runserver</literal> . (If you left it running, that's fine, too. | 现在我们来测试修改好的 URLconf, 像第二章一样,运行命令<literal>python manage.py runserver</literal> 以启动服务器。 (如果你让它一直运行也可以。 | 翻译 | ||
| 139#翻译 | The development server automatically detects changes to your Python code and reloads as necessary, so you don't have to restart the server between changes.) The server is running at the address <literal>http://127.0.0.1:8000/</literal> , so open up a Web browser and go to <literal>http://127.0.0.1:8000/hello/</literal> . You should see the text Hello world the output of your Django view. | 开发服务器将自动检测Python代码的变动来做必要的重新加载, 所以你不需要在更改代码之后重启服务器。)服务器运行地址是<literal> http://127.0.0.1:8000/</literal> ,所以打开浏览器直接输入<literal> http://127.0.0.1:8000/hello/</literal> ,你将看到由你的Django视图输出的Hello world。 | 翻译 | ||
| 141#翻译 | Hooray! | 万岁! | 翻译 | ||
| 142#翻译 | You've made your first Django-powered Web page. | 你已经创建了第一个Django的Web页面。 | 翻译 | ||
| 144#翻译 | Regular Expressions | 正则表达式 | 翻译 | ||
| 146#翻译 | <emphasis>Regular expressions</emphasis> (or <emphasis>regexes</emphasis> ) are a compact way of specifying patterns in text. | <emphasis>正则表达式</emphasis> (或 <emphasis>regexes</emphasis> ) 是通用的文本模式匹配的方法。 | 翻译 | ||
| 147#翻译 | While Django URLconfs allow arbitrary regexes for powerful URL matching, you'll probably only use a few regex symbols in practice. | Django URLconfs 允许你 使用任意的正则表达式来做强有力的URL映射,不过你实际上可能只需要使用很少的一 部分功能。 | 翻译 | ||
| 148#翻译 | Here's a selection of common symbols: | 这里是一些基本的语法。 | 翻译 | ||
| 150#翻译 | <table><tgroup cols="2"><colspec colwidth="12"/><colspec colwidth="68"/><thead><row><entry> | <table><tgroup cols="2"><colspec colwidth="12"/><colspec colwidth="68"/><thead><row><entry> | 翻译 | ||
| 151#翻译 | Symbol | 符号 | 翻译 | ||
| 153#翻译 | Matches | 匹配 | 翻译 | ||
| 155#翻译 | <literal>.</literal> (dot) | <literal>.</literal> (dot) | 翻译 | ||
| 157#翻译 | Any single character | 任意单一字符 | 翻译 | ||
| 159#翻译 | <literal>\d</literal> | <literal>\d</literal> | 翻译 | ||
| 161#翻译 | Any single digit | 任意一位数字 | 翻译 | ||
| 163#翻译 | <literal>[A-Z]</literal> | <literal>[A-Z]</literal> | 翻译 | ||
| 165#翻译 | Any character between <literal>A</literal> and <literal>Z</literal> (uppercase) | <literal>A</literal> 到 <literal>Z</literal>中任意一个字符(大写) | 翻译 | ||
| 167#翻译 | <literal>[a-z]</literal> | <literal>[a-z]</literal> | 翻译 | ||
| 169#翻译 | Any character between <literal>a</literal> and <literal>z</literal> (lowercase) | <literal>a</literal> 到 <literal>z</literal>中任意一个字符(小写) | 翻译 | ||
| 171#翻译 | <literal>[A-Za-z]</literal> | <literal>[A-Za-z]</literal> | 翻译 | ||
| 173#翻译 | Any character between <literal>a</literal> and <literal>z</literal> (case-insensitive) | <literal>a</literal> 到 <literal>z</literal>中任意一个字符(不区分大小写) | 翻译 | ||
| 175#翻译 | <literal>+</literal> | <literal>+</literal> | 翻译 | ||
| 177#翻译 | One or more of the previous expression (e.g., <literal>\d+</literal> matches one or more digits) | 匹配一个或更多 (例如, <literal>\d+</literal> 匹配一个或 多个数字字符) | 翻译 | ||
| 179#翻译 | <literal>[^/]+</literal> | <literal>[^/]+</literal> | 翻译 | ||
| 181#翻译 | One or more characters until (and not including) a forward slash | 一个或多个不为‘/’的字符 | 翻译 | ||
| 183#翻译 | <literal>?</literal> | <literal>?</literal> | 翻译 | ||
| 185#翻译 | Zero or one of the previous expression (e.g., <literal>\d?</literal> | 零个或一个之前的表达式(例如:<literal>\d?</literal> | 翻译 | ||
| 186#翻译 | matches zero or one digits) | 匹配零个或一个数字) | 翻译 | ||
| 188#翻译 | <literal>*</literal> | <literal>*</literal> | 翻译 | ||
| 190#翻译 | Zero or more of the previous expression (e.g., <literal>\d*</literal> matches zero, one or more than one digit) | 匹配0个或更多 (例如, <literal>\d*</literal> 匹配0个 或更多数字字符) | 翻译 | ||
| 192#翻译 | <literal>{1,3}</literal> | <literal>{1,3}</literal> | 翻译 | ||
| 194#翻译 | Between one and three (inclusive) of the previous expression (e.g., <literal>\d{1,3}</literal> matches one, two or three digits) | 介于一个和三个(包含)之前的表达式(例如,<literal>\d{1,3}</literal>匹配一个或两个或三个数字) | 翻译 | ||
| 196#翻译 | For more on regular expressions, see <reference name="http://www.djangoproject.com/r/python/re-module/" refuri="http://www.djangoproject.com/r/python/re-module/">http://www.djangoproject.com/r/python/re-module/</reference>. | 有关正则表达式的更多内容,请访问 <reference name="http://www.djangoproject.com/r/python/re-module/" refuri="http://www.djangoproject.com/r/python/re-module/">http://www.djangoproject.com/r/python/re-module/</reference>. | 翻译 | ||
| 198#翻译 | A Quick Note About 404 Errors | 关于“404错误”的快速参考 | 翻译 | ||
| 200#翻译 | At this point, our URLconf defines only a single URLpattern: | 目前,我们的URLconf只定义了一个单独的URL模式: | 翻译 | ||
| 201#翻译 | the one that handles requests to the URL <literal>/hello/</literal> . What happens when you request a different URL? | 处理URL <literal>/hello/</literal> 。 当请求其他URL会怎么样呢? | 翻译 | ||
| 203#翻译 | To find out, try running the Django development server and visiting a page such as <literal>http://127.0.0.1:8000/goodbye/</literal> or <literal>http://127.0.0.1:8000/hello/subdirectory/</literal> , or even <literal>http://127.0.0.1:8000/</literal> (the site root). | 让我们试试看,运行Django开发服务器并访问类似 <literal>http://127.0.0.1:8000/goodbye/</literal> 或者 <literal>http://127.0.0.1:8000/hello/subdirectory/</literal> ,甚至 <literal>http://127.0.0.1:8000/</literal> (网站根目录)。 | 翻译 | ||
| 204#翻译 | You should see a Page not found message (see Figure 3-1). | 你将会看到一个 “Page not found” 页面(图 3-2)。 | 翻译 | ||
| 205#翻译 | Django displays this message because you requested a URL that's not defined in your URLconf. | 因为你的URL申请在URLconf中没有定义,所以Django显示这条信息。 | 翻译 | ||
| 207#翻译 | <image alt="Screenshot of Django's 404 page." uri="http://new-media.djangobook.com/content/en/2.0/chapter03/404.png"/><cnid>64 | <image alt="Djangos 404 页面截屏." uri="http://new-media.djangobook.com/content/en/1.0/chapter03/404.png"/><cnid>83 | 翻译 | ||
| 208#翻译 | Figure 3-1. | 图3-1: | 翻译 | ||
| 209#翻译 | Django's 404 page | Django的404 Error页 | 翻译 | ||
| 211#翻译 | The utility of this page goes beyond the basic 404 error message. | 这个页面比原始的404错误信息更加实用。 | 翻译 | ||
| 212#翻译 | It also tells you precisely which URLconf Django used and every pattern in that URLconf. | 它同时精确的告诉你Django调用哪个URLconf及其包含的每个模式。 | 翻译 | ||
| 213#翻译 | From that information, you should be able to tell why the requested URL threw a 404. | 这样,你应该能了解到为什么这个请求会抛出404错误。 | 翻译 | ||
| 215#翻译 | Naturally, this is sensitive information intended only for you, the Web developer. | 当然,这些敏感的信息应该只呈现给你-开发者。 | 翻译 | ||
| 216#翻译 | If this were a production site deployed live on the Internet, you wouldn't want to expose that information to the public. | 如果是部署到了因特网上的站点就不应该暴露 这些信息。 | 翻译 | ||
| 217#翻译 | For that reason, this Page not found page is only displayed if your Django project is in <emphasis>debug mode</emphasis> . We'll explain how to deactivate debug mode later. | 出于这个考虑,这个“Page not found”页面只会在 <emphasis>调试模式(debug mode)</emphasis> 下 显示。 | 翻译 | ||
| 218#翻译 | For now, just know that every Django project is in debug mode when you first create it, and if the project is not in debug mode, Django outputs a different 404 response. | 我们将在以后说明怎么关闭调试模式。现在我们只需知道对于每个新建的Django项目,在默认情况下都是开启调试模式的;若未开启调试模式,Django将输出不同的404页面。 | 翻译 | ||
| 220#翻译 | A Quick Note About The Site Root | 关于网站根目录的快速参考。 | 翻译 | ||
| 222#翻译 | As explained in the last section, you'll see a 404 error message if you view the site root <literal>http://127.0.0.1:8000/</literal> . Django doesn't add magically anything to the site root; that URL is not special-cased in any way. | 在上一节提到,如果我们访问网站根目录<literal>http://127.0.0.1:8000/</literal>时将看到一个404错误的消息。Django并不会自动为网站根目录增加任何映射,这个URL并不特殊。 | 翻译 | ||
| 223#翻译 | It's up to you to assign it to a URLpattern, just like every other entry in your URLconf. | 就像在URLconf中的其他条目一样,它也依赖于指定给它的URL模式. | 翻译 | ||
| 225#翻译 | The URLpattern to match the site root is a bit unintuitive, though, so it's worth mentioning. | 尽管匹配网站根目录的URL模式不能想象,但是还是值得提一下的. | 翻译 | ||
| 226#翻译 | When you're ready to implement a view for the site root, use the URLpattern <literal>'^$'</literal> , which matches an empty string. | 当为网站根目录实现一个视图,你需要使用URL模式<literal> '^$'</literal> , 它代表一个空字符串。 | 翻译 | ||
| 227#翻译 | For example: | 例如: | 翻译 | ||
| 230#翻译 | How Django Processes a Request | Django是怎么处理请求的 | 翻译 | ||
| 232#翻译 | Before continuing to our second view function, let's pause to learn a little more about how Django works. | 在继续我们的第二个视图功能之前,让我们暂停一下去了解更多一些有关Django是怎么工作的知识. | 翻译 | ||
| 233#翻译 | Specifically, when you view your Hello world message by visiting <literal>http://127.0.0.1:8000/hello/</literal> in your Web browser, what does Django do behind the scenes? | 具体地说,当你通过在浏览器里敲http://127.0.0.1:8000/hello/来访问Hello world消息的时候,Django在后台做了些什么呢? | 翻译 | ||
| 235#翻译 | It all starts with the <emphasis>settings file</emphasis> . When you run <literal>python manage.py runserver</literal> , the script looks for a file called <literal>settings.py</literal> in the same directory as <literal>manage.py</literal> . This file contains all sorts of configuration for this particular Django project, all in uppercase: | 一切都开始于<emphasis>settings</emphasis>文件。当你运行<literal>python manage.py runserver</literal>,脚本将在<literal>manage.py</literal>所在的目录下查找名为<literal>setting.py</literal>的文件。这个文件包含了这个Django项目的所有配置信息,它们都是大写的: | 翻译 | ||
| 236#翻译 | <literal>TEMPLATE_DIRS</literal> , <literal>DATABASE_NAME</literal> , etc. | TEMPLATE_DIRS , DATABASE_NAME , 等. | 翻译 | ||
| 237#翻译 | The most important setting is called <literal>ROOT_URLCONF</literal> . <literal>ROOT_URLCONF</literal> tells Django which Python module should be used as the URLconf for this Web site. | 最重要的设置是ROOT_URLCONF,它将作为URLconf告诉Django在这个站点中哪些Python的模块将被用到。 | 翻译 | ||
| 239#翻译 | Remember when <literal>django-admin.py startproject</literal> created the files <literal>settings.py</literal> and <literal>urls.py</literal> ? The autogenerated <literal>settings.py</literal> contains a <literal>ROOT_URLCONF</literal> setting that points to the autogenerated <literal>urls.py</literal> . Open the <literal>settings.py</literal> file and see for yourself; it should look like this: | 还记得我们运行django-admin.py startproject时创建的文件settings.py和urls.py吗?自动创建的settings.py包含一个ROOT_URLCONF配置用来指向自动产生的urls.py. 打开文件settings.py你将看到如下: | 翻译 | ||
| 242#翻译 | This corresponds to the file <literal>mysite/urls.py</literal> . | 相对应的文件是mysite/urls.py | 翻译 | ||
| 244#翻译 | When a request comes in for a particular URL say, a request for <literal>/hello/</literal> Django loads the URLconf pointed to by the <literal>ROOT_URLCONF</literal> setting. | 当访问 URL <literal>/hello/</literal> 时,Django 根据 <literal>ROOT_URLCONF</literal> 的设置装载 URLconf 。 | 翻译 | ||
| 245#翻译 | Then it checks each of the URLpatterns in that URLconf, in order, comparing the requested URL with the patterns one at a time, until it finds one that matches. | 然后按顺序逐个匹配URLconf里的URLpatterns,直到找到一个匹配的。 | 翻译 | ||
| 246#翻译 | When it finds one that matches, it calls the view function associated with that pattern, passing it an <literal>HttpRequest</literal> object as the first parameter. | 当找到这个匹配 的URLpatterns就调用相关联的view函数,并把 <literal>HttpRequest</literal> 对象作为第一个参数 | 翻译 | ||
| 247#翻译 | (We'll cover the specifics of <literal>HttpRequest</literal> later.) | (稍后再给出 <literal>HttpRequest</literal> 的更多信息) | 翻译 | ||
| 249#翻译 | As we saw in our first view example, a view function must return an <literal>HttpResponse</literal> . Once it does this, Django does the rest, converting the Python object to a proper Web response with the appropriate HTTP headers and body (i.e., the content of the Web page). | 正如我们在第一个视图例子里面看到的,一个视图函数必须返回一个HttpResponse对象。 一旦视图函数执行完成,Django将完成剩余的工作,把Python对象转换成一个合适的带有HTTP头和body的Web Response(例如,网页内容)。 | 翻译 | ||
| 251#翻译 | In summary: | 总结一下: | 翻译 | ||
| 253#翻译 | A request comes in to <literal>/hello/</literal> . | 进来的请求转入/hello/. | 翻译 | ||
| 255#翻译 | Django determines the root URLconf by looking at the <literal>ROOT_URLCONF</literal> setting. | Django通过在ROOT_URLCONF配置来决定根URLconf. | 翻译 | ||
| 257#翻译 | Django looks at all of the URLpatterns in the URLconf for the first one that matches <literal>/hello/</literal> . | Django在URLconf中的所有URL模式中,查找第一个匹配/hello/的条目。 | 翻译 | ||
| 259#翻译 | If it finds a match, it calls the associated view function. | 如果找到匹配,将调用相应的视图函数 | 翻译 | ||
| 261#翻译 | The view function returns an <literal>HttpResponse</literal> . | 视图函数返回一个HttpResponse | 翻译 | ||
| 263#翻译 | Django converts the <literal>HttpResponse</literal> to the proper HTTP response, which results in a Web page. | Django把HttpResponse转换为一个合适的HTTP response, 以Web page的形式显示出来。 | 翻译 | ||
| 265#翻译 | You now know the basics of how to make Django-powered pages. | 你现在知道了怎么做一个 Django-powered 页面了,真的很简单,只需要写视图函数并用 URLconfs把它们和URLs对应起来。 | 翻译 | ||
| 266#翻译 | It's quite simple, really just write view functions and map them to URLs via URLconfs. | 你可能会认为用一系列正则表达式将URLs映射到函数也许会比较慢,但事实却会让你惊讶。 | 翻译 | ||
| 268#翻译 | Your Second View: | 第二个视图: | 翻译 | ||
| 269#翻译 | Dynamic Content | 动态内容 | 翻译 | ||
| 271#翻译 | Our Hello world view was instructive in demonstrating the basics of how Django works, but it wasn't an example of a <emphasis>dynamic</emphasis> Web page, because the content of the page are always the same. | 我们的Hello world视图是用来演示基本的Django是如何工作的,但是它不是一个动态网页的例子,因为网页的内容一直是一样的. | 翻译 | ||
| 272#翻译 | Every time you view <literal>/hello/</literal> , you'll see the same thing; it might as well be a static HTML file. | 每次去查看/hello/,你将会看到相同的内容,它类似一个静态HTML文件。 | 翻译 | ||
| 274#翻译 | For our second view, let's create something more dynamic a Web page that displays the current date and time. | 第二个视图,我们将把更多动态的东西放在网页上,例如当前日期和时间。 | 翻译 | ||
| 275#翻译 | This is a nice, simple next step, because it doesn't involve a database or any user input just the output of your server's internal clock. | 这将是非常理想而简单的下一步,因为它不引入数据库或者任何用户的输入,仅仅是显示你的服务器的内部时钟. | 翻译 | ||
| 276#翻译 | Its only marginally more exciting than Hello world, but it'll demonstrate a few new concepts. | 它仅仅比Helloworld稍微刺激一些,但它将演示一些新的概念。 | 翻译 | ||
| 278#翻译 | This view needs to do two things: | 这个视图需要做两件事情: | 翻译 | ||
| 279#翻译 | calculate the current date and time, and return an <literal>HttpResponse</literal> containing that value. | 计算当前日期和时间,并返回包含这些值的HttpResponse。 | 翻译 | ||
| 280#翻译 | If you have experience with Python, you know that Python includes a <literal>datetime</literal> module for calculating dates. | 如果你对python很有经验,那肯定知道在python中需要利用datetime模块去计算时间。 | 翻译 | ||
| 281#翻译 | Here's how to use it: | 下面演示如何去使用它: | 翻译 | ||
| 284#翻译 | That's simple enough, and it has nothing to do with Django. | 以上代码很简单,并没有涉及Django。 | 翻译 | ||
| 285#翻译 | It's just Python code. | 它仅仅是Python代码。 | 翻译 | ||
| 286#翻译 | (We want to emphasize that you should be aware of what code is just Python vs. | (我们要强调的是,你应该清除意识到哪些仅是Python代码, | 翻译 | ||
| 287#翻译 | code that is Django-specific. | 哪些是Django特性代码。) | 翻译 | ||
| 288#翻译 | As you learn Django, we want you to be able to apply your knowledge to other Python projects that don't necessarily use Django.) | 作为你学习Django的目的之一,我们希望你能将你的知识应用在那些不一定需要使用Django的Python项目上。) | 翻译 | ||
| 290#翻译 | To make a Django view that displays the current date and time, then, we just need to hook this <literal>datetime.datetime.now()</literal> statement into a view and return an <literal>HttpResponse</literal> . Here's how that looks: | 为了让Django视图显示当前日期和时间,我们仅需要把语句:datetime.datetime.now()放入视图函数,然后返回一个HttpResponse对象即可。代码如下: | 翻译 | ||
| 293#翻译 | As with our <literal>hello</literal> view function, this should live in <literal>views.py</literal> . Note that we've hidden the <literal>hello</literal> function from this example for brevity, but for the sake of completeness, here's what the entire <literal>views.py</literal> looks like: | 正如我们的hello函数一样,这个函数也保存在views.py中。为了简洁,上面我们隐藏了hello函数。下面是完整的views.py文件内容: | 翻译 | ||
| 296#翻译 | (From now on, we won't display previous code in code examples, except when necessary. | (从现在开始,如非必要,本文不再重复列出先前的代码。 | 翻译 | ||
| 297#翻译 | You should be able to tell from context which parts of an example are new vs. | 你应该懂得识别哪些是新代码,哪些是先前的。) | 翻译 | ||
| 298#翻译 | old.) | (见上) | 翻译 | ||
| 300#翻译 | Let's step through the changes we've made to <literal>views.py</literal> to accommodate the <literal>current_datetime</literal> view. | 让我们分析一下改动后的views.py: | 翻译 | ||
| 302#翻译 | We've added an <literal>import datetime</literal> to the top of the module, so we can calculate dates. | 在文件顶端,我们添加了一条语句:import datetime。这样就可以计算日期了。 | 翻译 | ||
| 304#翻译 | The new <literal>current_datetime</literal> function calculates the current date and time, as a <literal>datetime.datetime</literal> object, and stores that as the local variable <literal>now</literal> . | 函数中的第一行代码计算当前日期和时间,并以 <literal>datetime.datetime</literal> 对象的形式保存为局部变量 <literal>now</literal> 。 | 翻译 | ||
| 306#翻译 | The second line of code within the view constructs an HTML response using Python's format-string capability. | 函数的第二行代码用 Python 的格式化字符串(format-string)功能构造了一段 HTML 响应。 | 翻译 | ||
| 307#翻译 | The <literal>%s</literal> within the string is a placeholder, and the percent sign after the string means Replace the <literal>%s</literal> in the preceding string with the value of the variable <literal>now</literal> . The <literal>now</literal> variable is technically a <literal>datetime.datetime</literal> object, not a string, but the <literal>%s</literal> format character converts it to its string representation, which is something like <literal>"2008-12-13 14:09:39.002731"</literal> . This will result in an HTML string such as <literal>"<html><body>It is now 2008-12-13 14:09:39.002731.</body></html>"</literal> . | 字符串中的%s是占位符,字符串后面的百分号表示用它后面的变量now的值来代替%s。变量%s是一个datetime.datetime对象。它虽然不是一个字符串,但是%s(格式化字符串)会把它转换成字符串,如:2008-12-13 14:09:39.002731。这将使HTML的输出字符串变成:It is now 2008-12-13 14:09:39.002731。 | 翻译 | ||
| 309#翻译 | (Yes, our HTML is invalid, but we're trying to keep the example simple and short.) | (目前HTML是有错误的,但我们这样做是为了保持例子的简短。) | 翻译 | ||
| 311#翻译 | Finally, the view returns an <literal>HttpResponse</literal> object that contains the generated response just as we did in <literal>hello</literal> . | 最后,正如我们刚才写的hello函数一样,视图返回一个HttpResponse对象,它包含生成的响应。 | 翻译 | ||
| 313#翻译 | After adding that to <literal>views.py</literal> , add the URLpattern to <literal>urls.py</literal> to tell Django which URL should handle this view. | 添加上述代码之后,还要在urls.py中添加URL模式,以告诉Django由哪一个URL来处理这个视图。 | 翻译 | ||
| 314#翻译 | Something like <literal>/time/</literal> would make sense: | 用/time/之类的字眼易于理解: | 翻译 | ||
| 317#翻译 | We've made two changes here. | 这里,我们更改了两个地方。 | 翻译 | ||
| 318#翻译 | First, we imported the <literal>current_datetime</literal> function at the top. | 首先,在顶部导入current_datetime函数; | 翻译 | ||
| 319#翻译 | Second, and more importantly, we added a URLpattern mapping the URL <literal>/time/</literal> to that new view. | 其次,也是更重要的:添加一个URL模式来映射URL中的/time/到那个新视图。 | 翻译 | ||
| 320#翻译 | Getting the hang of this? | 理解了么? | 翻译 | ||
| 322#翻译 | With the view written and URLconf updated, fire up the <literal>runserver</literal> and visit <literal>http://127.0.0.1:8000/time/</literal> in your browser. | 写好视图并且更新URLconf之后,运行命令python manage.py runserver以启动服务,在浏览器中输入http://127.0.0.1:8000/time/。 | 翻译 | ||
| 323#翻译 | You should see the current date and time. | 你将看到当前的日期和时间。 | 翻译 | ||
| 325#翻译 | Django's Time Zone | Django时区 | 翻译 | ||
| 327#翻译 | Depending on your computer, the date and time may be a few hours off. | 显示的日期与时间可能和实际的相差几个小时,这取决于你的机器。 | 翻译 | ||
| 328#翻译 | That's because Django is time zone-aware and defaults to the <literal>America/Chicago</literal> time zone. | 这是因为Django是有时区意识的,并且默认时区为America/Chicago。 | 翻译 | ||
| 329#翻译 | (It has to default to <emphasis>something</emphasis> , and that's the time zone where the original developers live.) If you live elsewhere, you'll want to change it in <literal>settings.py</literal> . See the comment in that file for a link to an up-to-date list of worldwide time zone options. | (它必须有个值,它的默认值是Django的诞生地:美国/芝加哥)如果你处在别的时区,你需要在settings.py文件中更改这个值。请参见它里面的注释,以获得最新世界时区列表。 | 翻译 | ||
| 331#翻译 | URLconfs and Loose Coupling | URL配置和松耦合 | 翻译 | ||
| 333#翻译 | Now's a good time to highlight a key philosophy behind URLconfs and behind Django in general: | 现在是好时机来指出Django和URL配置背后的哲学: | 翻译 | ||
| 334#翻译 | the principle of <emphasis>loose coupling</emphasis> . Simply put, loose coupling is a software-development approach that values the importance of making pieces interchangeable. | <emphasis>松耦合</emphasis> 原则。简单的说,松耦合是一个重要的保证互换性的软件开发方法。 | 翻译 | ||
| 335#翻译 | If two pieces of code are loosely coupled, then changes made to one of the pieces will have little or no effect on the other. | 如果两段代码是松耦合的,那么其中任意一段代码的变动只会对另一段代码造成很小的或者根本不会造成影响。 | 翻译 | ||
| 337#翻译 | Django's URLconfs are a good example of this principle in practice. | Django的URL配置就是一个很好的例子。 | 翻译 | ||
| 338#翻译 | In a Django Web application, the URL definitions and the view functions they call are loosely coupled; that is, the decision of what the URL should be for a given function, and the implementation of the function itself, reside in two separate places. | 在Django的应用程序中,URL的定义和视图函数之间是松 耦合的,换句话说,决定URL返回哪个视图函数和实现这个视图函数是在两个不同的地方。 | 翻译 | ||
| 339#翻译 | This lets you switch out one piece without affecting the other. | 这使得 开发人员可以修改一块而不会影响另一块。 | 翻译 | ||
| 341#翻译 | For example, consider our <literal>current_datetime</literal> view. | 例如,考虑一下current_datetime视图。 | 翻译 | ||
| 342#翻译 | If we wanted to change the URL for the application say, to move it from <literal>/time/</literal> to <literal>/current-time/</literal> we could make a quick change to the URLconf, without having to worry about the view itself. | 如果我们想把它的URL 从原来的 <literal>/time/</literal> 改变到 <literal>/currenttime/</literal> ,我们只需要快速的修改一下URL配置即可, 不用担心这个函数的内部实现。 | 翻译 | ||
| 343#翻译 | Similarly, if we wanted to change the view function altering its logic somehow we could do that without affecting the URL to which the function is bound. | 同样的,如果我们想要修改这个函数的内部实现也不用担心会影响 到对应的URL。 | 翻译 | ||
| 345#翻译 | Furthermore, if we wanted to expose the current-date functionality at <emphasis>several</emphasis> URLs, we could easily take care of that by editing the URLconf, without having to touch the view code. | 此外,如果我们想把这个函数到 <emphasis>不止一个</emphasis> URL, 我们只需要修改URL配置而不用 去改动视图的代码。 | 翻译 | ||
| 346#翻译 | In this example, our <literal>current_datetime</literal> is available at two URLs. | 在这个例子里,current_datetime被两个URL使用。 | 翻译 | ||
| 347#翻译 | It's a contrived example, but this technique can come in handy: | 这是一个故弄玄虚的例子,但这个方法迟早会用得上。 | 翻译 | ||
| 350#翻译 | URLconfs and views are loose coupling in action. | URLconf和视图是松耦合的。 | 翻译 | ||
| 351#翻译 | We'll continue to point out examples of this important philosophy throughout this book. | 我们将在本书中继续给出这一重要哲学的相关例子。 | 翻译 | ||
| 353#翻译 | Your Third View: | 第三个视图 | 翻译 | ||
| 354#翻译 | Dynamic URLs | 动态URL | 翻译 | ||
| 356#翻译 | In our <literal>current_datetime</literal> view, the contents of the page the current date/time were dynamic, but the URL (<literal>/time/</literal> ) was static. | 在我们的<literal> current_datetime</literal> 视图范例中,尽管内容是动态的,但是URL ( <literal>/time/</literal> )是静态的。 | 翻译 | ||
| 357#翻译 | In most dynamic Web applications, though, a URL contains parameters that influence the output of the page. | 然而在大多数动态web应用中,URL通常都包含能够影响输出内容的参数。 | 翻译 | ||
| 358#翻译 | For example, an online bookstore might give each book its own URL, like <literal>/books/243/</literal> and <literal>/books/81196/</literal> . | 举个例子,一家在线书店会为每一本书提供一个URL,如:/books/243/、/books/81196/。 | 翻译 | ||
| 360#翻译 | Let's create a third view that displays the current date and time offset by a certain number of hours. | 让我们创建第三个视图来显示当前时间和加上时间偏差量的时间,设计是这样的: | 翻译 | ||
| 361#翻译 | The goal is to craft a site in such a way that the page <literal>/time/plus/1/</literal> displays the date/time one hour into the future, the page <literal>/time/plus/2/</literal> displays the date/time two hours into the future, the page <literal>/time/plus/3/</literal> displays the date/time three hours into the future, and so on. | <literal>/time/plus/1/</literal> 显示当前时间+1个小时的页面 <literal>/time/plus/2/</literal> 显示当前时间+2个小时的页面 <literal>/time/plus/3/</literal> 显示当前时间+3个小时的页面,以此类推。 | 翻译 | ||
| 363#翻译 | A novice might think to code a separate view function for each hour offset, which might result in a URLconf like this: | 新手可能会考虑写不同的视图函数来处理每个时间偏差量,URL配置看起来就象这样: | 翻译 | ||
| 366#翻译 | Clearly, this line of thought is flawed. | 很明显,这样处理是不太妥当的。 | 翻译 | ||
| 367#翻译 | Not only would this result in redundant view functions, but also the application is fundamentally limited to supporting only the predefined hour ranges one, two, three or four hours. | 不但有很多冗余的视图函数,而且整个应用也被限制了只支持 预先定义好的时间段,2小时,3小时,或者4小时。 | 翻译 | ||
| 368#翻译 | If we decided to create a page that displayed the time <emphasis>five</emphasis> hours into the future, we'd have to create a separate view and URLconf line for that, furthering the duplication. | 如果哪天我们要实现 <emphasis>5</emphasis> 小时,我们就 不得不再单独创建新的视图函数和配置URL,既重复又混乱。 | 翻译 | ||
| 369#翻译 | We need to do some abstraction here. | 我们需要在这里做一点抽象,提取 一些共同的东西出来。 | 翻译 | ||
| 371#翻译 | A Word About Pretty URLs | 关于漂亮URL的一点建议 | 翻译 | ||
| 373#翻译 | If you're experienced in another Web development platform, such as PHP or Java, you may be thinking, Hey, let's use a query string parameter! | 如果你有其它Web平台的开发经验(如PHP或Java),你可能会想:嘿!让我们用查询字符串参数吧! | 翻译 | ||
| 374#翻译 | something like <literal>/time/plus?hours=3</literal> , in which the hours would be designated by the <literal>hours</literal> parameter in the URL's query string (the part after the <literal>?</literal> ). | 就像/time/plus?hours=3里面的小时应该在查询字符串中被参数hours指定(问号后面的是参数)。 | 翻译 | ||
| 376#翻译 | You <emphasis>can</emphasis> do that with Django (and we'll tell you how in Chapter 7), but one of Django's core philosophies is that URLs should be beautiful. | 你 <emphasis>可以</emphasis> 在Django里也这样做 (我们稍后会在第七章告诉你怎么做), 但是Django的一个核心理念就是URL必须看起来漂亮。 | 翻译 | ||
| 377#翻译 | The URL <literal>/time/plus/3/</literal> is far cleaner, simpler, more readable, easier to recite to somebody aloud and just plain prettier than its query string counterpart. | URL <literal>/time/plus/3/</literal> 更加清晰, 更简单,也更有可读性,可以很容易的大声念出来,因为它是纯文本,没有查询字符串那么 复杂。 | 翻译 | ||
| 378#翻译 | Pretty URLs are a characteristic of a quality Web application. | 漂亮的URL就像是高质量的Web应用的一个标志。 | 翻译 | ||
| 380#翻译 | Django's URLconf system encourages pretty URLs by making it easier to use pretty URLs than <emphasis>not</emphasis> to. | Django的URL配置系统可以使你很容易的设置漂亮的URL,而尽量不要考虑它的 <emphasis>反面</emphasis> 。 | 翻译 | ||
| 382#翻译 | How, then do we design our application to handle arbitrary hour offsets? | 那么,我们如何设计程序来处理任意数量的时差? | 翻译 | ||
| 383#翻译 | The key is to use <emphasis>wildcard URLpatterns</emphasis> . As we mentioned previously, a URLpattern is a regular expression; hence, we can use the regular expression pattern <literal>\d+</literal> to match one or more digits: | 答案是:使用通配符(wildcard URLpatterns)。正如我们之前提到过,一个URL模式就是一个正则表达式。因此,这里可以使用\\d+来匹配1个以上的数字。 | 翻译 | ||
| 386#翻译 | (We're using the <literal># ...</literal> | (这里使用# ... | 翻译 | ||
| 387#翻译 | to imply there might be other URLpatterns that we trimmed from this example.) | 来表示省略了其它可能存在的URL模式定义。) | 翻译 | ||
| 389#翻译 | This new URLpattern will match any URL such as <literal>/time/plus/2/</literal> , <literal>/time/plus/25/</literal> , or even <literal>/time/plus/100000000000/</literal> . Come to think of it, let's limit it so that the maximum allowed offset is 99 hours. | 这个URL模式将匹配类似 <literal>/time/plus/2/</literal> , <literal>/time/plus/25/</literal> ,甚至 <literal>/time/plus/100000000000/</literal> 的任何URL。 | 翻译 | ||
| 390#翻译 | That means we want to allow either one- or two-digit numbers and in regular expression syntax, that translates into <literal>\d{1,2}</literal> : | 更进一步,让我们把它限制在最大允许99个小时, 这样我们就只允许一个或两个数字,正则表达式的语法就是 <literal>\d{1,2}</literal> : | 翻译 | ||
| 393#翻译 | Note | 备注 | 翻译 | ||
| 395#翻译 | When building Web applications, it's always important to consider the most outlandish data input possible, and decide whether or not the application should support that input. | 在建造Web应用的时候,尽可能多考虑可能的数据输入是很重要的,然后决定哪些我们可以接受。 | 翻译 | ||
| 396#翻译 | We've curtailed the outlandishness here by limiting the offset to 99 hours. | 在这里我们就设置了99个小时的时间段限制。 | 翻译 | ||
| 398#翻译 | One more important detail we've introduced here is that <literal>r</literal> character in front of the regular expression string. | 另外一个重点,正则表达式字符串的开头字母“r”。 | 翻译 | ||
| 399#翻译 | This tells Python that the string is a raw string its contents should not interpret backslashes. | 它告诉Python这是个原始字符串,不需要处理里面的反斜杠(转义字符)。 | 翻译 | ||
| 400#翻译 | In normal Python strings, backslashes are used for escaping special characters such as in the string <literal>'\n'</literal> , which is a one-character string containing a newline. | 在普通Python字符串中,反斜杠用于特殊字符的转义。比如\n转义成一个换行符。 | 翻译 | ||
| 401#翻译 | When you add the <literal>r</literal> to make it a raw string, Python does not apply its backslash escaping so, <literal>r'\n'</literal> is a two-character string containing a literal backslash and a lowercase n. There's a natural collision between Python's usage of backslashes and the backslashes that are found in regular expressions, so it's strongly suggested that you use raw strings any time you're defining a regular expression in Python. | 当你用r把它标示为一个原始字符串后,Python不再视其中的反斜杠为转义字符。也就是说,“\n”是两个字符串:“\”和“n”。由于反斜杠在Python代码和正则表达式中有冲突,因此建议你在Python定义正则表达式时都使用原始字符串。 | 翻译 | ||
| 402#翻译 | From now on, all of the URLpatterns in this book will be raw strings. | 从现在开始,本文所有URL模式都用原始字符串。 | 翻译 | ||
| 404#翻译 | Now that we've designated a wildcard for the URL, we need a way of passing that wildcard data to the view function, so that we can use a single view function for any arbitrary hour offset. | 现在我们已经设计了一个带通配符的URL,我们需要一个方法把它传递到视图函数里去,这样 我们只用一个视图函数就可以处理所有的时间段了。 | 翻译 | ||
| 405#翻译 | We do this by placing parentheses around the data in the URLpattern that we want to save. | 我们使用圆括号把参数在URL模式里标识 出来。 | 翻译 | ||
| 406#翻译 | In the case of our example, we want to save whatever number was entered in the URL, so let's put parentheses around the <literal>\d{1,2}</literal> , like this: | 在这个例子中,我们想要把这些数字作为参数,用圆括号把 <literal>\d{1,2}</literal> 包围起来: | 翻译 | ||
| 409#翻译 | If you're familiar with regular expressions, you'll be right at home here; were using parentheses to <emphasis>capture</emphasis> data from the matched text. | 如果你熟悉正则表达式,那么你应该已经了解,正则表达式也是用圆括号来从文本里 <emphasis>提取</emphasis> 数据的。 | 翻译 | ||
| 411#翻译 | The final URLconf, including our previous two views, looks like this: | 最终的URLconf包含上面两个视图,如: | 翻译 | ||
| 414#翻译 | With that taken care of, let's write the <literal>hours_ahead</literal> view. | 现在开始写 <literal>hours_ahead</literal> 视图。 | 翻译 | ||
| 416#翻译 | Coding Order | 编码次序 | 翻译 | ||
| 418#翻译 | In this example, we wrote the URLpattern first and the view second, but in the previous examples, we wrote the view first, then the URLpattern. | 这个例子中,我们先写了URLpattern ,然后是视图,但是在前面的例子中, 我们先写了视图,然后是URLpattern 。 | 翻译 | ||
| 419#翻译 | Which technique is better? | 哪一种方式比较好? | 翻译 | ||
| 421#翻译 | Well, every developer is different. | 嗯,怎么说呢,每个开发者是不一样的。 | 翻译 | ||
| 423#翻译 | If you're a big-picture type of person, it may make the most sense to you to write all of the URLpatterns for your application at the same time, at the start of your project, and then code up the views. | 如果你喜欢从总体上来把握事物,那么对你来说,最有意义的做法可能是在项目开始的时候就写下所有的URL配置,然后再完成视图的编写。 | 翻译 | ||
| 424#翻译 | This has the advantage of giving you a clear to-do list, and it essentially defines the parameter requirements for the view functions you'll need to write. | 这样做的好处是为你提供了一个清晰的to-do list,并且基本上确定了你所需要编写的视图函数的变量要求。 | 翻译 | ||
| 426#翻译 | If you're more of a bottom-up developer, you might prefer to write the views first, and then anchor them to URLs afterward. | 如果你更偏向于一个自底向上的开发者,你可能更喜欢先写视图, 然后把它们挂接到URL上。 | 翻译 | ||
| 427#翻译 | That's OK, too. | 这同样是可以的。 | 翻译 | ||
| 429#翻译 | In the end, it comes down to which technique fits your brain the best. | 最后,取决与你喜欢哪种技术,两种方法都是可以的。 | 翻译 | ||
| 430#翻译 | Both approaches are valid. | (见上) | 翻译 | ||
| 432#翻译 | <literal>hours_ahead</literal> is very similar to the <literal>current_datetime</literal> view we wrote earlier, with a key difference: | <literal>hours_ahead</literal> 和我们以前写的 <literal>current_datetime</literal> 很象,关键的区别在于: | 翻译 | ||
| 433#翻译 | it takes an extra argument, the number of hours of offset. | 它多了一个额外参数,时间差。 | 翻译 | ||
| 434#翻译 | Here's the view code: | 以下是view代码: | 翻译 | ||
| 437#翻译 | Let's step through this code one line at a time: | 让我们逐行分析一下代码: | 翻译 | ||
| 439#翻译 | The view function, <literal>hours_ahead</literal> , takes <emphasis>two</emphasis> parameters: | 视图函数, <literal>hours_ahead</literal> , 有 <emphasis>两个</emphasis> 参数: <literal>request</literal> 和 <literal>offset</literal> . | 翻译 | ||
| 440#翻译 | <literal>request</literal> and <literal>offset</literal> . | (见上) | 翻译 | ||
| 442#翻译 | <literal>request</literal> is an <literal>HttpRequest</literal> object, just as in <literal>hello</literal> and <literal>current_datetime</literal> . We'll say it again: | <literal>request</literal> 是一个 <literal>HttpRequest</literal> 对象, 就像在 <literal>current_datetime</literal> 中一样. 再说一次好了: 每一个视图 <emphasis>总是</emphasis> 以一个 <literal>HttpRequest</literal> 对象作为 它的第一个参数。 | 翻译 | ||
| 443#翻译 | each view <emphasis>always</emphasis> takes an <literal>HttpRequest</literal> object as its first parameter. | (见上) | 翻译 | ||
| 445#翻译 | <literal>offset</literal> is the string captured by the parentheses in the URLpattern. | <literal>offset</literal> 是从匹配的URL里提取出来的。 | 翻译 | ||
| 446#翻译 | For example, if the requested URL were <literal>/time/plus/3/</literal> , then <literal>offset</literal> would be the string <literal>'3'</literal> . If the requested URL were <literal>/time/plus/21/</literal> , then <literal>offset</literal> would be the string <literal>'21'</literal> . Note that captured values will always be <emphasis>strings</emphasis> , not integers, even if the string is composed of only digits, such as <literal>'21'</literal> . | 例如:如果请求URL是/time/plus/3/,那么offset将会是3;如果请求URL是/time/plus/21/,那么offset将会是21。请注意:捕获值永远都是字符串(string)类型,而不会是整数(integer)类型,即使这个字符串全由数字构成(如:“21”)。 | 翻译 | ||
| 448#翻译 | (Technically, captured values will always be <emphasis>Unicode objects</emphasis> , not plain Python bytestrings, but don't worry about this distinction at the moment.) | (从技术上来说,捕获值总是Unicode objects,而不是简单的Python字节串,但目前不需要担心这些差别。) | 翻译 | ||
| 450#翻译 | We decided to call the variable <literal>offset</literal> , but you can call it whatever you'd like, as long as its a valid Python identifier. | 在这里我们命名变量为 <literal>offset</literal> ,你也可以任意命名它,只要它是一个合法的Python 标识符。 | 翻译 | ||
| 451#翻译 | The variable name doesn't matter; all that matters is that it's the second argument to the function, after <literal>request</literal> . (It's also possible to use keyword, rather than positional, arguments in an URLconf. | 变量名是无关紧要的,重要的是它的位置,它是这个函数的第二个参数,在 <literal>request</literal> 的后面。(也可以使用关键字代替位置指定变量的值。 | 翻译 | ||
| 452#翻译 | We cover that in Chapter 8.) | 我们将在第八章学习。) | 翻译 | ||
| 454#翻译 | The first thing we do within the function is call <literal>int()</literal> on <literal>offset</literal> . This converts the string value to an integer. | 我们在这个函数中要做的第一件事情就是在 <literal>offset</literal> 上调用 <literal>int()</literal> . 这会把这个字符串值转换为整数。 | 翻译 | ||
| 456#翻译 | Note that Python will raise a <literal>ValueError</literal> exception if you call <literal>int()</literal> on a value that cannot be converted to an integer, such as the string <literal>'foo'</literal> . In this example, if we encounter the <literal>ValueError</literal> , we raise the exception <literal>django.http.Http404</literal> , which, as you can imagine, results in a 404 Page not found error. | 请留意:如果你在一个不能转换成整数类型的值上调用int(),Python将抛出一个ValueError异常。如:int('foo')。在这个例子中,如果我们遇到ValueError异常,我们将转为抛出django.http.Http404异常——正如你想象的那样:最终显示404页面(提示信息:页面不存在)。 | 翻译 | ||
| 458#翻译 | Astute readers will wonder: | 机灵的读者可能会问: | 翻译 | ||
| 459#翻译 | how could we ever reach the <literal>ValueError</literal> case, anyway, given that the regular expression in our URLpattern <literal>(\d{1,2})</literal> captures only digits, and therefore <literal>offset</literal> will only ever be a string composed of digits? | 我们在URL模式中用正则表达式(\d{1,2})约束它,仅接受数字怎么样?这样无论如何,offset都是由数字构成的。 | 翻译 | ||
| 460#翻译 | The answer is, we won't, because the URLpattern provides a modest but useful level of input validation, <emphasis>but</emphasis> we still check for the <literal>ValueError</literal> in case this view function ever gets called in some other way. | 答案是:我们不会这么做,因为URLpattern提供的是“适度但有用”级别的输入校验。万一这个视图函数被其它方式调用,我们仍需自行检查ValueError。 | 翻译 | ||
| 461#翻译 | It's good practice to implement view functions such that they don't make any assumptions about their parameters. | 实践证明,在实现视图函数时,不臆测参数值的做法是比较好的。 | 翻译 | ||
| 462#翻译 | Loose coupling, remember? | 松散耦合,还记得么? | 翻译 | ||
| 464#翻译 | In the next line of the function, we calculate the current date/time and add the appropriate number of hours. | 下一行,计算当前日期/时间,然后加上适当的小时数。 | 翻译 | ||
| 465#翻译 | We've already seen <literal>datetime.datetime.now()</literal> from the <literal>current_datetime</literal> view; the new concept here is that you can perform date/time arithmetic by creating a <literal>datetime.timedelta</literal> object and adding to a <literal>datetime.datetime</literal> object. | 在current_datetime视图中,我们已经见过datetime.datetime.now()。这里新的概念是执行日期/时间的算术操作。我们需要创建一个datetime.timedelta对象和增加一个datetime.datetime对象。 | 翻译 | ||
| 466#翻译 | Our result is stored in the variable <literal>dt</literal> . | 结果保存在变量dt中。 | 翻译 | ||
| 468#翻译 | This line also shows why we called <literal>int()</literal> on <literal>offset</literal> the <literal>datetime.timedelta</literal> function requires the <literal>hours</literal> parameter to be an integer. | 这一行还说明了,我们为什么在offset上调用int()——datetime.timedelta函数要求hours参数必须为整数类型。 | 翻译 | ||
| 470#翻译 | Next, we construct the HTML output of this view function, just as we did in <literal>current_datetime</literal> . A small difference in this line from the previous line is that it uses Python's format-string capability with <emphasis>two</emphasis> values, not just one. | 这行和前面的那行的的一个微小差别就是,它使用带有两个值的Python的格式化字符串功能, 而不仅仅是一个值。 | 翻译 | ||
| 471#翻译 | Hence, there are two <literal>%s</literal> symbols in the string and a tuple of values to insert: | 因此,在字符串中有两个 <literal>%s</literal> 符号和一个以进行插入的值的元组: | 翻译 | ||
| 472#翻译 | <literal>(offset, dt)</literal> . | <literal>(offset, dt)</literal> 。 | 翻译 | ||
| 474#翻译 | Finally, we return an <literal>HttpResponse</literal> of the HTML. | 最终,返回一个HTML的HttpResponse。 | 翻译 | ||
| 475#翻译 | By now, this is old hat. | 如今,这种方式已经过时了。 | 翻译 | ||
| 477#翻译 | With that view function and URLconf written, start the Django development server (if it's not already running), and visit <literal>http://127.0.0.1:8000/time/plus/3/</literal> to verify it works. | 在完成视图函数和URL配置编写后,启动Django开发服务器,用浏览器访问 <literal>http://127.0.0.1:8000/time/plus/3/</literal> 来确认它工作正常。 | 翻译 | ||
| 478#翻译 | Then try <literal>http://127.0.0.1:8000/time/plus/5/</literal> . Then <literal>http://127.0.0.1:8000/time/plus/24/</literal> . Finally, visit <literal>http://127.0.0.1:8000/time/plus/100/</literal> to verify that the pattern in your URLconf only accepts one- or two-digit numbers; Django should display a Page not found error in this case, just as we saw in the section A Quick Note About 404 Errors earlier. | 然后是 <literal>http://127.0.0.1:8000/time/plus/5/</literal> 。再然后是 <literal>http://127.0.0.1:8000/time/plus/24/</literal> 。最后,访问 <literal>http://127.0.0.1:8000/time/plus/100/</literal> 来检验URL配置里设置的模式是否只 接受一个或两个数字;Django会显示一个 Page not found error 页面, 和以前看到的 404 错误一样。 | 翻译 | ||
| 479#翻译 | The URL <literal>http://127.0.0.1:8000/time/plus/</literal> (with <emphasis>no</emphasis> hour designation) should also throw a 404. | 访问URL <literal>http://127.0.0.1:8000/time/plus/</literal> (<emphasis>没有</emphasis> 定义时间差) 也会抛出404错误。 | 翻译 | ||
| 481#翻译 | Django's Pretty Error Pages | Django 漂亮的出错页面 | 翻译 | ||
| 483#翻译 | Take a moment to admire the fine Web application we've made so far now lets break it! | 花几分钟时间欣赏一下我们写好的Web应用程序,然后我们再来搞点小破坏。 | 翻译 | ||
| 484#翻译 | Let's deliberately introduce a Python error into our <literal>views.py</literal> file by commenting out the <literal>offset = int(offset)</literal> lines in the <literal>hours_ahead</literal> view: | 我们故意在 <literal>views.py</literal> 文件中引入一项 Python 错误,注释掉 <literal>hours_ahead</literal> 视图中的 <literal>offset = int(offset)</literal> 一行。 | 翻译 | ||
| 487#翻译 | Load up the development server and navigate to <literal>/time/plus/3/</literal> . You'll see an error page with a significant amount of information, including a <literal>TypeError</literal> message displayed at the very top: | 启动开发服务器,然后访问 <literal>/time/plus/3/</literal> 。你会看到一个包含大量信息的出错页,最上面 的一条 <literal>TypeError</literal> 信息是: | 翻译 | ||
| 488#翻译 | <literal>"unsupported type for timedelta hours component: | <literal>"unsupported type for timedelta hours component: | 翻译 | ||
| 489#翻译 | unicode"</literal> . | unicode" . | 翻译 | ||
| 491#翻译 | What happened? | 怎么回事呢? | 翻译 | ||
| 492#翻译 | Well, the <literal>datetime.timedelta</literal> function expects the <literal>hours</literal> parameter to be an integer, and we commented out the bit of code that converted <literal>offset</literal> to an integer. | 是的, <literal>datetime.timedelta</literal> 函数要求 <literal>hours</literal> 参数必须为整型, 而我们注释掉了将 <literal>offset</literal> 转为整型的代码。 | 翻译 | ||
| 493#翻译 | That caused <literal>datetime.timedelta</literal> to raise the <literal>TypeError</literal> . It's the typical kind of small bug that every programmer runs into at some point. | 这样导致 <literal>datetime.timedelta</literal> 弹出 <literal>TypeError</literal> 异常。 | 翻译 | ||
| 495#翻译 | The point of this example was to demonstrate Django's error pages. | 这个例子是为了展示 Django 的出错页面。 | 翻译 | ||
| 496#翻译 | Take some time to explore the error page and get to know the various bits of information it gives you. | 我们来花些时间看一看这个出错页,了解一下其中 给出了哪些信息。 | 翻译 | ||
| 498#翻译 | Here are some things to notice: | 以下是值得注意的一些要点: | 翻译 | ||
| 500#翻译 | At the top of the page, you get the key information about the exception: | 在页面顶部,你可以得到关键的异常信息: | 翻译 | ||
| 501#翻译 | the type of exception, any parameters to the exception (the <literal>"unsupported type"</literal> message in this case), the file in which the exception was raised, and the offending line number. | 异常数据类型、异常的参数 (如本例中的 <literal>"unsupported type"</literal> )、在哪个文件中引发了异常、出错的行号等等。 | 翻译 | ||
| 503#翻译 | Under the key exception information, the page displays the full Python traceback for this exception. | 在关键异常信息下方,该页面显示了对该异常的完整 Python 追踪信息。 | 翻译 | ||
| 504#翻译 | This is similar to the standard traceback you get in Python's command-line interpreter, except it's more interactive. | 这类似于你在 Python 命令行解释器中获得的追踪信息,只不过后者更具交互性。 | 翻译 | ||
| 505#翻译 | For each level (frame) in the stack, Django displays the name of the file, the function/method name, the line number, and the source code of that line. | 对栈中的每一帧,Django 均显示了其文件名、函数或方法名、行号及该行源代码。 | 翻译 | ||
| 507#翻译 | Click the line of source code (in dark gray), and you'll see several lines from before and after the erroneous line, to give you context. | 点击该行代码 (以深灰色显示),你可以看到出错行的前后几行,从而得知相关上下文情况。 | 翻译 | ||
| 509#翻译 | Click Local vars under any frame in the stack to view a table of all local variables and their values, in that frame, at the exact point in the code at which the exception was raised. | 点击栈中的任何一帧的“Local vars”可以看到一个所有局部变量的列表,以及在出错 那一帧时它们的值。 | 翻译 | ||
| 510#翻译 | This debugging information can be a great help. | 这些调试信息相当有用。 | 翻译 | ||
| 512#翻译 | Note the Switch to copy-and-paste view text under the Traceback header. | 注意“Traceback”下面的“Switch to copy-and-paste view”文字。 | 翻译 | ||
| 513#翻译 | Click those words, and the traceback will switch to a alternate version that can be easily copied and pasted. | 点击这些字,追溯会 切换另一个视图,它让你很容易地复制和粘贴这些内容。 | 翻译 | ||
| 514#翻译 | Use this when you want to share your exception traceback with others to get technical support such as the kind folks in the Django IRC chat room or on the Django users mailing list. | 当你想同其他人分享这些异常 追溯以获得技术支持时(比如在 Django 的 IRC 聊天室或邮件列表中),可以使用它。 | 翻译 | ||
| 516#翻译 | Underneath, the Share this traceback on a public Web site button will do this work for you in just one click. | 你按一下下面的“Share this traceback on a public Web site”按钮,它将会完成这项工作。 | 翻译 | ||
| 517#翻译 | Click it to post the traceback to <reference name="http://www.dpaste.com/" refuri="http://www.dpaste.com/">http://www.dpaste.com/</reference>, where you'll get a distinct URL that you can share with other people. | 点击它以传回追溯信息至http://www.dpaste.com/,在那里你可以得到一个单独的URL并与其他人分享你的追溯信息。 | 翻译 | ||
| 519#翻译 | Next, the Request information section includes a wealth of information about the incoming Web request that spawned the error: | 接下来的“Request information”部分包含了有关产生错误的 Web 请求的大量信息: | 翻译 | ||
| 520#翻译 | GET and POST information, cookie values, and meta information, such as CGI headers. | GET 和 POST、cookie 值、元数据(象 CGI 头)。 | 翻译 | ||
| 521#翻译 | Appendix G has a complete reference of all the information a request object contains. | 在附录G里给出了request的对象的 完整参考。 | 翻译 | ||
| 523#翻译 | Below the Request information section, the Settings section lists all of the settings for this particular Django installation. | Request信息的下面,“Settings”列出了 Django 使用的具体配置信息。 | 翻译 | ||
| 524#翻译 | (We've already mentioned <literal>ROOT_URLCONF</literal> , and we'll show you various Django settings throughout the book. | (我们已经提及过ROOT_URLCONF,接下来我们将向你展示各式的Django设置。 | 翻译 | ||
| 525#翻译 | All the available settings are covered in detail in Appendix D.) | 附录D包含了所有可用的设置。) | 翻译 | ||
| 527#翻译 | The Django error page is capable of displaying more information in certain special cases, such as the case of template syntax errors. | Django 的出错页某些情况下有能力显示更多的信息,比如模板语法错误。 | 翻译 | ||
| 528#翻译 | We'll get to those later, when we discuss the Django template system. | 我们讨论 Django 模板系统时再说它们。 | 翻译 | ||
| 529#翻译 | For now, uncomment the <literal>offset = int(offset)</literal> lines to get the view function working properly again. | 现在,取消 <literal>offset = int(offset)</literal> 这行的注释,让它重新正常 工作。 | 翻译 | ||
| 531#翻译 | Are you the type of programmer who likes to debug with the help of carefully placed <literal>print</literal> statements? | 不知道你是不是那种使用小心放置的 <literal>print</literal> 语句来帮助调试的程序员? | 翻译 | ||
| 532#翻译 | You can use the Django error page to do so just without the <literal>print</literal> statements. | 你其实可以用 Django 出错页来做这些,而不用 <literal>print</literal> 语句。 | 翻译 | ||
| 533#翻译 | At any point in your view, temporarily insert an <literal>assert False</literal> to trigger the error page. | 在你视图的任何位置,临时插入一个 <literal>assert False</literal> 来触发出错页。 | 翻译 | ||
| 534#翻译 | Then, you can view the local variables and state of the program. | 然后,你就可以看到局部变量和程序的状态了。 | 翻译 | ||
| 535#翻译 | Here's an example, using the <literal>hours_ahead</literal> view: | 这里有个使用hours_ahead视图的例子: | 翻译 | ||
| 538#翻译 | Finally, it's obvious that much of this information is sensitive it exposes the innards of your Python code and Django configuration and it would be foolish to show this information on the public Internet. | 最后,很显然这些信息很多是敏感的,它暴露了你 Python 代码的内部结构以及 Django 配置,在 Internet 上公开这信息是很愚蠢的。 | 翻译 | ||
| 539#翻译 | A malicious person could use it to attempt to reverse-engineer your Web application and do nasty things. | 不怀好意的人会尝试使用它攻击你的 Web 应用程序,做些讨厌的事情。 | 翻译 | ||
| 540#翻译 | For that reason, the Django error page is only displayed when your Django project is in debug mode. | 因此,Django 出错信息仅在 debug 模式下才会显现。 | 翻译 | ||
| 541#翻译 | We'll explain how to deactivate debug mode in Chapter 12. | 我们将在第十二章说明如何禁用 debug 模式。 | 翻译 | ||
| 542#翻译 | For now, just know that every Django project is in debug mode automatically when you start it. | 现在,你只要知道 Django 服务器在你开启它时默认运行在 debug 模式就行了。 | 翻译 | ||
| 543#翻译 | (Sound familiar? | (听起来很熟悉? | 翻译 | ||
| 544#翻译 | The Page not found errors, described earlier in this chapter, work the same way.) | 页面未发现错误,本章稍前所述,以同样方式工作。) | 翻译 | ||
| 546#翻译 | What's next? | 接下来做什么? | 翻译 | ||
| 548#翻译 | So far, we've been writing our view functions with HTML hard-coded directly in the Python code. | 至此,我们已经用在Python中难于直接编码的HTML写好了视图函数。 | 翻译 | ||
| 549#翻译 | We've done that to keep things simple while we demonstrated core concepts, but in the real world, this is nearly always a bad idea. | 在演示核心概念时,我们所作的是为了保持简单。但是在现实世界中,这差不多总是个坏主意。 | 翻译 | ||
| 551#翻译 | Django ships with a simple yet powerful template engine that allows you to separate the design of the page from the underlying code. | 幸运的是,Django内建有一个简单又强大的模板处理引擎来让你从潜在的编码中分离出页面的设计工作。 | 翻译 | ||
| 552#翻译 | We'll dive into Djangos template engine in the <reference name="next chapter" refuri="../chapter04/">next chapter</reference>. | 我们将在<reference name="next chapter" refuri="../chapter04/">下一章</reference>学习模板引擎。 | 翻译 |