| ID | English原文 | 中文翻译 | 最近翻译记录 | 状态 | 操作 |
|---|---|---|---|---|---|
| 0#翻译 | Chapter 4: Templates | 第四章 模板 | 翻译 | ||
| 3#翻译 | In the previous chapter, you may have noticed something peculiar in how we returned the text in our example views. | 在前一章中,你可能已经注意到我们在例子视图中返回文本的方式有点特别。 | 翻译 | ||
| 4#翻译 | Namely, the HTML was hard-coded directly in our Python code, like this: | 也就是说,HTML被直接硬编码在 Python 代码之中。 | 翻译 | ||
| 7#翻译 | Although this technique was convenient for the purpose of explaining how views work, it's not a good idea to hard-code HTML directly in your views. | 尽管这种技术便于解释视图是如何工作的,但直接将HTML硬编码到你的视图里却并不是一个好主意。 | 翻译 | ||
| 8#翻译 | Here's why: | 让我们来看一下为什么: | 翻译 | ||
| 10#翻译 | Any change to the design of the page requires a change to the Python code. | 对页面设计进行的任何改变都必须对 Python 代码进行相应的修改。 | 翻译 | ||
| 11#翻译 | The design of a site tends to change far more frequently than the underlying Python code, so it would be convenient if the design could change without needing to modify the Python code. | 站点设计的修改往往比底层 Python 代码的修改要频繁得多,因此如果可以在不进行 Python 代码修改的情况下变更设计,那将会方便得多。 | 翻译 | ||
| 13#翻译 | Writing Python code and designing HTML are two different disciplines, and most professional Web development environments split these responsibilities between separate people (or even separate departments). | Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成。 | 翻译 | ||
| 14#翻译 | Designers and HTML/CSS coders shouldn't be required to edit Python code to get their job done. | 设计者和HTML/CSS的编码人员不应该被要求去编辑Python的代码来完成他们的工作。 | 翻译 | ||
| 16#翻译 | It's most efficient if programmers can work on Python code and designers can work on templates at the same time, rather than one person waiting for the other to finish editing a single file that contains both Python and HTML. | 程序员编写 Python代码和设计人员制作模板两项工作同时进行的效率是最高的,远胜于让一个人等待另一个人完成对某个既包含 Python又包含 HTML 的文件的编辑工作。 | 翻译 | ||
| 18#翻译 | For these reasons, it's much cleaner and more maintainable to separate the design of the page from the Python code itself. | 基于这些原因,将页面的设计和Python的代码分离开会更干净简洁更容易维护。 | 翻译 | ||
| 19#翻译 | We can do this with Django's <emphasis>template system</emphasis> , which we discuss in this chapter. | 我们可以使用 Django的 <emphasis>模板系统</emphasis> (Template System)来实现这种模式,这就是本章要具体讨论的问题。 | 翻译 | ||
| 21#翻译 | Template System Basics | 模板系统基本知识 | 翻译 | ||
| 23#翻译 | A Django template is a string of text that is intended to separate the presentation of a document from its data. | 模板是一个文本,用于分离文档的表现形式和内容。 | 翻译 | ||
| 24#翻译 | A template defines placeholders and various bits of basic logic (template tags) that regulate how the document should be displayed. | 模板定义了占位符以及各种用于规范文档该如何显示的各部分基本逻辑(模板标签)。 | 翻译 | ||
| 25#翻译 | Usually, templates are used for producing HTML, but Django templates are equally capable of generating any text-based format. | 模板通常用于产生HTML,但是Django的模板也能产生任何基于文本格式的文档。 | 翻译 | ||
| 27#翻译 | Let's start with a simple example template. | 让我们从一个简单的例子模板开始。 | 翻译 | ||
| 28#翻译 | This Django template describes an HTML page that thanks a person for placing an order with a company. | 该模板描述了一个向某个与公司签单人员致谢 HTML 页面。 | 翻译 | ||
| 29#翻译 | Think of it as a form letter: | 可将其视为一个格式信函: | 翻译 | ||
| 32#翻译 | This template is basic HTML with some variables and template tags thrown in. | 该模板是一段添加了些许变量和模板标签的基础 HTML 。 | 翻译 | ||
| 33#翻译 | Let's step through it: | 让我们逐步分析一下: | 翻译 | ||
| 35#翻译 | Any text surrounded by a pair of braces (e.g., <literal>{{ person_name }}</literal> ) is a <emphasis>variable</emphasis> . This means insert the value of the variable with the given name. | 用两个大括号括起来的文字(例如 <literal>{{ person_name }}</literal> )称为 <emphasis>变量(variable)</emphasis> 。这意味着在此处插入指定变量的值。 | 翻译 | ||
| 36#翻译 | (How do we specify the values of the variables? | 如何指定变量的值呢? | 翻译 | ||
| 37#翻译 | We'll get to that in a moment.) | 稍后就会说明。 | 翻译 | ||
| 39#翻译 | Any text that's surrounded by curly braces and percent signs (e.g., <literal>{% if ordered_warranty %}</literal> ) is a <emphasis>template tag</emphasis> . The definition of a tag is quite broad: | 被大括号和百分号包围的文本(例如 <literal>{% if ordered_warranty %}</literal> )是 <emphasis>模板标签(template tag)</emphasis> 。标签(tag)定义比较明确,即: | 翻译 | ||
| 40#翻译 | a tag just tells the template system to do something. | 仅通知模板系统完成某些工作的标签。 | 翻译 | ||
| 42#翻译 | This example template contains a <literal>for</literal> tag (<literal>{% for item in item_list %}</literal> ) and an <literal>if</literal> tag (<literal>{% if ordered_warranty %}</literal> ). | 这个例子中的模板包含一个<literal>for</literal>标签( <literal>{% for item in item_list %}</literal> )和一个<literal>if</literal> 标签(<literal>{% if ordered_warranty %}</literal> ) | 翻译 | ||
| 44#翻译 | A <literal>for</literal> tag works very much like a <literal>for</literal> statement in Python, letting you loop over each item in a sequence. | for标签类似Python的for语句,可让你循环访问序列里的每一个项目。 | 翻译 | ||
| 45#翻译 | An <literal>if</literal> tag, as you may expect, acts as a logical if statement. | <literal>if</literal> 标签,正如你所料,是用来执行逻辑判断的。 | 翻译 | ||
| 46#翻译 | In this particular case, the tag checks whether the value of the <literal>ordered_warranty</literal> variable evaluates to <literal>True</literal> . If it does, the template system will display everything between the <literal>{% if ordered_warranty %}</literal> and <literal>{% else %}</literal> . If not, the template system will display everything between <literal>{% else %}</literal> and <literal>{% endif %}</literal> . Note that the <literal>{% else %}</literal> is optional. | 在这里,tag标签检查ordered_warranty值是否为True。如果是,模板系统将显示{% if ordered_warranty %}和{% else %}之间的内容;否则将显示{% else %}和{% endif %}之间的内容。{% else %}是可选的。 | 翻译 | ||
| 48#翻译 | Finally, the second paragraph of this template contains an example of a <emphasis>filter</emphasis> , which is the most convenient way to alter the formatting of a variable. | 最后,这个模板的第二段中有一个关于<emphasis>filter</emphasis>过滤器的例子,它是一种最便捷的转换变量输出格式的方式。 | 翻译 | ||
| 49#翻译 | In this example, <literal>{{ ship_date|date:"F j, Y" }}</literal> , we're passing the <literal>ship_date</literal> variable to the <literal>date</literal> filter, giving the <literal>date</literal> filter the argument <literal>"F j, Y"</literal> . The <literal>date</literal> filter formats dates in a given format, as specified by that argument. | 如这个例子中的{{ship_date|date:"F j, Y" }},我们将变量ship_date传递给date过滤器,同时指定参数"F j,Y"。date过滤器根据参数进行格式输出。 | 翻译 | ||
| 50#翻译 | Filters are attached using a pipe character (<literal>|</literal> ), as a reference to Unix pipes. | 过滤器是用管道符(|)来调用的,具体可以参见Unix管道符。 | 翻译 | ||
| 52#翻译 | Each Django template has access to several built-in tags and filters, many of which are discussed in the sections that follow. | Django 模板含有很多内置的tags和filters,我们将陆续进行学习. | 翻译 | ||
| 53#翻译 | Appendix F contains the full list of tags and filters, and it's a good idea to familiarize yourself with that list so you know what's possible. | 附录F列出了很多的tags和filters的列表,熟悉这些列表对你来说是个好建议. | 翻译 | ||
| 54#翻译 | Its also possible to create your own filters and tags; we'll cover that in Chapter 9. | 你依然可以利用它创建自己的tag和filters。这些我们在第9章会讲到。 | 翻译 | ||
| 56#翻译 | Using the Template System | 如何使用模板系统 | 翻译 | ||
| 58#翻译 | Let's dive into Djangos template system so you can see how it works but we're <emphasis>not</emphasis> yet going to integrate it with the views that we created in the previous chapter. | 让我们深入研究模板系统,你将会明白它是如何工作的。但我们暂不打算将它与先前创建的视图结合在一起,因为我们现在的目的是了解它是如何独立工作的。 | 翻译 | ||
| 59#翻译 | Our goal here is to show you how the system works independently of the rest of Django. | 。 | 翻译 | ||
| 60#翻译 | (Put another way: | (换言之, | 翻译 | ||
| 61#翻译 | usually you'll be using the template system within a Django view, but we want to make it clear that the template system is just a Python library that you can use <emphasis>anywhere</emphasis> , not just in Django views.) | 通常你会将模板和视图一起使用,但是我们只是想突出模板系统是一个Python库,你可以在任何地方使用它,而不仅仅是在Django视图中。) | 翻译 | ||
| 63#翻译 | Here is the most basic way you can use Django's template system in Python code: | 在Python代码中使用Django模板的最基本方式如下: | 翻译 | ||
| 65#翻译 | Create a <literal>Template</literal> object by providing the raw template code as a string. | 可以用原始的模板代码字符串创建一个 <literal>Template</literal> 对象, Django同样支持用指定模板文件路径的方式来创建 <literal>Template</literal> 对象; | 翻译 | ||
| 67#翻译 | Call the <literal>render()</literal> method of the <literal>Template</literal> object with a given set of variables (the <emphasis>context</emphasis> ). This returns a fully rendered template as a string, with all of the variables and template tags evaluated according to the context. | 调用模板对象的render方法,并且传入一套变量context。它将返回一个基于模板的展现字符串,模板中的变量和标签会被context值替换。 | 翻译 | ||
| 69#翻译 | In code, here's what that looks like: | 代码如下: | 翻译 | ||
| 72#翻译 | The following sections describe each step in much more detail. | 以下部分逐步的详细介绍 | 翻译 | ||
| 74#翻译 | Creating Template Objects | 创建模板对象 | 翻译 | ||
| 76#翻译 | The easiest way to create a <literal>Template</literal> object is to instantiate it directly. | 创建一个 <literal>Template</literal> 对象最简单的方法就是直接实例化它。 | 翻译 | ||
| 77#翻译 | The <literal>Template</literal> class lives in the <literal>django.template</literal> module, and the constructor takes one argument, the raw template code. | <literal>Template</literal> 类就在 <literal>django.template</literal> 模块中,构造函数接受一个参数,原始模板代码。 | 翻译 | ||
| 78#翻译 | Let's dip into the Python interactive interpreter to see how this works in code. | 让我们深入挖掘一下 Python的解释器看看它是怎么工作的。 | 翻译 | ||
| 80#翻译 | From the <literal>mysite</literal> project directory created by <literal>django-admin.py startproject</literal> (as covered in Chapter 2), type <literal>python manage.py shell</literal> to start the interactive interpreter. | 转到project目录(在第二章由 <literal>django-admin.py startproject</literal> 命令创建), 输入命令 <literal>python manage.py shell</literal> 启动交互界面。 | 翻译 | ||
| 82#翻译 | A special Python prompt | 一个特殊的Python提示符 | 翻译 | ||
| 84#翻译 | If you've used Python before, you may be wondering why we're running <literal>python manage.py shell</literal> instead of just <literal>python</literal> . Both commands will start the interactive interpreter, but the <literal>manage.py shell</literal> command has one key difference: | 如果你曾经使用过Python,你一定好奇,为什么我们运行<literal>python manage.py shell</literal>而不是<literal>python</literal>。这两个命令都会启动交互解释器,但是<literal>manage.py shell</literal>命令有一个重要的不同: | 翻译 | ||
| 85#翻译 | before starting the interpreter, it tells Django which settings file to use. | 在启动解释器之前,它告诉Django使用哪个设置文件。 | 翻译 | ||
| 86#翻译 | Many parts of Django, including the template system, rely on your settings, and you won't be able to use them unless the framework knows which settings to use. | Django框架的大部分子系统,包括模板系统,都依赖于配置文件;如果Django不知道使用哪个配置文件,这些系统将不能工作。 | 翻译 | ||
| 88#翻译 | If you're curious, heres how it works behind the scenes. | 如果你想知道,这里将向你解释它背后是如何工作的。 | 翻译 | ||
| 89#翻译 | Django looks for an environment variable called <literal>DJANGO_SETTINGS_MODULE</literal> , which should be set to the import path of your <literal>settings.py</literal> . For example, <literal>DJANGO_SETTINGS_MODULE</literal> might be set to <literal>'mysite.settings'</literal> , assuming <literal>mysite</literal> is on your Python path. | Django搜索DJANGO_SETTINGS_MODULE环境变量,它被设置在settings.py中。例如,假设mysite在你的Python搜索路径中,那么DJANGO_SETTINGS_MODULE应该被设置为:'mysite.settings'。 | 翻译 | ||
| 91#翻译 | When you run <literal>python manage.py shell</literal> , the command takes care of setting <literal>DJANGO_SETTINGS_MODULE</literal> for you. | 当你运行命令:python manage.py shell,它将自动帮你处理DJANGO_SETTINGS_MODULE。 | 翻译 | ||
| 92#翻译 | We're encouraging you to use <literal>python manage.py shell</literal> in these examples so as to minimize the amount of tweaking and configuring you have to do. | 在当前的这些示例中,我们鼓励你使用<literal> python manage.py shell</literal>这个方法,这样可以免去你大费周章地去配置那些你不熟悉的环境变量。 | 翻译 | ||
| 94#翻译 | As you become more familiar with Django, you'll likely stop using <literal>manage.py shell</literal> and will set <literal>DJANGO_SETTINGS_MODULE</literal> manually in your <literal>.bash_profile</literal> or other shell environment configuration file. | 随着你越来越熟悉Django,你可能会偏向于废弃使用<literal> manage.py shell</literal> ,而是在你的配置文件<literal>.bash_profile</literal>中手动添加 <literal>DJANGO_SETTINGS_MODULE</literal>这个环境变量。 | 翻译 | ||
| 96#翻译 | Let's go through some template system basics: | 让我们来了解一些模板系统的基本知识: | 翻译 | ||
| 99#翻译 | If you're following along interactively, you'll see something like this: | 如果你跟我们一起做,你将会看到下面的内容: | 翻译 | ||
| 102#翻译 | That <literal>0xb7d5f24c</literal> will be different every time, and it isn't relevant; its a Python thing (the Python identity of the <literal>Template</literal> object, if you must know). | <literal>0xb7d5f24c</literal> 每次都会不一样,这没什么关系;这只是Python运行时 <literal>Template</literal> 对象的ID。 | 翻译 | ||
| 104#翻译 | When you create a <literal>Template</literal> object, the template system compiles the raw template code into an internal, optimized form, ready for rendering. | 当你创建一个 <literal>Template</literal> 对象,模板系统在内部编译这个模板到内部格式,并做优化,做好 渲染的准备。 | 翻译 | ||
| 105#翻译 | But if your template code includes any syntax errors, the call to <literal>Template()</literal> will cause a <literal>TemplateSyntaxError</literal> exception: | 如果你的模板语法有错误,那么在调用 <literal>Template()</literal> 时就会抛出 <literal>TemplateSyntaxError</literal> 异常: | 翻译 | ||
| 108#翻译 | The term block tag here refers to <literal>{% notatag %}</literal> . Block tag and template tag are synonymous. | 这里,块标签(block tag)指向的是<literal> {% notatag %}</literal>,块标签与模板标签是同义的。 | 翻译 | ||
| 110#翻译 | The system raises a <literal>TemplateSyntaxError</literal> exception for any of the following cases: | 系统会在下面的情形抛出 <literal>TemplateSyntaxError</literal> 异常: | 翻译 | ||
| 112#翻译 | Invalid tags | 无效的tags | 翻译 | ||
| 114#翻译 | Invalid arguments to valid tags | 标签的参数无效 | 翻译 | ||
| 116#翻译 | Invalid filters | 无效的过滤器 | 翻译 | ||
| 118#翻译 | Invalid arguments to valid filters | 过滤器的参数无效 | 翻译 | ||
| 120#翻译 | Invalid template syntax | 无效的模板语法 | 翻译 | ||
| 122#翻译 | Unclosed tags (for tags that require closing tags) | 未封闭的块标签 (针对需要封闭的块标签) | 翻译 | ||
| 124#翻译 | Rendering a Template | 模板渲染 | 翻译 | ||
| 126#翻译 | Once you have a <literal>Template</literal> object, you can pass it data by giving it a <emphasis>context</emphasis> . A context is simply a set of template variable names and their associated values. | 一旦你创建一个 <literal>Template</literal> 对象,你可以用 <emphasis>context</emphasis> 来传递数据给它。 | 翻译 | ||
| 127#翻译 | A template uses this to populate its variables and evaluate its tags. | 一个context是一系列变量和它们值的集合。 | 翻译 | ||
| 129#翻译 | A context is represented in Django by the <literal>Context</literal> class, which lives in the <literal>django.template</literal> module. | context在Django里表现为 <literal>Context</literal> 类,在 <literal>django.template</literal> 模块里。 | 翻译 | ||
| 130#翻译 | Its constructor takes one optional argument: | 她的构造函数带有一个可选的参数: | 翻译 | ||
| 131#翻译 | a dictionary mapping variable names to variable values. | 一个字典映射变量和它们的值。 | 翻译 | ||
| 132#翻译 | Call the <literal>Template</literal> object's <literal>render()</literal> method with the context to fill the template: | 调用 <literal>Template</literal> 对象 的 <literal>render()</literal> 方法并传递context来填充模板: | 翻译 | ||
| 135#翻译 | One thing we should point out here is that the return value of <literal>t.render(c)</literal> is a Unicode object not a normal Python string. | 我们必须指出的一点是,<literal>t.render(c)</literal>返回的值是一个Unicode对象,不是普通的Python字符串。 | 翻译 | ||
| 136#翻译 | You can tell this by the <literal>u</literal> in front of the string. | 你可以通过字符串前的<literal>u</literal>来区分。 | 翻译 | ||
| 137#翻译 | Django uses Unicode objects instead of normal strings throughout the framework. | 在框架中,Django会一直使用Unicode对象而不是普通的字符串。 | 翻译 | ||
| 138#翻译 | If you understand the repercussions of that, be thankful for the sophisticated things Django does behind the scenes to make it work. | 如果你明白这样做给你带来了多大便利的话,尽可能地感激Django在幕后有条不紊地为你所做这这么多工作吧。 | 翻译 | ||
| 139#翻译 | If you don't understand the repercussions of that, don't worry for now; just know that Django's Unicode support makes it relatively painless for your applications to support a wide variety of character sets beyond the basic A-Z of the English language. | 如果不明白你从中获益了什么,别担心。你只需要知道Django对Unicode的支持,将让你的应用程序轻松地处理各式各样的字符集,而不仅仅是基本的A-Z英文字符。 | 翻译 | ||
| 141#翻译 | Dictionaries and Contexts | 字典和Contexts | 翻译 | ||
| 143#翻译 | A Python dictionary is a mapping between known keys and variable values. | Python的字典数据类型就是关键字和它们值的一个映射。 | 翻译 | ||
| 144#翻译 | A <literal>Context</literal> is similar to a dictionary, but a <literal>Context</literal> provides additional functionality, as covered in Chapter 9. | <literal>Context</literal> 和字典很类似, <literal>Context</literal> 还提供更多的功能,请看第九章。 | 翻译 | ||
| 146#翻译 | Variable names must begin with a letter (A-Z or a-z) and may contain more letters, digits, underscores, and dots. | 变量名必须由英文字符开始 (A-Z或a-z)并可以包含数字字符、下划线和小数点。 | 翻译 | ||
| 147#翻译 | (Dots are a special case we'll get to in a moment.) Variable names are case sensitive. | (小数点在这里有特别的用途,稍后我们会讲到)变量是大小写敏感的。 | 翻译 | ||
| 149#翻译 | Here's an example of template compilation and rendering, using a template similar to the example in the beginning of this chapter: | 下面是编写模板并渲染的示例: | 翻译 | ||
| 152#翻译 | Let's step through this code one statement at a time: | 让我们逐步来分析下这段代码: | 翻译 | ||
| 154#翻译 | First, we import the classes <literal>Template</literal> and <literal>Context</literal> , which both live in the module <literal>django.template</literal> . | 首先我们导入 (import)类 <literal>Template</literal> 和 <literal>Context</literal> ,它们都在模块 <literal>django.template</literal> 里。 | 翻译 | ||
| 156#翻译 | We save the raw text of our template into the variable <literal>raw_template</literal> . Note that we use triple quote marks to designate the string, because it wraps over multiple lines; in contrast, strings within single quote marks cannot be wrapped over multiple lines. | 我们把模板原始文本保存到变量 <literal>raw_template</literal> 。注意到我们使用了三个引号来 标识这些文本,因为这样可以包含多行。 | 翻译 | ||
| 158#翻译 | Next, we create a template object, <literal>t</literal> , by passing <literal>raw_template</literal> to the <literal>Template</literal> class constructor. | 接下来,我们创建了一个模板对象 <literal>t</literal> ,把 <literal>raw_template</literal> 作为 <literal>Template</literal> 类构造函数的参数。 | 翻译 | ||
| 160#翻译 | We import the <literal>datetime</literal> module from Python's standard library, because well need it in the following statement. | 我们从Python的标准库导入 <literal>datetime</literal> 模块,以后我们将会使用它。 | 翻译 | ||
| 162#翻译 | Then, we create a <literal>Context</literal> object, <literal>c</literal> . The <literal>Context</literal> constructor takes a Python dictionary, which maps variable names to values. | 然后,我们创建一个 <literal>Context</literal> 对象, <literal>c</literal> 。 <literal>Context</literal> 构造的参数是Python 字典数据类型。 | 翻译 | ||
| 163#翻译 | Here, for example, we specify that the <literal>person_name</literal> is <literal>'John Smith'</literal> , <literal>company</literal> is <literal>'Outdoor Equipment'</literal> , and so forth. | 在这里,我们指定参数 <literal>person_name</literal> 的值是 <literal>'John Smith'</literal> , 参数company 的值为 'Outdoor Equipment' ,等等。 | 翻译 | ||
| 165#翻译 | Finally, we call the <literal>render()</literal> method on our template object, passing it the context. | 最后,我们在模板对象上调用 <literal>render()</literal> 方法,传递 context参数给它。 | 翻译 | ||
| 166#翻译 | This returns the rendered template i.e., it replaces template variables with the actual values of the variables, and it executes any template tags. | 这是返回渲染后的模板的方法,它会替换模板变量为真实的值和执行块标签。 | 翻译 | ||
| 168#翻译 | Note that the You didn't order a warranty paragraph was displayed because the <literal>ordered_warranty</literal> variable evaluated to <literal>False</literal> . Also note the date, <literal>April 2, 2009</literal> , which is displayed according to the format string <literal>'F j, Y'</literal> . (We'll explain format strings for the <literal>date</literal> filter in a little while.) | 注意,warranty paragraph显示是因为 <literal>ordered_warranty</literal> 的值为 <literal>True</literal> . 注意时间的显示, <literal>April 2, 2009</literal> , 它是按 <literal>'F j, Y'</literal> 格式显示的。 | 翻译 | ||
| 170#翻译 | If you're new to Python, you may wonder why this output includes newline characters (<literal>'\n'</literal> ) rather than displaying the line breaks. | 如果你是Python初学者,你可能在想为什么输出里有回车换行的字符(<literal>'\n'</literal> )而不是 显示回车换行? | 翻译 | ||
| 171#翻译 | That's happening because of a subtlety in the Python interactive interpreter: | 因为这是Python交互解释器的缘故: | 翻译 | ||
| 172#翻译 | the call to <literal>t.render(c)</literal> returns a string, and by default the interactive interpreter displays the <emphasis>representation</emphasis> of the string, rather than the printed value of the string. | 调用 <literal>t.render(c)</literal> 返回字符串, 解释器缺省显示这些字符串的 <emphasis>真实内容呈现</emphasis> ,而不是打印这个变量的值。 | 翻译 | ||
| 173#翻译 | If you want to see the string with line breaks displayed as true line breaks rather than <literal>'\n'</literal> characters, use the <literal>print</literal> statement: | 要显示换行而不是 <literal>'\n'</literal> ,使用 <literal>print</literal> 语句: | 翻译 | ||
| 174#翻译 | <literal>print t.render(c)</literal> . | <literal>print t.render(c)</literal> 。 | 翻译 | ||
| 176#翻译 | Those are the fundamentals of using the Django template system: | 这就是使用Django模板系统的基本规则: | 翻译 | ||
| 177#翻译 | just write a template string, create a <literal>Template</literal> object, create a <literal>Context</literal> , and call the <literal>render()</literal> method. | 写模板,创建 <literal>Template</literal> 对象,创建 <literal>Context</literal> , 调用 <literal>render()</literal> 方法。 | 翻译 | ||
| 179#翻译 | Multiple Contexts, Same Template | 同一模板,多个上下文 | 翻译 | ||
| 181#翻译 | Once you have a <literal>Template</literal> object, you can render multiple contexts through it. | 一旦有了 <literal>模板</literal> 对象,你就可以通过它渲染多个context, | 翻译 | ||
| 182#翻译 | For example: | 例如: | 翻译 | ||
| 185#翻译 | Whenever you're using the same template source to render multiple contexts like this, it's more efficient to create the <literal>Template</literal> object <emphasis>once</emphasis> , and then call <literal>render()</literal> on it multiple times: | 无论何时我们都可以像这样使用同一模板源渲染多个context,只进行 <literal>一次</literal>模板创建然后多次调用render()方法渲染会更为高效: | 翻译 | ||
| 188#翻译 | Django's template parsing is quite fast. | Django 模板解析非常快捷。 | 翻译 | ||
| 189#翻译 | Behind the scenes, most of the parsing happens via a call to a single regular expression. | 大部分的解析工作都是在后台通过对简短正则表达式一次性调用来完成。 | 翻译 | ||
| 190#翻译 | This is in stark contrast to XML-based template engines, which incur the overhead of an XML parser and tend to be orders of magnitude slower than Django's template rendering engine. | 这和基于 XML 的模板引擎形成鲜明对比,那些引擎承担了 XML 解析器的开销,且往往比 Django 模板渲染引擎要慢上几个数量级。 | 翻译 | ||
| 192#翻译 | Context Variable Lookup | 深度变量的查找 | 翻译 | ||
| 194#翻译 | In the examples so far, we've passed simple values in the contexts mostly strings, plus a <literal>datetime.date</literal> example. | 在到目前为止的例子中,我们通过 context 传递的简单参数值主要是字符串,还有一个 <literal>datetime.date</literal> 范例。 | 翻译 | ||
| 195#翻译 | However, the template system elegantly handles more complex data structures, such as lists, dictionaries, and custom objects. | 然而,模板系统能够非常简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。 | 翻译 | ||
| 197#翻译 | The key to traversing complex data structures in Django templates is the dot character (<literal>.</literal> ). Use a dot to access dictionary keys, attributes, methods, or indices of an object. | 在 Django 模板中遍历复杂数据结构的关键是句点字符 (<literal>.</literal>)。 | 翻译 | ||
| 199#翻译 | This is best illustrated with a few examples. | 最好是用几个例子来说明一下。 | 翻译 | ||
| 200#翻译 | For instance, suppose you're passing a Python dictionary to a template. | 比如,假设你要向模板传递一个 Python 字典。 | 翻译 | ||
| 201#翻译 | To access the values of that dictionary by dictionary key, use a dot: | 要通过字典键访问该字典的值,可使用一个句点: | 翻译 | ||
| 204#翻译 | Similarly, dots also allow access of object attributes. | 同样,也可以通过句点来访问对象的属性。 | 翻译 | ||
| 205#翻译 | For example, a Python <literal>datetime.date</literal> object has <literal>year</literal> , <literal>month</literal> , and <literal>day</literal> attributes, and you can use a dot to access those attributes in a Django template: | 比方说, Python 的 <literal>datetime.date</literal> 对象有 <literal>year</literal> 、 <literal>month</literal> 和 <literal>day</literal> 几个属性,你同样可以在模板中使用句点来访问这些属性: | 翻译 | ||
| 208#翻译 | This example uses a custom class, demonstrating that variable dots also allow attribute access on arbitrary objects: | 这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适用于任意的对象。 | 翻译 | ||
| 211#翻译 | Dots can also refer to <emphasis>methods</emphasis> on objects. | 点语法也可以用来引用对象的<emphasis> 方法</emphasis>。 | 翻译 | ||
| 212#翻译 | For example, each Python string has the methods <literal>upper()</literal> and <literal>isdigit()</literal> , and you can call those in Django templates using the same dot syntax: | 例如,每个 Python 字符串都有 <literal>upper()</literal> 和 <literal>isdigit()</literal> 方法,你在模板中可以使用同样的句点语法来调用它们: | 翻译 | ||
| 215#翻译 | Note that you do <emphasis>not</emphasis> include parentheses in the method calls. | 注意这里调用方法时并<emphasis> 没有</emphasis> 使用圆括号 | 翻译 | ||
| 216#翻译 | Also, it's not possible to pass arguments to the methods; you can only call methods that have no required arguments. | 而且也无法给该方法传递参数;你只能调用不需参数的方法。 | 翻译 | ||
| 217#翻译 | (We explain this philosophy later in this chapter.) | (我们将在本章稍后部分解释该设计观。) | 翻译 | ||
| 219#翻译 | Finally, dots are also used to access list indices, for example: | 最后,句点也可用于访问列表索引,例如: | 翻译 | ||
| 222#翻译 | Negative list indices are not allowed. | 不允许使用负数列表索引。 | 翻译 | ||
| 223#翻译 | For example, the template variable <literal>{{ items.-1 }}</literal> would cause a <literal>TemplateSyntaxError</literal> . | 像 <literal>{{ items.-1 }}</literal> 这样的模板变量将会引发<literal> TemplateSyntaxError</literal> | 翻译 | ||
| 225#翻译 | Python Lists | Python 列表类型 | 翻译 | ||
| 227#翻译 | A reminder: | 一点提示: | 翻译 | ||
| 228#翻译 | Python lists have 0-based indices. | Python的列表是从0开始索引。 | 翻译 | ||
| 229#翻译 | The first item is at index 0, the second is at index 1, and so on. | 第一项的索引是0,第二项的是1,依此类推。 | 翻译 | ||
| 231#翻译 | Dot lookups can be summarized like this: | 句点查找规则可概括为: | 翻译 | ||
| 232#翻译 | when the template system encounters a dot in a variable name, it tries the following lookups, in this order: | 当模板系统在变量名中遇到点时,按照以下顺序尝试进行查找: | 翻译 | ||
| 234#翻译 | Dictionary lookup (e.g., <literal>foo["bar"]</literal> ) | 字典类型查找 (比如 <literal>foo["bar"]</literal> ) | 翻译 | ||
| 236#翻译 | Attribute lookup (e.g., <literal>foo.bar</literal> ) | 属性查找 (比如 <literal>foo.bar</literal> ) | 翻译 | ||
| 238#翻译 | Method call (e.g., <literal>foo.bar()</literal> ) | 方法调用 (比如 <literal>foo.bar()</literal> ) | 翻译 | ||
| 240#翻译 | List-index lookup (e.g., <literal>foo[2]</literal> ) | 列表类型索引查找 (比如 <literal>foo[bar]</literal> ) | 翻译 | ||
| 242#翻译 | The system uses the first lookup type that works. | 系统使用找到的第一个有效类型。 | 翻译 | ||
| 243#翻译 | It's short-circuit logic. | 这是一种短路逻辑。 | 翻译 | ||
| 245#翻译 | Dot lookups can be nested multiple levels deep. | 句点查找可以多级深度嵌套。 | 翻译 | ||
| 246#翻译 | For instance, the following example uses <literal>{{ person.name.upper }}</literal> , which translates into a dictionary lookup (<literal>person['name']</literal> ) and then a method call (<literal>upper()</literal> ): | 例如在下面这个例子中 <literal>{{person.name.upper}}</literal> 会转换成字典类型查找( <literal>person['name']</literal> ) 然后是方法调用( <literal>upper()</literal> ): | 翻译 | ||
| 249#翻译 | Method Call Behavior | 方法调用行为 | 翻译 | ||
| 251#翻译 | Method calls are slightly more complex than the other lookup types. | 方法调用比其他类型的查找略为复杂一点。 | 翻译 | ||
| 252#翻译 | Here are some things to keep in mind: | 以下是一些注意事项: | 翻译 | ||
| 254#翻译 | If, during the method lookup, a method raises an exception, the exception will be propagated, unless the exception has an attribute <literal>silent_variable_failure</literal> whose value is <literal>True</literal> . If the exception <emphasis>does</emphasis> have a <literal>silent_variable_failure</literal> attribute, the variable will render as an empty string, for example: | 在方法查找过程中,如果某方法抛出一个异常,除非该异常有一个 <literal>silent_variable_failure</literal> 属性并且值为 <literal>True</literal> ,否则的话它将被传播。如果异常被传播,模板里的指定变量会被置为空字符串,比如: | 翻译 | ||
| 257#翻译 | A method call will only work if the method has no required arguments. | 仅在方法无需传入参数时,其调用才有效。 | 翻译 | ||
| 258#翻译 | Otherwise, the system will move to the next lookup type (list-index lookup). | 否则,系统将会转移到下一个查找类型(列表索引查找)。 | 翻译 | ||
| 260#翻译 | Obviously, some methods have side effects, and it would be foolish at best, and possibly even a security hole, to allow the template system to access them. | 显然,有些方法是有副作用的,好的情况下允许模板系统访问它们可能只是干件蠢事,坏的情况下甚至会引发安全漏洞。 | 翻译 | ||
| 262#翻译 | Say, for instance, you have a <literal>BankAccount</literal> object that has a <literal>delete()</literal> method. | 例如,你的一个 <literal>BankAccount</literal> 对象有一个 <literal>delete()</literal> 方法。 | 翻译 | ||
| 263#翻译 | If a template includes something like <literal>{{ account.delete }}</literal> , where <literal>account</literal> is a <literal>BankAccount</literal> object, the object would be deleted when the template is rendered! | 如果某个模板中包含了像 <literal>{{ account.delete }}</literal>这样的标签,其中<literal> account</literal> 又是<literal>BankAccount</literal> 的一个实例,请注意在这个模板载入时,account对象将被删除。 | 翻译 | ||
| 265#翻译 | To prevent this, set the function attribute <literal>alters_data</literal> on the method: | 要防止这样的事情发生,必须设置该方法的 <literal>alters_data</literal> 函数属性: | 翻译 | ||
| 268#翻译 | The template system won't execute any method marked in this way. | 模板系统不会执行任何以该方式进行标记的方法。 | 翻译 | ||
| 269#翻译 | Continuing the above example, if a template includes <literal>{{ account.delete }}</literal> and the <literal>delete()</literal> method has the <literal>alters_data=True</literal> , then the <literal>delete()</literal> method will not be executed when the template is rendered. | 接上面的例子,如果模板文件里包含了 <literal>{{ account.delete }}</literal> ,对象又具有 <literal>delete()</literal>方法,而且<literal>delete()</literal> 有<literal>alters_data=True</literal>这个属性,那么在模板载入时, <literal>delete()</literal>方法将不会被执行。 | 翻译 | ||
| 270#翻译 | Instead, it will fail silently. | 它将静静地错误退出。 | 翻译 | ||
| 272#翻译 | How Invalid Variables Are Handled | 如何处理无效变量 | 翻译 | ||
| 274#翻译 | By default, if a variable doesn't exist, the template system renders it as an empty string, failing silently. | 默认情况下,如果一个变量不存在,模板系统会把它展示为空字符串,不做任何事情来表示失败。 | 翻译 | ||
| 275#翻译 | For example: | 例如: | 翻译 | ||
| 278#翻译 | The system fails silently rather than raising an exception because it's intended to be resilient to human error. | 系统静悄悄地表示失败,而不是引发一个异常,因为这通常是人为错误造成的。 | 翻译 | ||
| 279#翻译 | In this case, all of the lookups failed because variable names have the wrong case or name. | 这种情况下,因为变量名有错误的状况或名称, 所有的查询都会失败。 | 翻译 | ||
| 280#翻译 | In the real world, it's unacceptable for a Web site to become inaccessible due to a small template syntax error. | 现实世界中,对于一个web站点来说,如果仅仅因为一个小的模板语法错误而造成无法访问,这是不可接受的。 | 翻译 | ||
| 282#翻译 | Playing with Context Objects | 玩一玩上下文(context)对象 | 翻译 | ||
| 284#翻译 | Most of the time, you'll instantiate <literal>Context</literal> objects by passing in a fully populated dictionary to <literal>Context()</literal> . But you can add and delete items from a <literal>Context</literal> object once it's been instantiated, too, using standard Python dictionary syntax: | 多数时间,你可以通过传递一个完全填充(full populated)的字典给 <literal>Context()</literal> 来初始化 <literal>上下文(Context)</literal> 。 但是初始化以后,你也可以使用标准的Python字典语法(syntax)向``上下文(Context)`` 对象添加或者删除条目: | 翻译 | ||
| 287#翻译 | Basic Template Tags and Filters | 基本的模板标签和过滤器 | 翻译 | ||
| 289#翻译 | As we've mentioned already, the template system ships with built-in tags and filters. | 像我们以前提到过的,模板系统带有内置的标签和过滤器。 | 翻译 | ||
| 290#翻译 | The sections that follow provide a rundown of the most common tags and filters. | 下面的章节提供了一个多数通用标签和过滤器的简要说明。 | 翻译 | ||
| 292#翻译 | Tags | 标签 | 翻译 | ||
| 294#翻译 | if/else | if/else | 翻译 | ||
| 296#翻译 | The <literal>{% if %}</literal> tag evaluates a variable, and if that variable is True (i.e., it exists, is not empty, and is not a false Boolean value), the system will display everything between <literal>{% if %}</literal> and <literal>{% endif %}</literal> , for example: | <literal>{% if %}</literal> 标签检查(evaluate)一个变量,如果这个变量为真(即,变量存在,非空,不是布尔值假),系统会显示在 <literal>{% if %}</literal> 和 <literal>{% endif %}</literal> 之间的任何内容,例如: | 翻译 | ||
| 299#翻译 | An <literal>{% else %}</literal> tag is optional: | <literal>{% else %}</literal> 标签是可选的: | 翻译 | ||
| 302#翻译 | Python Truthiness | Python 的“真值” | 翻译 | ||
| 304#翻译 | In Python and in the Django template system, these objects evaluate to <literal>False</literal> in a Boolean context: | 在Python和Django模板系统中,以下这些对象相当于布尔值的<literal>False</literal> | 翻译 | ||
| 306#翻译 | An empty list (<literal>[]</literal> ) | 空列表(<literal>[]</literal> ) | 翻译 | ||
| 308#翻译 | An empty tuple (<literal>()</literal> ) | 空元组(<literal>()</literal> ) | 翻译 | ||
| 310#翻译 | An empty dictionary (<literal>{}</literal> ) | 空字典(<literal>{}</literal> ) | 翻译 | ||
| 312#翻译 | An empty string (<literal>''</literal> ) | 空字符串(<literal>''</literal> ) | 翻译 | ||
| 314#翻译 | Zero (<literal>0</literal> ) | 零值(<literal>0</literal> ) | 翻译 | ||
| 316#翻译 | The special object <literal>None</literal> | 特殊对象<literal>None</literal> | 翻译 | ||
| 318#翻译 | The object <literal>False</literal> (obviously) | 对象<literal>False</literal>(很明显) | 翻译 | ||
| 320#翻译 | Custom objects that define their own Boolean context behavior (this is advanced Python usage) | 提示:你也可以在自定义的对象里定义他们的布尔值属性(这个是python的高级用法)。 | 翻译 | ||
| 322#翻译 | Everything else evaluates to <literal>True</literal> . | 除以上几点以外的所有东西都视为<literal> True</literal> | 翻译 | ||
| 324#翻译 | The <literal>{% if %}</literal> tag accepts <literal>and</literal> , <literal>or</literal> , or <literal>not</literal> for testing multiple variables, or to negate a given variable. | <literal>{% if %}</literal> 标签接受 <literal>and</literal> , <literal>or</literal> 或者 <literal>not</literal> 关键字来对多个变量做判断 ,或者对变量取反( <literal>not</literal> ),例如: | 翻译 | ||
| 325#翻译 | For example: | 例如: | 翻译 | ||
| 328#翻译 | <literal>{% if %}</literal> tags don't allow <literal>and</literal> and <literal>or</literal> clauses within the same tag, because the order of logic would be ambiguous. | <literal>{% if %}</literal> 标签不允许在同一个标签中同时使用 <literal>and</literal> 和 <literal>or</literal> ,因为逻辑上可能模糊的,例如,如下示例是错误的: | 翻译 | ||
| 329#翻译 | For example, this is invalid: | 比如这样的代码是不合法的: | 翻译 | ||
| 332#翻译 | The use of parentheses for controlling order of operations is not supported. | 系统不支持用圆括号来组合比较操作。 | 翻译 | ||
| 333#翻译 | If you find yourself needing parentheses, consider performing logic outside the template and passing the result of that as a dedicated template variable. | 如果你确实需要用到圆括号来组合表达你的逻辑式,考虑将它移到模板之外处理,然后以模板变量的形式传入结果吧。 | 翻译 | ||
| 334#翻译 | Or, just use nested <literal>{% if %}</literal> tags, like this: | 或者,仅仅用嵌套的<literal>{% if %}</literal>标签替换吧,就像这样: | 翻译 | ||
| 337#翻译 | Multiple uses of the same logical operator are fine, but you can't combine different operators. | 多次使用同一个逻辑操作符是没有问题的,但是我们不能把不同的操作符组合起来。 | 翻译 | ||
| 338#翻译 | For example, this is valid: | 例如,这是合法的: | 翻译 | ||
| 341#翻译 | There is no <literal>{% elif %}</literal> tag. | 并没有 <literal>{% elif %}</literal> 标签, | 翻译 | ||
| 342#翻译 | Use nested <literal>{% if %}</literal> tags to accomplish the same thing: | 请使用嵌套的<literal> {% if %}</literal> 标签来达成同样的效果: | 翻译 | ||
| 345#翻译 | Make sure to close each <literal>{% if %}</literal> with an <literal>{% endif %}</literal> . Otherwise, Django will throw a <literal>TemplateSyntaxError</literal> . | 一定要用 <literal>{% endif %}</literal> 关闭每一个 <literal>{% if %}</literal> 标签。 | 翻译 | ||
| 347#翻译 | for | for | 翻译 | ||
| 349#翻译 | The <literal>{% for %}</literal> tag allows you to loop over each item in a sequence. | <literal>{% for %}</literal> 允许我们在一个序列上迭代。 | 翻译 | ||
| 350#翻译 | As in Python's <literal>for</literal> statement, the syntax is <literal>for X in Y</literal> , where <literal>Y</literal> is the sequence to loop over and <literal>X</literal> is the name of the variable to use for a particular cycle of the loop. | 与Python的 <literal>for</literal> 语句的情形类似,循环语法是 <literal>for X in Y</literal> ,Y是要迭代的序列而X是在每一个特定的循环中使用的变量名称。 | 翻译 | ||
| 351#翻译 | Each time through the loop, the template system will render everything between <literal>{% for %}</literal> and <literal>{% endfor %}</literal> . | 每一次循环中,模板系统会渲染在 <literal>{% for %}</literal> 和 <literal>{% endfor %}</literal> 之间的所有内容。 | 翻译 | ||
| 353#翻译 | For example, you could use the following to display a list of athletes given a variable <literal>athlete_list</literal> : | 例如,给定一个运动员列表 <literal>athlete_list</literal> 变量,我们可以使用下面的代码来显示这个列表: | 翻译 | ||
| 356#翻译 | Add <literal>reversed</literal> to the tag to loop over the list in reverse: | 给标签增加一个 <literal>reversed</literal> 使得该列表被反向迭代: | 翻译 | ||
| 359#翻译 | It's possible to nest <literal>{% for %}</literal> tags: | 可以嵌套使用 <literal>{% for %}</literal> 标签: | 翻译 | ||
| 362#翻译 | A common pattern is to check the size of the list before looping over it, and outputting some special text if the list is empty: | 在执行循环之前先检测列表的大小是一个通常的做法,当列表为空时输出一些特别的提示。 | 翻译 | ||
| 365#翻译 | Because this pattern is so common, the <literal>for</literal> tag supports an optional <literal>{% empty %}</literal> clause that lets you define what to output if the list is empty. | 因为这种做法十分常见,所以<literal> for</literal> 标签支持一个可选的<literal> {% empty %}</literal> 分句,通过它我们可以定义当列表为空时的输出内容 | 翻译 | ||
| 366#翻译 | This example is equivalent to the previous one: | 下面的例子与之前那个等价: | 翻译 | ||
| 369#翻译 | There is no support for breaking out of a loop before the loop is finished. | Django不支持退出循环操作。 | 翻译 | ||
| 370#翻译 | If you want to accomplish this, change the variable you're looping over so that it includes only the values you want to loop over. | 如果我们想退出循环,可以改变正在迭代的变量,让其仅仅包含需要迭代的项目。 | 翻译 | ||
| 371#翻译 | Similarly, there is no support for a continue statement that would instruct the loop processor to return immediately to the front of the loop. | 同理,Django也不支持continue语句,我们无法让当前迭代操作跳回到循环头部。 | 翻译 | ||
| 372#翻译 | (See the section Philosophies and Limitations later in this chapter for the reasoning behind this design decision.) | (请参看本章稍后的理念和限制小节,了解下决定这个设计的背后原因) | 翻译 | ||
| 374#翻译 | Within each <literal>{% for %}</literal> loop, you get access to a template variable called <literal>forloop</literal> . This variable has a few attributes that give you information about the progress of the loop: | 在每个<literal> {% for %}</literal>循环里有一个称为<literal> forloop</literal> 的模板变量。这个变量有一些提示循环进度信息的属性。 | 翻译 | ||
| 376#翻译 | <literal>forloop.counter</literal> is always set to an integer representing the number of times the loop has been entered. | <literal>forloop.counter</literal> 总是一个表示当前循环的执行次数的整数计数器。 | 翻译 | ||
| 377#翻译 | This is one-indexed, so the first time through the loop, <literal>forloop.counter</literal> will be set to <literal>1</literal> . Here's an example: | 这个计数器是从1开始的,所以在第一次循环时 <literal>forloop.counter</literal> 将会被设置为1。 | 翻译 | ||
| 380#翻译 | <literal>forloop.counter0</literal> is like <literal>forloop.counter</literal> , except it's zero-indexed. | <literal>forloop.counter0</literal> 类似于 <literal>forloop.counter</literal> ,但是它是从0计数的。 | 翻译 | ||
| 381#翻译 | Its value will be set to <literal>0</literal> the first time through the loop. | 第一次执行循环时这个变量会被设置为0。 | 翻译 | ||
| 383#翻译 | <literal>forloop.revcounter</literal> is always set to an integer representing the number of remaining items in the loop. | <literal>forloop.revcounter</literal> 是表示循环中剩余项的整型变量。 | 翻译 | ||
| 384#翻译 | The first time through the loop, <literal>forloop.revcounter</literal> will be set to the total number of items in the sequence you're traversing. | 在循环初次执行时 <literal>forloop.revcounter</literal> 将被设置为序列中项的总数。 | 翻译 | ||
| 385#翻译 | The last time through the loop, <literal>forloop.revcounter</literal> will be set to <literal>1</literal> . | 最后一次循环执行中,这个变量将被置1。 | 翻译 | ||
| 387#翻译 | <literal>forloop.revcounter0</literal> is like <literal>forloop.revcounter</literal> , except it's zero-indexed. | <literal>forloop.revcounter0</literal> 类似于 <literal>forloop.revcounter</literal> ,但它以0做为结束索引。 | 翻译 | ||
| 388#翻译 | The first time through the loop, <literal>forloop.revcounter0</literal> will be set to the number of elements in the sequence minus 1. The last time through the loop, it will be set to <literal>0</literal> . | 在第一次执行循环时,该变量会被置为序列的项的个数减1。 | 翻译 | ||
| 390#翻译 | <literal>forloop.first</literal> is a Boolean value set to <literal>True</literal> if this is the first time through the loop. | <literal>forloop.first</literal> 是一个布尔值,如果该迭代是第一次执行,那么它被置为<literal></literal> | 翻译 | ||
| 391#翻译 | This is convenient for special-casing: | 在下面的情形中这个变量是很有用的: | 翻译 | ||
| 394#翻译 | <literal>forloop.last</literal> is a Boolean value set to <literal>True</literal> if this is the last time through the loop. | <literal>forloop.last</literal> 是一个布尔值;在最后一次执行循环时被置为True。 | 翻译 | ||
| 395#翻译 | A common use for this is to put pipe characters between a list of links: | 一个常见的用法是在一系列的链接之间放置管道符(|) | 翻译 | ||
| 398#翻译 | The above template code might output something like this: | 上面的模板可能会产生如下的结果: | 翻译 | ||
| 401#翻译 | Another common use for this is to put a comma between words in a list: | 另一个常见的用途是为列表的每个单词的加上逗号。 | 翻译 | ||
| 404#翻译 | <literal>forloop.parentloop</literal> is a reference to the <literal>forloop</literal> object for the <emphasis>parent</emphasis> loop, in case of nested loops. | <literal>forloop.parentloop</literal> 是一个指向当前循环的上一级循环的 <literal>forloop</literal> 对象的引用(在嵌套循环的情况下)。 | 翻译 | ||
| 405#翻译 | Here's an example: | 例子在此: | 翻译 | ||
| 408#翻译 | The magic <literal>forloop</literal> variable is only available within loops. | <literal>forloop</literal> 变量仅仅能够在循环中使用。 | 翻译 | ||
| 409#翻译 | After the template parser has reached <literal>{% endfor %}</literal> , <literal>forloop</literal> disappears. | 在模板解析器碰到<literal>{% endfor %}</literal>标签后,<literal>forloop</literal>就不可访问了。 | 翻译 | ||
| 411#翻译 | Context and the forloop Variable | Context和forloop变量 | 翻译 | ||
| 413#翻译 | Inside the <literal>{% for %}</literal> block, the existing variables are moved out of the way to avoid overwriting the magic <literal>forloop</literal> variable. | 在一个 <literal>{% for %}</literal> 块中,已存在的变量会被移除,以避免 <literal>forloop</literal> 变量被覆盖。 | 翻译 | ||
| 414#翻译 | Django exposes this moved context in <literal>forloop.parentloop</literal> . You generally don't need to worry about this, but if you supply a template variable named <literal>forloop</literal> (though we advise against it), it will be named <literal>forloop.parentloop</literal> while inside the <literal>{% for %}</literal> block. | Django会把这个变量移动到 <literal>forloop.parentloop</literal> 中。通常我们不用担心这个问题,但是一旦我们在模板中定义了 <literal>forloop</literal> 这个变量(当然我们反对这样做),在 <literal>{% for %}</literal> 块中它会在 <literal>forloop.parentloop</literal> 被重新命名。 | 翻译 | ||
| 416#翻译 | ifequal/ifnotequal | ifequal/ifnotequal | 翻译 | ||
| 418#翻译 | The Django template system deliberately is not a full-fledged programming language and thus does not allow you to execute arbitrary Python statements. | Django模板系统压根儿就没想过实现一个全功能的编程语言,所以它不允许我们在模板中执行Python的语句(还是那句话,要了解更多请参看理念和限制小节)。 | 翻译 | ||
| 419#翻译 | (More on this idea in the section Philosophies and Limitations.) However, it's quite a common template requirement to compare two values and display something if they're equal and Django provides an <literal>{% ifequal %}</literal> tag for that purpose. | 但是比较两个变量的值并且显示一些结果实在是个太常见的需求了,所以Django提供了 <literal>{% ifequal %}</literal> 标签供我们使用。 | 翻译 | ||
| 421#翻译 | The <literal>{% ifequal %}</literal> tag compares two values and displays everything between <literal>{% ifequal %}</literal> and <literal>{% endifequal %}</literal> if the values are equal. | <literal>{% ifequal %}</literal> 标签比较两个值,当他们相等时,显示在 <literal>{% ifequal %}</literal> 和 <literal>{% endifequal %}</literal> 之中所有的值。 | 翻译 | ||
| 423#翻译 | This example compares the template variables <literal>user</literal> and <literal>currentuser</literal> : | 下面的例子比较两个模板变量 <literal>user</literal> 和 <literal>currentuser</literal> : | 翻译 | ||
| 426#翻译 | The arguments can be hard-coded strings, with either single or double quotes, so the following is valid: | 参数可以是硬编码的字符串,随便用单引号或者双引号引起来,所以下列代码都是正确的: | 翻译 | ||
| 429#翻译 | Just like <literal>{% if %}</literal> , the <literal>{% ifequal %}</literal> tag supports an optional <literal>{% else %}</literal> : | 和 <literal>{% if %}</literal> 类似, <literal>{% ifequal %}</literal> 支持可选的 <literal>{% else%}</literal> 标签: | 翻译 | ||
| 432#翻译 | Only template variables, strings, integers, and decimal numbers are allowed as arguments to <literal>{% ifequal %}</literal> . These are valid examples: | 只有模板变量,字符串,整数和小数可以作为 <literal>{% ifequal %}</literal> 标签的参数。下面是合法参数的例子: | 翻译 | ||
| 435#翻译 | Any other types of variables, such as Python dictionaries, lists, or Booleans, can't be hard-coded in <literal>{% ifequal %}</literal> . These are invalid examples: | 其他任何类型,例如Python的字典类型、列表类型、布尔类型,不能用在 <literal>{% ifequal %}</literal> 中。 下面是些错误的例子: | 翻译 | ||
| 438#翻译 | If you need to test whether something is true or false, use the <literal>{% if %}</literal> tags instead of <literal>{% ifequal %}</literal> . | 如果你需要判断变量是真还是假,请使用 <literal>{% if %}</literal> 来替代 <literal>{% ifequal %}</literal> 。 | 翻译 | ||
| 440#翻译 | Comments | 注释 | 翻译 | ||
| 442#翻译 | Just as in HTML or Python, the Django template language allows for comments. | 就像HTML或者Python,Django模板语言同样提供代码注释。 | 翻译 | ||
| 443#翻译 | To designate a comment, use <literal>{# #}</literal> : | 注释使用 <literal>{# #}</literal> : | 翻译 | ||
| 446#翻译 | The comment will not be output when the template is rendered. | 注释的内容不会在模板渲染时输出。 | 翻译 | ||
| 448#翻译 | Comments using this syntax cannot span multiple lines. | 用这种语法的注释不能跨越多行。 | 翻译 | ||
| 449#翻译 | This limitation improves template parsing performance. | 这个限制是为了提高模板解析的性能。 | 翻译 | ||
| 450#翻译 | In the following template, the rendered output will look exactly the same as the template (i.e., the comment tag will not be parsed as a comment): | 在下面这个模板中,输出结果和模板本身是 完全一样的(也就是说,注释标签并没有被解析为注释): | 翻译 | ||
| 453#翻译 | If you want to use multi-line comments, use the <literal>{% comment %}</literal> template tag, like this: | 如果要实现多行注释,可以使用<literal> {% comment %}</literal> 模板标签,就像这样: | 翻译 | ||
| 456#翻译 | Filters | 过滤器 | 翻译 | ||
| 458#翻译 | As explained earlier in this chapter, template filters are simple ways of altering the value of variables before they're displayed. | 就象本章前面提到的一样,模板过滤器是在变量被显示前修改它的值的一个简单方法。 | 翻译 | ||
| 459#翻译 | Filters use a pipe character, like this: | 过滤器使用管道字符,如下所示: | 翻译 | ||
| 462#翻译 | This displays the value of the <literal>{{ name }}</literal> variable after being filtered through the <literal>lower</literal> filter, which converts text to lowercase. | 显示的内容是变量 <literal>{{ name }}</literal> 被过滤器 <literal>lower</literal> 处理后的结果,它功能是转换文本为小写。 | 翻译 | ||
| 464#翻译 | Filters can be <emphasis>chained</emphasis> that is, they can be used in tandem such that the output of one filter is applied to the next. | 过滤管道可以被<emphasis> 套接</emphasis> ,既是说,一个过滤器管道的输出又可以作为下一个管道的输入,如此下去。 | 翻译 | ||
| 465#翻译 | Here's an example that takes the first element in a list and converts it to uppercase: | 下面的例子实现查找列表的第一个元素并将其转化为大写。 | 翻译 | ||
| 468#翻译 | Some filters take arguments. | 有些过滤器有参数。 | 翻译 | ||
| 469#翻译 | A filter argument comes after a colon and is always in double quotes. | 过滤器的参数跟随冒号之后并且总是以双引号包含。 | 翻译 | ||
| 470#翻译 | For example: | 例如: | 翻译 | ||
| 473#翻译 | This displays the first 30 words of the <literal>bio</literal> variable. | 这个将显示变量 <literal>bio</literal> 的前30个词。 | 翻译 | ||
| 475#翻译 | The following are a few of the most important filters. | 以下几个是最为重要的过滤器的一部分。 | 翻译 | ||
| 476#翻译 | Appendix F covers the rest. | 附录F包含其余的过滤器。 | 翻译 | ||
| 478#翻译 | <literal>addslashes</literal> : Adds a backslash before any backslash, single quote, or double quote. | <literal>addslashes</literal> : 添加反斜杠到任何反斜杠、单引号或者双引号前面。 | 翻译 | ||
| 479#翻译 | This is useful if the produced text is included in a JavaScript string. | 这在处理包含JavaScript的文本时是非常有用的。 | 翻译 | ||
| 481#翻译 | <literal>date</literal> : Formats a <literal>date</literal> or <literal>datetime</literal> object according to a format string given in the parameter, for example: | <literal>date</literal> : 按指定的格式字符串参数格式化 <literal>date</literal> 或者 <literal>datetime</literal> 对象, 范例: | 翻译 | ||
| 484#翻译 | Format strings are defined in Appendix F. | 格式参数的定义在附录F中。 | 翻译 | ||
| 486#翻译 | <literal>length</literal> : Returns the length of the value. | <literal>length</literal> : 返回变量的长度。 | 翻译 | ||
| 487#翻译 | For a list, this returns the number of elements. | 对于列表,这个参数将返回列表元素的个数。 | 翻译 | ||
| 488#翻译 | For a string, this returns the number of characters. | 对于字符串,这个参数将返回字符串中字符的个数。 | 翻译 | ||
| 489#翻译 | (Python experts, take note that this works on any Python object that knows how to determine its length i.e., any object that has a <literal>__len__()</literal> method.) | 你可以对列表或者字符串,或者任何知道怎么测定长度的Python 对象使用这个方法(也就是说,有 <literal>__len__()</literal> 方法的对象)。 | 翻译 | ||
| 491#翻译 | Philosophies and Limitations | 理念与局限 | 翻译 | ||
| 493#翻译 | Now that you've gotten a feel for the Django template language, we should point out some of its intentional limitations, along with some philosophies behind why it works the way it works. | 现在你已经对Django的模板语言有一些认识了,我们将指出一些特意设置的限制和为什么要这样做 背后的一些设计哲学。 | 翻译 | ||
| 495#翻译 | More than any other component of Web applications, template syntax is highly subjective, and programmers' opinions vary wildly. | 相对与其他的网络应用的组件,模板的语法很具主观性,因此可供程序员的选择方案也很广泛。 | 翻译 | ||
| 496#翻译 | The fact that Python alone has dozens, if not hundreds, of open source template-language implementations supports this point. | 事实上,Python有成十上百的 开放源码的模板语言实现。 | 翻译 | ||
| 497#翻译 | Each was likely created because its developer deemed all existing template languages inadequate. | 每个实现都是因为开发者认为现存的模板语言不够用。 | 翻译 | ||
| 498#翻译 | (In fact, it is said to be a rite of passage for a Python developer to write his or her own template language! | (事实上,对一个 Python开发者来说,写一个自己的模板语言就象是某种“成人礼”一样! | 翻译 | ||
| 499#翻译 | If you haven't done this yet, consider it. | 如果你还没有完成一个自己的 模板语言,好好考虑写一个,这是一个非常有趣的锻炼。 | 翻译 | ||
| 500#翻译 | Its a fun exercise.) | ) | 翻译 | ||
| 502#翻译 | With that in mind, you might be interested to know that Django doesn't require that you use its template language. | 明白了这个,你也许有兴趣知道事实上Django并不强制要求你必须使用它的模板语言。 | 翻译 | ||
| 503#翻译 | Because Django is intended to be a full-stack Web framework that provides all the pieces necessary for Web developers to be productive, many times it's <emphasis>more convenient</emphasis> to use Django's template system than other Python template libraries, but it's not a strict requirement in any sense. | 因为Django 虽然被设计成一个FULL-Stack的Web框架,它提供了开发者所必需的所有组件,而且在大多数情况 使用Django模板系统会比其他的Python模板库要 <emphasis>更方便</emphasis> 一点,但是并不是严格要求你必须使用 它。 | 翻译 | ||
| 504#翻译 | As you'll see in the upcoming section Using Templates in Views, it's very easy to use another template language with Django. | 你将在后续的“视图中应用模板”这一章节中看到,你还可以非常容易地在Django中使用其他的模板语言。 | 翻译 | ||
| 506#翻译 | Still, it's clear we have a strong preference for the way Django's template language works. | 虽然如此,很明显,我们对Django模板语言的工作方式有着强烈的偏爱。 | 翻译 | ||
| 507#翻译 | The template system has roots in how Web development is done at World Online and the combined experience of Django's creators. | 这个模板语言来源于World Online的开发经验和Django创造者们集体智慧的结晶。 | 翻译 | ||
| 508#翻译 | Here are a few of those philosophies: | 下面是关于它的一些设计哲学理念: | 翻译 | ||
| 510#翻译 | <emphasis>Business logic should be separated from presentation logic</emphasis> . Django's developers see a template system as a tool that controls presentation and presentation-related logic and that's it. | <emphasis>业务逻辑应该和表现逻辑相对分开</emphasis> 。我们将模板系统视为控制表现及表现相关逻辑的工具,仅此而已。 | 翻译 | ||
| 511#翻译 | The template system shouldn't support functionality that goes beyond this basic goal. | 模板系统不应提供超出此基本目标的功能。 | 翻译 | ||
| 513#翻译 | For that reason, it's impossible to call Python code directly within Django templates. | 出于这个原因,在 Django 模板中是不可能直接调用 Python 代码的。 | 翻译 | ||
| 514#翻译 | All programming is fundamentally limited to the scope of what template tags can do. | 所有的编程工作基本上都被局限于模板标签的能力范围。 | 翻译 | ||
| 515#翻译 | It <emphasis>is</emphasis> possible to write custom template tags that do arbitrary things, but the out-of-the-box Django template tags intentionally do not allow for arbitrary Python code execution. | 当然, <emphasis>是</emphasis> 有可能写出自定义的模板标签来完成任意工作,但这些“超范围”的 Django 模板标签有意地不允许执行任何 Python 代码。 | 翻译 | ||
| 517#翻译 | <emphasis>Syntax should be decoupled from HTML/XML</emphasis> . Although Django's template system is used primarily to produce HTML, it's intended to be just as usable for non-HTML formats, such as plain text. | <emphasis>语法不应受到 HTML/XML 的束缚</emphasis> 。尽管 Django 模板系统主要用于生成 HTML,它还是被有意地设计为可生成非 HTML 格式,如纯文本。 | 翻译 | ||
| 518#翻译 | Some other template languages are XML based, placing all template logic within XML tags or attributes, but Django deliberately avoids this limitation. | 一些其它的模板语言是基于 XML 的,将所有的模板逻辑置于 XML 标签与属性之中,而 Django 有意地避开了这种限制。 | 翻译 | ||
| 519#翻译 | Requiring valid XML to write templates introduces a world of human mistakes and hard-to-understand error messages, and using an XML engine to parse templates incurs an unacceptable level of overhead in template processing. | 强制要求使用有效 XML 编写模板将会引发大量的人为错误和难以理解的错误信息,而且使用 XML 引擎解析模板也会导致令人无法容忍的模板处理开销。 | 翻译 | ||
| 521#翻译 | <emphasis>Designers are assumed to be comfortable with HTML code</emphasis> . The template system isn't designed so that templates necessarily are displayed nicely in WYSIWYG editors such as Dreamweaver. | <emphasis>假定设计师精通 HTML 编码</emphasis> 。模板系统的设计意图并不是为了让模板一定能够很好地显示在 Dreamweaver 这样的所见即所得编辑器中。 | 翻译 | ||
| 522#翻译 | That is too severe a limitation and wouldn't allow the syntax to be as friendly as it is. | 这种限制过于苛刻,而且会使得语法不能像目前这样的完美。 | 翻译 | ||
| 523#翻译 | Django expects template authors to be comfortable editing HTML directly. | Django 要求模板创作人员对直接编辑 HTML 非常熟悉。 | 翻译 | ||
| 525#翻译 | <emphasis>Designers are assumed not to be Python programmers</emphasis> . The template system authors recognize that Web page templates are most often written by <emphasis>designers</emphasis> , not <emphasis>programmers</emphasis> , and therefore should not assume Python knowledge. | <emphasis>假定设计师不是 Python 程序员</emphasis> 。模板系统开发人员认为:模板通常由设计师而非程序员来编写,因此不应被假定拥有Python开发知识。 | 翻译 | ||
| 527#翻译 | However, the system also intends to accommodate small teams in which the templates <emphasis>are</emphasis> created by Python programmers. | 当然,系统同样也特意地提供了对那些 <emphasis>由</emphasis> Python 程序员进行模板制作的小型团队的支持。 | 翻译 | ||
| 528#翻译 | It offers a way to extend the system's syntax by writing raw Python code. | 它提供了一种工作模式,允许通过编写原生 Python 代码进行系统语法拓展。 | 翻译 | ||
| 529#翻译 | (More on this in Chapter 9.) | (详见第十章) | 翻译 | ||
| 531#翻译 | <emphasis>The goal is not to invent a programming language</emphasis> . The goal is to offer just enough programming-esque functionality, such as branching and looping, that is essential for making presentation-related decisions. | <emphasis>目标并不是要发明一种编程语言</emphasis> 。目标是恰到好处地提供如分支和循环这一类编程式功能,这是进行与表现相关判断的基础。 | 翻译 | ||
| 533#翻译 | Using Templates in Views | 在视图中使用模板 | 翻译 | ||
| 535#翻译 | You've learned the basics of using the template system; now let's use this knowledge to create a view. | 在学习了模板系统的基础之后,现在让我们使用相关知识来创建视图。 | 翻译 | ||
| 536#翻译 | Recall the <literal>current_datetime</literal> view in <literal>mysite.views</literal> , which we started in the previous chapter. | 重新打开我们在前一章在 <literal>mysite.views</literal> 中创建的 <literal>current_datetime</literal> 视图。 | 翻译 | ||
| 537#翻译 | Here's what it looks like: | 以下是其内容: | 翻译 | ||
| 540#翻译 | Let's change this view to use Django's template system. | 让我们用 Django 模板系统来修改该视图。 | 翻译 | ||
| 541#翻译 | At first, you might think to do something like this: | 第一步,你可能已经想到了要做下面这样的修改: | 翻译 | ||
| 544#翻译 | Sure, that uses the template system, but it doesn't solve the problems we pointed out in the introduction of this chapter. | 没错,它确实使用了模板系统,但是并没有解决我们在本章开头所指出的问题。 | 翻译 | ||
| 545#翻译 | Namely, the template is still embedded in the Python code, so true separation of data and presentation isn't achieved. | 也就是说,模板仍然嵌入在Python代码里,并未真正的实现数据与表现的分离。 | 翻译 | ||
| 546#翻译 | Lets fix that by putting the template in a <emphasis>separate file</emphasis> , which this view will load. | 让我们将模板置于一个 <emphasis>单独的文件</emphasis> 中,并且让视图加载该文件来解决此问题。 | 翻译 | ||
| 548#翻译 | You might first consider saving your template somewhere on your filesystem and using Python's built-in file-opening functionality to read the contents of the template. | 你可能首先考虑把模板保存在文件系统的某个位置并用 Python 内建的文件操作函数来读取文件内容。 | 翻译 | ||
| 549#翻译 | Here's what that might look like, assuming the template was saved as the file <literal>/home/djangouser/templates/mytemplate.html</literal> : | 假设文件保存在 <literal>/home/djangouser/templates/mytemplate.html</literal> 中的话,代码就会像下面这样: | 翻译 | ||
| 552#翻译 | This approach, however, is inelegant for these reasons: | 然而,基于以下几个原因,该方法还算不上简洁: | 翻译 | ||
| 554#翻译 | It doesn't handle the case of a missing file. | 它没有对文件丢失的情况做出处理。 | 翻译 | ||
| 555#翻译 | If the file <literal>mytemplate.html</literal> doesn't exist or isn't readable, the <literal>open()</literal> call will raise an <literal>IOError</literal> exception. | 如果文件 <literal>mytemplate.html</literal> 不存在或者不可读, <literal>open()</literal> 函数调用将会引发 <literal>IOError</literal> 异常。 | 翻译 | ||
| 557#翻译 | It hard-codes your template location. | 这里对模板文件的位置进行了硬编码。 | 翻译 | ||
| 558#翻译 | If you were to use this technique for every view function, you'd be duplicating the template locations. | 如果你在每个视图函数都用该技术,就要不断复制这些模板的位置。 | 翻译 | ||
| 559#翻译 | Not to mention it involves a lot of typing! | 更不用说还要带来大量的输入工作! | 翻译 | ||
| 561#翻译 | It includes a lot of boring boilerplate code. | 它包含了大量令人生厌的重复代码。 | 翻译 | ||
| 562#翻译 | You've got better things to do than to write calls to <literal>open()</literal> , <literal>fp.read()</literal> , and <literal>fp.close()</literal> each time you load a template. | 与其在每次加载模板时都调用 <literal>open()</literal> 、 <literal>fp.read()</literal> 和 <literal>fp.close()</literal> ,还不如做出更佳选择。 | 翻译 | ||
| 564#翻译 | To solve these issues, we'll use <emphasis>template loading</emphasis> and <emphasis>template directories</emphasis> . | 为了解决这些问题,我们采用了 <emphasis>模板自加载</emphasis> 跟 <emphasis>模板目录</emphasis> 的技巧. | 翻译 | ||
| 566#翻译 | Template Loading | 模板加载 | 翻译 | ||
| 568#翻译 | Django provides a convenient and powerful API for loading templates from the filesystem, with the goal of removing redundancy both in your template-loading calls and in your templates themselves. | 为了减少模板加载调用过程及模板本身的冗余代码,Django 提供了一种使用方便且功能强大的 API ,用于从磁盘中加载模板, | 翻译 | ||
| 570#翻译 | In order to use this template-loading API, first you'll need to tell the framework where you store your templates. | 要使用此模板加载API,首先你必须将模板的保存位置告诉框架。 | 翻译 | ||
| 571#翻译 | The place to do this is in your settings file the <literal>settings.py</literal> file that we mentioned last chapter, when we introduced the <literal>ROOT_URLCONF</literal> setting. | 设置的保存文件就是我们前一章节讲述<literal>ROOT_URLCONF</literal>配置的时候提到的 <literal>settings.py</literal>。 | 翻译 | ||
| 573#翻译 | If you're following along, open your <literal>settings.py</literal> and find the <literal>TEMPLATE_DIRS</literal> setting. | 如果你是一步步跟随我们学习过来的,马上打开你的<literal>settings.py</literal>配置文件,找到<literal>TEMPLATE_DIRS</literal>这项设置吧。 | 翻译 | ||
| 574#翻译 | By default, it's an empty tuple, likely containing some auto-generated comments: | 它的默认设置是一个空元组(tuple),加上一些自动生成的注释。 | 翻译 | ||
| 577#翻译 | This setting tells Django's template-loading mechanism where to look for templates. | 该设置告诉 Django 的模板加载机制在哪里查找模板。 | 翻译 | ||
| 578#翻译 | Pick a directory where you'd like to store your templates and add it to <literal>TEMPLATE_DIRS</literal> , like so: | 选择一个目录用于存放模板并将其添加到 <literal>TEMPLATE_DIRS</literal> 中: | 翻译 | ||
| 581#翻译 | There are a few things to note: | 下面是一些注意事项: | 翻译 | ||
| 583#翻译 | You can specify any directory you want, as long as the directory and templates within that directory are readable by the user account under which your Web server runs. | 你可以任意指定想要的目录,只要运行 Web 服务器的用户可以读取该目录的子目录和模板文件。 | 翻译 | ||
| 584#翻译 | If you can't think of an appropriate place to put your templates, we recommend creating a <literal>templates</literal> directory within your project (i.e., within the <literal>mysite</literal> directory you created in Chapter 2). | 如果实在想不出合适的位置来放置模板,我们建议在 Django 项目中创建一个 <literal>templates</literal> 目录(也就是说,如果你一直都按本书的范例操作的话,在第二章创建的 <literal>mysite</literal> 目录中)。 | 翻译 | ||
| 586#翻译 | If your <literal>TEMPLATE_DIRS</literal> contains only one directory, don't forget the comma at the end of the directory string! | 如果你的 <literal>TEMPLATE_DIRS</literal>只包含一个目录,别忘了在该目录后加上个逗号。 | 翻译 | ||
| 588#翻译 | Bad: | Bad: | 翻译 | ||
| 591#翻译 | Good: | Good: | 翻译 | ||
| 594#翻译 | The reason for this is that Python requires commas within single-element tuples to disambiguate the tuple from a parenthetical expression. | Python 要求单元素元组中必须使用逗号,以此消除与圆括号表达式之间的歧义。 | 翻译 | ||
| 595#翻译 | This is a common newbie gotcha. | 这是新手常犯的错误。 | 翻译 | ||
| 597#翻译 | If you're on Windows, include your drive letter and use Unix-style forward slashes rather than backslashes, as follows: | 如果使用的是 Windows 平台,请包含驱动器符号并使用Unix风格的斜杠(/)而不是反斜杠(\),就像下面这样: | 翻译 | ||
| 600#翻译 | It's simplest to use absolute paths (i.e., directory paths that start at the root of the filesystem). | 最省事的方式是使用绝对路径(即从文件系统根目录开始的目录路径)。 | 翻译 | ||
| 601#翻译 | If you want to be a bit more flexible and decoupled, though, you can take advantage of the fact that Django settings files are just Python code by constructing the contents of <literal>TEMPLATE_DIRS</literal> dynamically. | 如果想要更灵活一点并减少一些负面干扰,可利用 Django 配置文件就是 Python 代码这一点来动态构建 <literal>TEMPLATE_DIRS</literal> 的内容,如: | 翻译 | ||
| 602#翻译 | For example: | 例如: | 翻译 | ||
| 605#翻译 | This example uses the magic Python variable <literal>__file__</literal> , which is automatically set to the file name of the Python module in which the code lives. | 这个例子使用了神奇的 Python 内部变量 <literal>__file__</literal> ,该变量被自动设置为代码所在的 Python 模块文件名。 | 翻译 | ||
| 606#翻译 | It gets the name of the directory that contains <literal>settings.py</literal> (<literal>os.path.dirname</literal> ), then joins that with <literal>templates</literal> in a cross-platform way (<literal>os.path.join</literal> ), then ensures that everything uses forward slashes instead of backslashes (in case of Windows). | <literal> os.path.dirname(__file__)</literal> 将会获取自身所在的文件,即<literal>settings.py</literal> 所在的目录,然后由<literal>os.path.join</literal> 这个方法将这目录与 <literal>templates</literal> 进行连接。如果在windows下,它会智能地选择正确的后向斜杠"\"进行连接,而不是前向斜杠"/"。 | 翻译 | ||
| 608#翻译 | While we're on the topic of dynamic Python code in settings files, we should point out that it's very important to avoid Python errors in your settings file. | 在这里我们面对的是动态语言python代码,我需要提醒你的是,不要在你的设置文件里写入错误的代码,这很重要。 | 翻译 | ||
| 609#翻译 | If you introduce a syntax error, or a runtime error, your Django-powered site will likely crash. | 如果你在这里引入了语法错误,或运行错误,你的Django-powered站点将很可能就要被崩溃掉。 | 翻译 | ||
| 611#翻译 | With <literal>TEMPLATE_DIRS</literal> set, the next step is to change the view code to use Django's template-loading functionality rather than hard-coding the template paths. | 完成 <literal>TEMPLATE_DIRS</literal> 设置后,下一步就是修改视图代码,让它使用 Django 模板加载功能而不是对模板路径硬编码。 | 翻译 | ||
| 612#翻译 | Returning to our <literal>current_datetime</literal> view, let's change it like so: | 返回 <literal>current_datetime</literal> 视图,进行如下修改: | 翻译 | ||
| 615#翻译 | In this example, we're using the function <literal>django.template.loader.get_template()</literal> rather than loading the template from the filesystem manually. | 此范例中,我们使用了函数 <literal>django.template.loader.get_template()</literal> ,而不是手动从文件系统加载模板。 | 翻译 | ||
| 616#翻译 | The <literal>get_template()</literal> function takes a template name as its argument, figures out where the template lives on the filesystem, opens that file, and returns a compiled <literal>Template</literal> object. | 该 <literal>get_template()</literal> 函数以模板名称为参数,在文件系统中找出模块的位置,打开文件并返回一个编译好的 <literal>Template</literal> 对象。 | 翻译 | ||
| 618#翻译 | Our template in this example is <literal>current_datetime.html</literal> , but there's nothing special about that <literal>.html</literal> extension. | 在这个例子里,我们选择的模板文件是<literal>current_datetime.html</literal>,但这个与<literal>.html</literal>后缀没有直接的联系。 | 翻译 | ||
| 619#翻译 | You can give your templates whatever extension makes sense for your application, or you can leave off extensions entirely. | 你可以选择任意后缀的任意文件,只要是符合逻辑的都行。甚至选择没有后缀的文件也不会有问题。 | 翻译 | ||
| 621#翻译 | To determine the location of the template on your filesystem, <literal>get_template()</literal> combines your template directories from <literal>TEMPLATE_DIRS</literal> with the template name that you pass to <literal>get_template()</literal> . For example, if your <literal>TEMPLATE_DIRS</literal> is set to <literal>'/home/django/mysite/templates'</literal> , the above <literal>get_template()</literal> call would look for the template <literal>/home/django/mysite/templates/current_datetime.html</literal> . | 要确定某个模板文件在你的系统里的位置, <literal>get_template()</literal>方法会自动为你连接已经设置的 <literal>TEMPLATE_DIRS</literal>目录和你传入该法的模板名称参数。比如,你的 <literal>TEMPLATE_DIRS</literal>目录设置为 <literal>'/home/django/mysite/templates'</literal>,上面的 <literal>get_template()</literal>调用就会为你找到 <literal>/home/django/mysite/templates/current_datetime.html</literal> 这样一个位置。 | 翻译 | ||
| 623#翻译 | If <literal>get_template()</literal> cannot find the template with the given name, it raises a <literal>TemplateDoesNotExist</literal> exception. | 如果 <literal>get_template()</literal> 找不到给定名称的模板,将会引发一个 <literal>TemplateDoesNotExist</literal> 异常。 | 翻译 | ||
| 624#翻译 | To see what that looks like, fire up the Django development server again by running <literal>python manage.py runserver</literal> within your Django project's directory. | 要了解究竟会发生什么,让我们按照第三章内容,在 Django 项目目录中运行 <literal>python manage.py runserver</literal> 命令,再次启动Django开发服务器。 | 翻译 | ||
| 625#翻译 | Then, point your browser at the page that activates the <literal>current_datetime</literal> view (e.g., <literal>http://127.0.0.1:8000/time/</literal> ). Assuming your <literal>DEBUG</literal> setting is set to <literal>True</literal> and you haven't yet created a <literal>current_datetime.html</literal> template, you should see a Django error page highlighting the <literal>TemplateDoesNotExist</literal> error. | 接着,告诉你的浏览器,使其定位到指定页面以激活<literal>current_datetime</literal>视图(如 <literal>http://127.0.0.1:8000/time/</literal> )。假设你的 <literal>DEBUG</literal>项设置为 <literal>True</literal>,而你有没有建立<literal>current_datetime.html</literal> 这个模板文件,你会看到Django的错误提示网页,告诉你发生了 <literal>TemplateDoesNotExist</literal> 错误。 | 翻译 | ||
| 627#翻译 | <image alt="Screenshot of a TemplateDoesNotExist error." uri="http://new-media.djangobook.com/content/en/2.0/chapter04/missing_template.png"/><cnid>330 | <image alt="Screenshot of a TemplateDoesNotExist error." uri="http://new-media.djangobook.com/content/en/1.0/chapter04/missing_template.png"/><cnid>307 | 翻译 | ||
| 628#翻译 | Figure 4-1: | 图 4-1: | 翻译 | ||
| 629#翻译 | The error page shown when a template cannot be found. | 模板文件无法找到时,将会发送提示错误的网页给用户。 | 翻译 | ||
| 631#翻译 | This error page is similar to the one we explained in Chapter 3, with one additional piece of debugging information: | 该页面与我们在第三章解释过的错误页面相似,只不过多了一块调试信息区: | 翻译 | ||
| 632#翻译 | a Template-loader postmortem section. | 模板加载器事后检查区。 | 翻译 | ||
| 633#翻译 | This section tells you which templates Django tried to load, along with the reason each attempt failed (e.g., File does not exist). | 该区域显示 Django 要加载哪个模板、每次尝试出错的原因(如:文件不存在等)。 | 翻译 | ||
| 634#翻译 | This information is invaluable when you're trying to debug template-loading errors. | 当你尝试调试模板加载错误时,这些信息会非常有帮助。 | 翻译 | ||
| 636#翻译 | Moving along, create the <literal>current_datetime.html</literal> file within your template directory using the following template code: | 接下来,在模板目录中创建包括以下模板代码 <literal>current_datetime.html</literal> 文件: | 翻译 | ||
| 639#翻译 | Refresh the page in your Web browser, and you should see the fully rendered page. | 在网页浏览器中刷新该页,你将会看到完整解析后的页面。 | 翻译 | ||
| 641#翻译 | render_to_response() | render_to_response() | 翻译 | ||
| 643#翻译 | We've shown you how to load a template, fill a <literal>Context</literal> and return an <literal>HttpResponse</literal> object with the result of the rendered template. | 我们已经告诉你如何载入一个模板文件,然后用 <literal>Context</literal>渲染它,最后返回这个处理好的<literal>HttpResponse</literal>对象给用户。 | 翻译 | ||
| 644#翻译 | We've optimized it to use <literal>get_template()</literal> instead of hard-coding templates and template paths. | 我们已经优化了方案,使用 <literal>get_template()</literal> 方法代替繁杂的用代码来处理模板及其路径的工作。 | 翻译 | ||
| 645#翻译 | But it still requires a fair amount of typing to do those things. | 但这仍然需要一定量的时间来敲出这些简化的代码。 | 翻译 | ||
| 646#翻译 | Because this is such a common idiom, Django provides a shortcut that lets you load a template, render it and return an <literal>HttpResponse</literal> all in one line of code. | 这是一个普遍存在的重复苦力劳动。Django为此提供了一个捷径,让你一次性地载入某个模板文件,渲染它,然后将此作为 <literal>HttpResponse</literal>返回。 | 翻译 | ||
| 648#翻译 | This shortcut is a function called <literal>render_to_response()</literal> , which lives in the module <literal>django.shortcuts</literal> . Most of the time, you'll be using <literal>render_to_response()</literal> rather than loading templates and creating <literal>Context</literal> and <literal>HttpResponse</literal> objects manually unless your employer judges your work by total lines of code written, that is. | 该捷径就是位于 <literal>django.shortcuts</literal> 模块中名为 <literal>render_to_response()</literal> 的函数。大多数情况下,你会使用<literal></literal><literal></literal><literal></literal>对象,除非你的老板以代码行数来衡量你的工作。 | 翻译 | ||
| 650#翻译 | Here's the ongoing <literal>current_datetime</literal> example rewritten to use <literal>render_to_response()</literal> : | 下面就是使用 <literal>render_to_response()</literal> 重新编写过的 <literal>current_datetime</literal> 范例。 | 翻译 | ||
| 653#翻译 | What a difference! | 大变样了! | 翻译 | ||
| 654#翻译 | Let's step through the code changes: | 让我们逐句看看代码发生的变化: | 翻译 | ||
| 656#翻译 | We no longer have to import <literal>get_template</literal> , <literal>Template</literal> , <literal>Context</literal> , or <literal>HttpResponse</literal> . Instead, we import <literal>django.shortcuts.render_to_response</literal> . The <literal>import datetime</literal> remains. | 我们不再需要导入 <literal>get_template</literal> 、 <literal>Template</literal> 、 <literal>Context</literal> 和 <literal>HttpResponse</literal> 。相反,我们导入 <literal>django.shortcuts.render_to_response</literal> 。 <literal>import datetime</literal> 继续保留. | 翻译 | ||
| 658#翻译 | Within the <literal>current_datetime</literal> function, we still calculate <literal>now</literal> , but the template loading, context creation, template rendering, and <literal>HttpResponse</literal> creation are all taken care of by the <literal>render_to_response()</literal> call. | 在 <literal>current_datetime</literal> 函数中,我们仍然进行 <literal>now</literal> 计算,但模板加载、上下文创建、模板解析和 <literal>HttpResponse</literal> 创建工作均在对 <literal>render_to_response()</literal> 的调用中完成了。 | 翻译 | ||
| 659#翻译 | Because <literal>render_to_response()</literal> returns an <literal>HttpResponse</literal> object, we can simply <literal>return</literal> that value in the view. | 由于 <literal>render_to_response()</literal> 返回 <literal>HttpResponse</literal> 对象,因此我们仅需在视图中 <literal>return</literal> 该值。 | 翻译 | ||
| 661#翻译 | The first argument to <literal>render_to_response()</literal> is the name of the template to use. | <literal>render_to_response()</literal> 的第一个参数必须是要使用的模板名称。 | 翻译 | ||
| 662#翻译 | The second argument, if given, should be a dictionary to use in creating a <literal>Context</literal> for that template. | 如果要给定第二个参数,那么该参数必须是为该模板创建 <literal>Context</literal> 时所使用的字典。 | 翻译 | ||
| 663#翻译 | If you don't provide a second argument, <literal>render_to_response()</literal> will use an empty dictionary. | 如果不提供第二个参数, <literal>render_to_response()</literal> 使用一个空字典。 | 翻译 | ||
| 665#翻译 | The locals() Trick | locals() 技巧 | 翻译 | ||
| 667#翻译 | Consider our latest incarnation of <literal>current_datetime</literal> : | 思考一下我们对 <literal>current_datetime</literal> 的最后一次赋值: | 翻译 | ||
| 670#翻译 | Many times, as in this example, you'll find yourself calculating some values, storing them in variables (e.g., <literal>now</literal> in the preceding code), and sending those variables to the template. | 很多时候,就像在这个范例中那样,你发现自己一直在计算某个变量,保存结果到变量中(比如前面代码中的 now ),然后将这些变量发送给模板。 | 翻译 | ||
| 671#翻译 | Particularly lazy programmers should note that it's slightly redundant to have to give names for temporary variables <emphasis>and</emphasis> give names for the template variables. | 尤其喜欢偷懒的程序员应该注意到了,不断地为临时变量<emphasis>和</emphasis>临时模板命名有那么一点点多余。 | 翻译 | ||
| 672#翻译 | Not only is it redundant, but also it's extra typing. | 不仅多余,而且需要额外的输入。 | 翻译 | ||
| 674#翻译 | So if you're one of those lazy programmers and you like keeping code particularly concise, you can take advantage of a built-in Python function called <literal>locals()</literal> . It returns a dictionary mapping all local variable names to their values, where local means all variables that have been defined within the current scope. | 如果你是个喜欢偷懒的程序员并想让代码看起来更加简明,可以利用 Python 的内建函数 <literal>locals()</literal> 。它返回的字典对所有局部变量的名称与值进行映射。 | 翻译 | ||
| 675#翻译 | Thus, the preceding view could be rewritten like so: | 因此,前面的视图可以重写成下面这个样子: | 翻译 | ||
| 678#翻译 | Here, instead of manually specifying the context dictionary as before, we pass the value of <literal>locals()</literal> , which will include all variables defined at that point in the function's execution. | 在此,我们没有像之前那样手工指定 context 字典,而是传入了 <literal>locals()</literal> 的值,它囊括了函数执行到该时间点时所定义的一切变量。 | 翻译 | ||
| 679#翻译 | As a consequence, weve renamed the <literal>now</literal> variable to <literal>current_date</literal> , because that's the variable name that the template expects. | 因此,我们将 <literal>now</literal> 变量重命名为 <literal>current_date</literal> ,因为那才是模板所预期的变量名称。 | 翻译 | ||
| 680#翻译 | In this example, <literal>locals()</literal> doesn't offer a <emphasis>huge</emphasis> improvement, but this technique can save you some typing if you have several template variables to define or if you're lazy. | 在本例中, <literal>locals()</literal> 并没有带来多 <emphasis>大</emphasis> 的改进,但是如果有多个模板变量要界定而你又想偷懒,这种技术可以减少一些键盘输入。 | 翻译 | ||
| 682#翻译 | One thing to watch out for when using <literal>locals()</literal> is that it includes <emphasis>every</emphasis> local variable, which may comprise more variables than you actually want your template to have access to. | 使用 <literal>locals()</literal> 时要注意是它将包括 <emphasis>所有</emphasis> 的局部变量,它们可能比你想让模板访问的要多。 | 翻译 | ||
| 683#翻译 | In the previous example, <literal>locals()</literal> will also include <literal>request</literal> . Whether this matters to you depends on your application and your level of perfectionism. | 在前例中, <literal>locals()</literal> 还包含了 <literal>request</literal> 。对此如何取舍取决你的应用程序。 | 翻译 | ||
| 685#翻译 | Subdirectories in get_template() | get_template()中使用子目录 | 翻译 | ||
| 687#翻译 | It can get unwieldy to store all of your templates in a single directory. | 把所有的模板都存放在一个目录下可能会让事情变得难以掌控。 | 翻译 | ||
| 688#翻译 | You might like to store templates in subdirectories of your template directory, and that's fine. | 你可能会考虑把模板存放在你模板目录的子目录中,这非常好。 | 翻译 | ||
| 689#翻译 | In fact, we recommend doing so; some more advanced Django features (such as the generic views system, which we cover in Chapter 11) expect this template layout as a default convention. | 事实上,我们推荐这样做;一些Django的高级特性(例如将在第十一章讲到的通用视图系统)的缺省约定就是期望使用这种模板布局。 | 翻译 | ||
| 691#翻译 | Storing templates in subdirectories of your template directory is easy. | 把模板存放于模板目录的子目录中是件很轻松的事情。 | 翻译 | ||
| 692#翻译 | In your calls to <literal>get_template()</literal> , just include the subdirectory name and a slash before the template name, like so: | 只需在调用 <literal>get_template()</literal> 时,把子目录名和一条斜杠添加到模板名称之前,如: | 翻译 | ||
| 695#翻译 | Because <literal>render_to_response()</literal> is a small wrapper around <literal>get_template()</literal> , you can do the same thing with the first argument to <literal>render_to_response()</literal> , like this: | 由于 <literal>render_to_response()</literal> 只是对 <literal>get_template()</literal> 的简单封装, 你可以对 <literal>render_to_response()</literal> 的第一个参数做相同处理。 | 翻译 | ||
| 698#翻译 | There's no limit to the depth of your subdirectory tree. | 对子目录树的深度没有限制,你想要多少层都可以。 | 翻译 | ||
| 699#翻译 | Feel free to use as many subdirectories as you like. | 只要你喜欢,用多少层的子目录都无所谓。 | 翻译 | ||
| 701#翻译 | Note | 注意 | 翻译 | ||
| 703#翻译 | Windows users, be sure to use forward slashes rather than backslashes. | Windows用户必须使用斜杠而不是反斜杠。 | 翻译 | ||
| 704#翻译 | <literal>get_template()</literal> assumes a Unix-style file name designation. | <literal>get_template()</literal> 假定的是 Unix 风格的文件名符号约定。 | 翻译 | ||
| 706#翻译 | The <literal>include</literal> Template Tag | <literal>include</literal> 模板标签 | 翻译 | ||
| 708#翻译 | Now that we've covered the template-loading mechanism, we can introduce a built-in template tag that takes advantage of it: | 在讲解了模板加载机制之后,我们再介绍一个利用该机制的内建模板标签: | 翻译 | ||
| 709#翻译 | <literal>{% include %}</literal> . This tag allows you to include the contents of another template. | <literal>{% include %}</literal> 。该标签允许在(模板中)包含其它的模板的内容。 | 翻译 | ||
| 710#翻译 | The argument to the tag should be the name of the template to include, and the template name can be either a variable or a hard-coded (quoted) string, in either single or double quotes. | 标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号硬编码的字符串。 | 翻译 | ||
| 711#翻译 | Anytime you have the same code in multiple templates, consider using an <literal>{% include %}</literal> to remove the duplication. | 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 <literal>{% include %}</literal> 来减少重复。 | 翻译 | ||
| 713#翻译 | These two examples include the contents of the template <literal>nav.html</literal> . The examples are equivalent and illustrate that either single or double quotes are allowed: | 下面这两个例子都包含了 <literal>nav.html</literal> 模板。这两个例子是等价的,它们证明单/双引号都是允许的。 | 翻译 | ||
| 716#翻译 | This example includes the contents of the template <literal>includes/nav.html</literal> : | 下面的例子包含了 <literal>includes/nav.html</literal> 模板的内容: | 翻译 | ||
| 719#翻译 | This example includes the contents of the template whose name is contained in the variable <literal>template_name</literal> : | 下面的例子包含了以变量 <literal>template_name</literal> 的值为名称的模板内容: | 翻译 | ||
| 722#翻译 | As in <literal>get_template()</literal> , the file name of the template is determined by adding the template directory from <literal>TEMPLATE_DIRS</literal> to the requested template name. | 和在 <literal>get_template()</literal> 中一样, 对模板的文件名进行判断时会在所调取的模板名称之前加上来自 <literal>TEMPLATE_DIRS</literal> 的模板目录。 | 翻译 | ||
| 724#翻译 | Included templates are evaluated with the context of the template that's including them. | 所包含的模板执行时的 context 和包含它们的模板是一样的。 | 翻译 | ||
| 725#翻译 | For example, consider these two templates: | 举例说,考虑下面两个模板文件: | 翻译 | ||
| 728#翻译 | If you render <literal>mypage.html</literal> with a context containing <literal>current_section</literal> , then the variable will be available in the included template, as you would expect. | 如果你用一个包含 <literal>current_section</literal>的上下文去渲染 <literal>mypage.html</literal>这个模板文件,这个变量将存在于它所包含(include)的模板里,就像你想象的那样。 | 翻译 | ||
| 730#翻译 | If, in an <literal>{% include %}</literal> tag, a template with the given name isn't found, Django will do one of two things: | 如果<literal>{% include %}</literal>标签指定的模板没找到,Django将会在下面两个处理方法中选择一个: | 翻译 | ||
| 732#翻译 | If <literal>DEBUG</literal> is set to <literal>True</literal> , you'll see the <literal>TemplateDoesNotExist</literal> exception on a Django error page. | 如果 <literal>DEBUG</literal> 设置为 <literal>True</literal> ,你将会在 Django 错误信息页面看到 <literal>TemplateDoesNotExist</literal> 异常。 | 翻译 | ||
| 734#翻译 | If <literal>DEBUG</literal> is set to <literal>False</literal> , the tag will fail silently, displaying nothing in the place of the tag. | 如果 <literal>DEBUG</literal> 设置为 <literal>False</literal> ,该标签不会引发错误信息,在标签位置不显示任何东西。 | 翻译 | ||
| 736#翻译 | Template Inheritance | 模板继承 | 翻译 | ||
| 738#翻译 | Our template examples so far have been tiny HTML snippets, but in the real world, you'll be using Django's template system to create entire HTML pages. | 到目前为止,我们的模板范例都只是些零星的 HTML 片段,但在实际应用中,你将用 Django 模板系统来创建整个 HTML 页面。 | 翻译 | ||
| 739#翻译 | This leads to a common Web development problem: | 这就带来一个常见的 Web 开发问题: | 翻译 | ||
| 740#翻译 | across a Web site, how does one reduce the duplication and redundancy of common page areas, such as sitewide navigation? | 在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码? | 翻译 | ||
| 742#翻译 | A classic way of solving this problem is to use <emphasis>server-side includes</emphasis> , directives you can embed within your HTML pages to include one Web page inside another. | 解决该问题的传统做法是使用 <emphasis>服务器端的 includes</emphasis> ,你可以在 HTML 页面中使用该指令将一个网页嵌入到另一个中。 | 翻译 | ||
| 743#翻译 | Indeed, Django supports that approach, with the <literal>{% include %}</literal> template tag just described. | 事实上, Django 通过刚才讲述的 <literal>{% include %}</literal> 支持了这种方法。 | 翻译 | ||
| 744#翻译 | But the preferred way of solving this problem with Django is to use a more elegant strategy called <emphasis>template inheritance</emphasis> . | 但是用 Django 解决此类问题的首选方法是使用更加优雅的策略—— <emphasis>模板继承</emphasis> 。 | 翻译 | ||
| 746#翻译 | In essence, template inheritance lets you build a base skeleton template that contains all the common parts of your site and defines blocks that child templates can override. | 本质上来说,模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。 | 翻译 | ||
| 748#翻译 | Let's see an example of this by creating a more complete template for our <literal>current_datetime</literal> view, by editing the <literal>current_datetime.html</literal> file: | 让我们通过修改 <literal>current_datetime.html</literal> 文件,为 <literal>current_datetime</literal> 创建一个更加完整的模板来体会一下这种做法: | 翻译 | ||
| 751#翻译 | That looks just fine, but what happens when we want to create a template for another view say, the <literal>hours_ahead</literal> view from Chapter 3? If we want again to make a nice, valid, full HTML template, we'd create something like: | 这看起来很棒,但如果我们要为第三章的 <literal>hours_ahead</literal> 视图创建另一个模板会发生什么事情呢? | 翻译 | ||
| 754#翻译 | Clearly, we've just duplicated a lot of HTML. | 很明显,我们刚才重复了大量的 HTML 代码。 | 翻译 | ||
| 755#翻译 | Imagine if we had a more typical site, including a navigation bar, a few style sheets, perhaps some JavaScript we'd end up putting all sorts of redundant HTML into each template. | 想象一下,如果有一个更典型的网站,它有导航条、样式表,可能还有一些 JavaScript 代码,事情必将以向每个模板填充各种冗余的 HTML 而告终。 | 翻译 | ||
| 757#翻译 | The server-side include solution to this problem is to factor out the common bits in both templates and save them in separate template snippets, which are then included in each template. | 解决这个问题的服务器端 include 方案是找出两个模板中的共同部分,将其保存为不同的模板片段,然后在每个模板中进行 include。 | 翻译 | ||
| 758#翻译 | Perhaps you'd store the top bit of the template in a file called <literal>header.html</literal> : | 也许你会把模板头部的一些代码保存为 <literal>header.html</literal> 文件: | 翻译 | ||
| 761#翻译 | And perhaps you'd store the bottom bit in a file called <literal>footer.html</literal> : | 你可能会把底部保存到文件 <literal>footer.html</literal> : | 翻译 | ||
| 764#翻译 | With an include-based strategy, headers and footers are easy. | 对基于 include 的策略,头部和底部的包含很简单。 | 翻译 | ||
| 765#翻译 | It's the middle ground thats messy. | 麻烦的是中间部分。 | 翻译 | ||
| 766#翻译 | In this example, both pages feature a title <literal><h1>My helpful timestamp site</h1></literal> but that title can't fit into <literal>header.html</literal> because the <literal><title></literal> on both pages is different. | 在此范例中,每个页面都有一个 <literal><h1>My helpful timestamp site</h1></literal> 标题,但是这个标题不能放在 <literal>header.html</literal> 中,因为每个页面的 <literal><title></literal> 是不同的。 | 翻译 | ||
| 767#翻译 | If we included the <literal><h1></literal> in the header, we'd have to include the <literal><title></literal> , which wouldn't allow us to customize it per page. | 如果我们将 <literal><h1></literal> 包含在头部,我们就不得不包含 <literal><title></literal> ,但这样又不允许在每个页面对它进行定制。 | 翻译 | ||
| 768#翻译 | See where this is going? | 何去何从呢? | 翻译 | ||
| 770#翻译 | Django's template inheritance system solves these problems. | Django 的模板继承系统解决了这些问题。 | 翻译 | ||
| 771#翻译 | You can think of it as an inside-out version of server-side includes. | 你可以将其视为服务器端 include 的逆向思维版本。 | 翻译 | ||
| 772#翻译 | Instead of defining the snippets that are <emphasis>common</emphasis> , you define the snippets that are <emphasis>different</emphasis> . | 你可以对那些 <emphasis>不同</emphasis> 的代码段进行定义,而不是 <emphasis>共同</emphasis> 代码段。 | 翻译 | ||
| 774#翻译 | The first step is to define a <emphasis>base template</emphasis> a skeleton of your page that <emphasis>child templates</emphasis> will later fill in. | 第一步是定义 <emphasis>基础模板</emphasis> , 该框架之后将由 <emphasis>子模板</emphasis> 所继承。 | 翻译 | ||
| 775#翻译 | Here's a base template for our ongoing example: | 以下是我们目前所讲述范例的基础模板: | 翻译 | ||
| 778#翻译 | This template, which we'll call <literal>base.html</literal> , defines a simple HTML skeleton document that we'll use for all the pages on the site. | 这个叫做 <literal>base.html</literal> 的模板定义了一个简单的 HTML 框架文档,我们将在本站点的所有页面中使用。 | 翻译 | ||
| 779#翻译 | It's the job of child templates to override, or add to, or leave alone the contents of the blocks. | 子模板的作用就是重载、添加或保留那些块的内容。 | 翻译 | ||
| 780#翻译 | (If you're following along, save this file to your template directory as <literal>base.html</literal> .) | (如果你一直按顺序学习到这里,保存这个文件到你的template目录下,命名为 <literal>base.html</literal> .) | 翻译 | ||
| 782#翻译 | We're using a template tag here that you haven't seen before: | 我们使用一个以前已经见过的模板标签: | 翻译 | ||
| 783#翻译 | the <literal>{% block %}</literal> tag. | <literal>{% block %}</literal> 。 所有的 <literal>{% block %}</literal> 标签告诉模板引擎,子模板可以重载这些部分。 | 翻译 | ||
| 784#翻译 | All the <literal>{% block %}</literal> tags do is tell the template engine that a child template may override those portions of the template. | 每个<literal>{% block %}</literal>标签所要做的是告诉模板引擎,该模板下的这一块内容将有可能被子模板覆盖。 | 翻译 | ||
| 786#翻译 | Now that we have this base template, we can modify our existing <literal>current_datetime.html</literal> template to use it: | 现在我们已经有了一个基本模板,我们可以修改 <literal>current_datetime.html</literal> 模板来 使用它: | 翻译 | ||
| 789#翻译 | While we're at it, lets create a template for the <literal>hours_ahead</literal> view from Chapter 3. (If you're following along with code, we'll leave it up to you to change <literal>hours_ahead</literal> to use the template system instead of hard-coded HTML.) Here's what that could look like: | 再为 <literal>hours_ahead</literal> 视图创建一个模板,看起来是这样的: | 翻译 | ||
| 792#翻译 | Isn't this beautiful? | 看起来很漂亮是不是? | 翻译 | ||
| 793#翻译 | Each template contains only the code that's <emphasis>unique</emphasis> to that template. | 每个模板只包含对自己而言 <emphasis>独一无二</emphasis> 的代码。 | 翻译 | ||
| 794#翻译 | No redundancy needed. | 无需多余的部分。 | 翻译 | ||
| 795#翻译 | If you need to make a site-wide design change, just make the change to <literal>base.html</literal> , and all of the other templates will immediately reflect the change. | 如果想进行站点级的设计修改,仅需修改 <literal>base.html</literal> ,所有其它模板会立即反映出所作修改。 | 翻译 | ||
| 797#翻译 | Here's how it works. | 以下是其工作方式。 | 翻译 | ||
| 798#翻译 | When you load the template <literal>current_datetime.html</literal> , the template engine sees the <literal>{% extends %}</literal> tag, noting that this template is a child template. | 在加载 <literal>current_datetime.html</literal> 模板时,模板引擎发现了 <literal>{% extends %}</literal> 标签, 注意到该模板是一个子模板。 | 翻译 | ||
| 799#翻译 | The engine immediately loads the parent template in this case, <literal>base.html</literal> . | 模板引擎立即装载其父模板,即本例中的 <literal>base.html</literal> 。 | 翻译 | ||
| 801#翻译 | At that point, the template engine notices the three <literal>{% block %}</literal> tags in <literal>base.html</literal> and replaces those blocks with the contents of the child template. | 此时,模板引擎注意到 <literal>base.html</literal> 中的三个 <literal>{% block %}</literal> 标签,并用子模板的内容替换这些 block 。因此,引擎将会使用我们在 <literal>{ block title %}</literal> 中定义的标题,对 <literal>{% block content %}</literal> 也是如此。 | 翻译 | ||
| 802#翻译 | So, the title we've defined in <literal>{% block title %}</literal> will be used, as will the <literal>{% block content %}</literal> . | 所以,网页标题一块将由 <literal>{% block title %}</literal>替换,同样地,网页的内容一块将由 <literal>{% block content %}</literal>替换。 | 翻译 | ||
| 804#翻译 | Note that since the child template doesn't define the <literal>footer</literal> block, the template system uses the value from the parent template instead. | 注意由于子模板并没有定义 <literal>footer</literal> 块,模板系统将使用在父模板中定义的值。 | 翻译 | ||
| 805#翻译 | Content within a <literal>{% block %}</literal> tag in a parent template is always used as a fallback. | 父模板 <literal>{% block %}</literal> 标签中的内容总是被当作一条退路。 | 翻译 | ||
| 807#翻译 | Inheritance doesn't affect the template context. | 继承并不会影响到模板的上下文。 | 翻译 | ||
| 808#翻译 | In other words, any template in the inheritance tree will have access to every one of your template variables from the context. | 换句话说,任何处在继承树上的模板都可以访问到你传到模板中的每一个模板变量。 | 翻译 | ||
| 810#翻译 | You can use as many levels of inheritance as needed. | 你可以根据需要使用任意多的继承次数。 | 翻译 | ||
| 811#翻译 | One common way of using inheritance is the following three-level approach: | 使用继承的一种常见方式是下面的三层法: | 翻译 | ||
| 813#翻译 | Create a <literal>base.html</literal> template that holds the main look and feel of your site. | 创建 <literal>base.html</literal> 模板,在其中定义站点的主要外观感受。 | 翻译 | ||
| 814#翻译 | This is the stuff that rarely, if ever, changes. | 这些都是不常修改甚至从不修改的部分。 | 翻译 | ||
| 816#翻译 | Create a <literal>base_SECTION.html</literal> template for each section of your site (e.g., <literal>base_photos.html</literal> and <literal>base_forum.html</literal> ). These templates extend <literal>base.html</literal> and include section-specific styles/design. | 为网站的每个区域创建 <literal>base_SECTION.html</literal> 模板(例如, <literal>base_photos.html</literal> 和 <literal>base_forum.html</literal> )。这些模板对 <literal>base.html</literal> 进行拓展,并包含区域特定的风格与设计。 | 翻译 | ||
| 818#翻译 | Create individual templates for each type of page, such as a forum page or a photo gallery. | 为每种类型的页面创建独立的模板,例如论坛页面或者图片库。 | 翻译 | ||
| 819#翻译 | These templates extend the appropriate section template. | 这些模板拓展相应的区域模板。 | 翻译 | ||
| 821#翻译 | This approach maximizes code reuse and makes it easy to add items to shared areas, such as section-wide navigation. | 这个方法可最大限度地重用代码,并使得向公共区域(如区域级的导航)添加内容成为一件轻松的工作。 | 翻译 | ||
| 823#翻译 | Here are some guidelines for working with template inheritance: | 以下是使用模板继承的一些诀窍: | 翻译 | ||
| 825#翻译 | If you use <literal>{% extends %}</literal> in a template, it must be the first template tag in that template. | 如果在模板中使用 <literal>{% extends %}</literal> ,必须保证其为模板中的第一个模板标记。 | 翻译 | ||
| 826#翻译 | Otherwise, template inheritance won't work. | 否则,模板继承将不起作用。 | 翻译 | ||
| 828#翻译 | Generally, the more <literal>{% block %}</literal> tags in your base templates, the better. | 一般来说,基础模板中的 <literal>{% block %}</literal> 标签越多越好。 | 翻译 | ||
| 829#翻译 | Remember, child templates don't have to define all parent blocks, so you can fill in reasonable defaults in a number of blocks, and then define only the ones you need in the child templates. | 记住,子模板不必定义父模板中所有的代码块,因此你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 | 翻译 | ||
| 830#翻译 | It's better to have more hooks than fewer hooks. | 俗话说,钩子越多越好。 | 翻译 | ||
| 832#翻译 | If you find yourself duplicating code in a number of templates, it probably means you should move that code to a <literal>{% block %}</literal> in a parent template. | 如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 <literal>{% block %}</literal> 中。 | 翻译 | ||
| 834#翻译 | If you need to get the content of the block from the parent template, use <literal>{{ block.super }}</literal> , which is a magic variable providing the rendered text of the parent template. | 如果你需要访问父模板中的块的内容,使用 <literal>{{ block.super }}</literal>这个标签吧,这一个魔法变量将会表现出父模板中的内容。 | 翻译 | ||
| 835#翻译 | This is useful if you want to add to the contents of a parent block instead of completely overriding it. | 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。 | 翻译 | ||
| 837#翻译 | You may not define multiple <literal>{% block %}</literal> tags with the same name in the same template. | 不允许在同一个模板中定义多个同名的 <literal>{% block %}</literal> 。 | 翻译 | ||
| 838#翻译 | This limitation exists because a block tag works in both directions. | 存在这样的限制是因为block 标签的工作方式是双向的。 | 翻译 | ||
| 839#翻译 | That is, a block tag doesn't just provide a hole to fill, it also defines the content that fills the hole in the <emphasis>parent</emphasis> . If there were two similarly named <literal>{% block %}</literal> tags in a template, that template's parent wouldn't know which one of the blocks content to use. | 也就是说,block 标签不仅挖了一个要填的坑,也定义了在<emphasis>父</emphasis>模板中这个坑所填充的内容。如果模板中出现了两个相同名称的 <emphasis>{% block %}</emphasis> 标签,父模板将无从得知要使用哪个块的内容。 | 翻译 | ||
| 841#翻译 | The template name you pass to <literal>{% extends %}</literal> is loaded using the same method that <literal>get_template()</literal> uses. | <literal>{% extends %}</literal> 对所传入模板名称使用的加载方法和 <literal>get_template()</literal> 相同。 | 翻译 | ||
| 842#翻译 | That is, the template name is appended to your <literal>TEMPLATE_DIRS</literal> setting. | 也就是说,会将模板名称被添加到 <literal>TEMPLATE_DIRS</literal> 设置之后。 | 翻译 | ||
| 844#翻译 | In most cases, the argument to <literal>{% extends %}</literal> will be a string, but it can also be a variable, if you don't know the name of the parent template until runtime. | 多数情况下, <literal>{% extends %}</literal> 的参数应该是字符串,但是如果直到运行时方能确定父模板名,这个参数也可以是个变量。 | 翻译 | ||
| 845#翻译 | This lets you do some cool, dynamic stuff. | 这使得你能够实现一些很酷的动态功能。 | 翻译 | ||
| 847#翻译 | What's next? | 下一章 | 翻译 | ||
| 849#翻译 | You now have the basics of Django's template system under your belt. | 你现在已经掌握了模板系统的基本知识。 | 翻译 | ||
| 850#翻译 | What's next? | 接下来呢? | 翻译 | ||
| 852#翻译 | Many modern Web sites are <emphasis>database-driven</emphasis> : the content of the Web site is stored in a relational database. | 时下大多数网站都是 <emphasis>数据库驱动</emphasis> 的:网站的内容都是存储在关系型数据库中。 | 翻译 | ||
| 853#翻译 | This allows a clean separation of data and logic (in the same way views and templates allow the separation of logic and display.) | 这使得数据和逻辑能够彻底地分开(视图和模板也以同样方式对逻辑和显示进行了分隔。) | 翻译 | ||
| 855#翻译 | The <reference name="next chapter" refuri="../chapter05/">next chapter</reference> covers the tools Django gives you to interact with a database. | 下一章将讲述如何与数据库打交道。 | 翻译 |