# SOME DESCRIPTIVE TITLE. # Copyright (C) 2009-2017, Marcel Hellkamp # This file is distributed under the same license as the Bottle package. # # Translators: msgid "" msgstr "" "Project-Id-Version: bottle\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-12-19 14:15+0100\n" "PO-Revision-Date: 2015-12-13 21:06+0000\n" "Last-Translator: defnull \n" "Language-Team: Chinese (China) (http://www.transifex.com/bottle/bottle/language/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" #: ../../tutorial.rst:24 msgid "Tutorial" msgstr "教程" #: ../../tutorial.rst:26 msgid "" "This tutorial introduces you to the concepts and features of the Bottle web " "framework and covers basic and advanced topics alike. You can read it from " "start to end, or use it as a reference later on. The automatically generated" " :doc:`api` may be interesting for you, too. It covers more details, but " "explains less than this tutorial. Solutions for the most common questions " "can be found in our :doc:`recipes` collection or on the :doc:`faq` page. If " "you need any help, join our `mailing list " "`_ or visit us in our `IRC channel " "`_." msgstr "这份教程将向你介绍Bottle的开发理念和功能特性。既介绍Bottle的基本用法,也包含了进阶用法。你可以从头到尾通读一遍,也可当做开发时的参考。你也许对自动生成的 :doc:`api` 感兴趣。它包含了更多的细节,但解释没有这份教程详细。在 :doc:`recipes` 或 :doc:`faq` 可找到常见问题的解决办法。如果需要任何帮助,可加入我们的 `邮件列表 `_ 或在 `IRC频道 `_ 和我们交流。" #: ../../tutorial.rst:31 msgid "Installation" msgstr "安装" #: ../../tutorial.rst:33 msgid "" "Bottle does not depend on any external libraries. You can just download " "`bottle.py `_ into your project directory and start coding:" msgstr "Bottle不依赖其他库,你需要做的仅是下载 `bottle.py `_ (开发版)到你的项目文件夹,然后开始写代码。" #: ../../tutorial.rst:39 msgid "" "This will get you the latest development snapshot that includes all the new " "features. If you prefer a more stable environment, you should stick with the" " stable releases. These are available on `PyPI " "`_ and can be installed via " ":command:`pip` (recommended), :command:`easy_install` or your package " "manager:" msgstr "在终端运行以上命令,即可下载到Bottle的最新开发版,包含了所有新功能特性。如果更需要稳定性,你应该坚持使用Bottle的稳定版本。可在 `PyPI `_ 下载稳定版本,然后通过 :command:`pip` (推荐), :command:`easy_install` 或你的包管理软件安装。" #: ../../tutorial.rst:47 msgid "" "Either way, you'll need Python 2.7 or newer (including 3.4+) to run bottle " "applications. If you do not have permissions to install packages system-wide" " or simply don't want to, create a `virtualenv " "`_ first:" msgstr "" #: ../../tutorial.rst:55 msgid "Or, if virtualenv is not installed on your system:" msgstr "如果还未安装virtualenv:" #: ../../tutorial.rst:67 msgid "Quickstart: \"Hello World\"" msgstr "" #: ../../tutorial.rst:69 msgid "" "This tutorial assumes you have Bottle either :ref:`installed `" " or copied into your project directory. Let's start with a very basic " "\"Hello World\" example::" msgstr "到目前为止,我假设你已经 :ref:`安装 ` 好了bottle或已将bottle.py拷贝到你的项目文件夹。接下来我们就可以写一个非常简单的\"Hello World\"了::" #: ../../tutorial.rst:79 msgid "" "This is it. Run this script, visit http://localhost:8080/hello and you will " "see \"Hello World!\" in your browser. Here is how it works:" msgstr "就这么简单!保存为py文件并执行,用浏览器访问 http://localhost:8080/hello 就可以看到\"Hello World!\"。它的执行流程大致如下:" #: ../../tutorial.rst:81 msgid "" "The :func:`route` decorator binds a piece of code to an URL path. In this " "case, we link the ``/hello`` path to the ``hello()`` function. This is " "called a `route` (hence the decorator name) and is the most important " "concept of this framework. You can define as many routes as you want. " "Whenever a browser requests a URL, the associated function is called and the" " return value is sent back to the browser. It's as simple as that." msgstr "" #: ../../tutorial.rst:83 msgid "" "The :func:`run` call in the last line starts a built-in development server. " "It runs on ``localhost`` port ``8080`` and serves requests until you hit " ":kbd:`Control-c`. You can switch the server backend later, but for now a " "development server is all we need. It requires no setup at all and is an " "incredibly painless way to get your application up and running for local " "tests." msgstr "最后一行调用的 :func:`run` 函数启动了内置的开发服务器。它监听 `localhost` 的8080端口并响应请求, :kbd:`Control-c` 可将其关闭。到目前为止,这个内置的开发服务器已经足够用于日常的开发测试了。它根本不需要安装,就可以让你的应用跑起来。在教程的后面,你将学会如何让你的应用跑在其他服务器上面(译者注:内置服务器不能满足生产环境的要求)" #: ../../tutorial.rst:85 msgid "" "The :ref:`tutorial-debugging` is very helpful during early development, but " "should be switched off for public applications. Keep that in mind." msgstr ":ref:`tutorial-debugging` 在早期开发的时候非常有用,但请务必记得,在生产环境中将其关闭。" #: ../../tutorial.rst:87 msgid "" "This is just a demonstration of the basic concept of how applications are " "built with Bottle. Continue reading and you'll see what else is possible." msgstr "" #: ../../tutorial.rst:92 msgid "The Default Application" msgstr "`默认应用`" #: ../../tutorial.rst:94 msgid "" "For the sake of simplicity, most examples in this tutorial use a module-" "level :func:`route` decorator to define routes. This adds routes to a global" " \"default application\", an instance of :class:`Bottle` that is " "automatically created the first time you call :func:`route`. Several other " "module-level decorators and functions relate to this default application, " "but if you prefer a more object oriented approach and don't mind the extra " "typing, you can create a separate application object and use that instead of" " the global one::" msgstr "基于简单性考虑,这份教程中的大部分例子都使用一个模块层面的 :func:`route` 修饰器函数来定义route。这样的话,所有route都添加到了一个全局的“默认应用”里面,即是在第一次调用 :func:`route` 函数时,创建的一个 :class:`Bottle` 类的实例。其他几个模块层面的修饰器函数都与这个“默认应用”有关,如果你偏向于面向对象的做法且不介意多打点字,你可以创建一个独立的应用对象,这样就可避免使用全局范围的“默认应用”。" #: ../../tutorial.rst:106 msgid "" "The object-oriented approach is further described in the :ref:`default-app` " "section. Just keep in mind that you have a choice." msgstr "接下来的 :ref:`default-app` 章节中将更详细地介绍这种做法。现在,你只需知道不止有一种选择就好了。" #: ../../tutorial.rst:114 msgid "Request Routing" msgstr "URL映射" #: ../../tutorial.rst:116 msgid "" "In the last chapter we built a very simple web application with only a " "single route. Here is the routing part of the \"Hello World\" example " "again::" msgstr "在上一章中,我们实现了一个十分简单的web应用,只有一个URL映射(route)。让我们再来看一下“Hello World”中与routing有关的部分::" #: ../../tutorial.rst:122 msgid "" "The :func:`route` decorator links an URL path to a callback function, and " "adds a new route to the :ref:`default application `. An " "application with just one route is kind of boring, though. Let's add some " "more (don't forget ``from bottle import template``)::" msgstr "" #: ../../tutorial.rst:129 msgid "" "This example demonstrates two things: You can bind more than one route to a " "single callback, and you can add wildcards to URLs and access them via " "keyword arguments." msgstr "这个例子说明了两件事情,一个回调函数可绑定多个route,你也可以在URL中添加通配符,然后在回调函数中使用它们。" #: ../../tutorial.rst:136 msgid "Dynamic Routes" msgstr "动态URL映射" #: ../../tutorial.rst:138 msgid "" "Routes that contain wildcards are called `dynamic routes` (as opposed to " "`static routes`) and match more than one URL at the same time. A simple " "wildcard consists of a name enclosed in angle brackets (e.g. ````) and" " accepts one or more characters up to the next slash (``/``). For example, " "the route ``/hello/`` accepts requests for ``/hello/alice`` as well as" " ``/hello/bob``, but not for ``/hello``, ``/hello/`` or ``/hello/mr/smith``." msgstr "包含通配符的route,我们称之为动态route(与之对应的是静态route),它能匹配多个URL地址。一个通配符包含在一对尖括号里面(像这样 ```` ),通配符之间用\"/\"分隔开来。如果我们将URL定义为 ``/hello/`` 这样,那么它就能匹配 ``/hello/alice`` 和 ``/hello/bob`` 这样的浏览器请求,但不能匹配 ``/hello`` , ``/hello/`` 和 ``/hello/mr/smith`` 。" #: ../../tutorial.rst:140 msgid "" "Each wildcard passes the covered part of the URL as a keyword argument to " "the request callback. You can use them right away and implement RESTful, " "nice-looking and meaningful URLs with ease. Here are some other examples " "along with the URLs they'd match::" msgstr "URL中的通配符都会当作参数传给回调函数,直接在回调函数中使用。这样可以漂亮地实现RESTful形式的URL。例子如下::" #: ../../tutorial.rst:150 msgid "" "Filters can be used to define more specific wildcards, and/or transform the " "covered part of the URL before it is passed to the callback. A filtered " "wildcard is declared as ```` or ````. The " "syntax for the optional config part depends on the filter used." msgstr "" #: ../../tutorial.rst:152 msgid "" "The following filters are implemented by default and more may be added:" msgstr "已实现下面几种形式的过滤器,后续可能会继续添加:" #: ../../tutorial.rst:154 msgid "" "**:int** matches (signed) digits only and converts the value to integer." msgstr "**:int** 匹配一个数字,自动将其转换为int类型。" #: ../../tutorial.rst:155 msgid "**:float** similar to :int but for decimal numbers." msgstr "**:float** 与:int类似,用于浮点数。" #: ../../tutorial.rst:156 msgid "" "**:path** matches all characters including the slash character in a non-" "greedy way and can be used to match more than one path segment." msgstr "**:path** 匹配一个路径(包含\"/\")" #: ../../tutorial.rst:157 msgid "" "**:re** allows you to specify a custom regular expression in the config " "field. The matched value is not modified." msgstr "**:re** 匹配config部分的一个正则表达式,不更改被匹配到的值" #: ../../tutorial.rst:159 msgid "Let's have a look at some practical examples::" msgstr "让我们来看看具体的使用例子::" #: ../../tutorial.rst:173 msgid "You can add your own filters as well. See :doc:`routing` for details." msgstr "" #: ../../tutorial.rst:177 msgid "HTTP Request Methods" msgstr "HTTP请求方法" #: ../../tutorial.rst:181 msgid "" "The HTTP protocol defines several `request methods`__ (sometimes referred to" " as \"verbs\") for different tasks. GET is the default for all routes with " "no other method specified. These routes will match GET requests only. To " "handle other methods such as POST, PUT, DELETE or PATCH, add a ``method`` " "keyword argument to the :func:`route` decorator or use one of the five " "alternative decorators: :func:`get`, :func:`post`, :func:`put`, " ":func:`delete` or :func:`patch`." msgstr "" #: ../../tutorial.rst:183 msgid "" "The POST method is commonly used for HTML form submission. This example " "shows how to handle a login form using POST::" msgstr "POST方法一般用于HTML表单的提交。下面是一个使用POST来实现用户登录的例子::" #: ../../tutorial.rst:206 msgid "" "In this example the ``/login`` URL is linked to two distinct callbacks, one " "for GET requests and another for POST requests. The first one displays a " "HTML form to the user. The second callback is invoked on a form submission " "and checks the login credentials the user entered into the form. The use of " ":attr:`Request.forms` is further described in the :ref:`tutorial-request` " "section." msgstr "在这个例子中, ``/login`` 绑定了两个回调函数,一个回调函数响应GET请求,一个回调函数响应POST请求。如果浏览器使用GET请求访问 ``/login`` ,则调用login_form()函数来返回登录页面,浏览器使用POST方法提交表单后,调用login_submit()函数来检查用户有效性,并返回登录结果。接下来的 :ref:`tutorial-request` 章节中,会详细介绍 :attr:`Request.forms` 的用法。" #: ../../tutorial.rst:209 msgid "Special Methods: HEAD and ANY" msgstr "特殊请求方法: HEAD 和 ANY" #: ../../tutorial.rst:210 msgid "" "The HEAD method is used to ask for the response identical to the one that " "would correspond to a GET request, but without the response body. This is " "useful for retrieving meta-information about a resource without having to " "download the entire document. Bottle handles these requests automatically by" " falling back to the corresponding GET route and cutting off the request " "body, if present. You don't have to specify any HEAD routes yourself." msgstr "HEAD方法类似于GET方法,但服务器不会返回HTTP响应正文,一般用于获取HTTP原数据而不用下载整个页面。Bottle像处理GET请求那样处理HEAD请求,但是会自动去掉HTTP响应正文。你无需亲自处理HEAD请求。" #: ../../tutorial.rst:212 msgid "" "Additionally, the non-standard ANY method works as a low priority fallback: " "Routes that listen to ANY will match requests regardless of their HTTP " "method but only if no other more specific route is defined. This is helpful " "for *proxy-routes* that redirect requests to more specific sub-applications." msgstr "另外,非标准的ANY方法做为一个低优先级的fallback:在没有其它route的时候,监听ANY方法的route会匹配所有请求,而不管请求的方法是什么。这对于用做代理的route很有用,可将所有请求都重定向给子应用。" #: ../../tutorial.rst:214 msgid "" "To sum it up: HEAD requests fall back to GET routes and all requests fall " "back to ANY routes, but only if there is no matching route for the original " "request method. It's as simple as that." msgstr "总而言之:HEAD请求被响应GET请求的route来处理,响应ANY请求的route处理所有请求,但仅限于没有其它route来匹配原先的请求的情况。就这么简单。" #: ../../tutorial.rst:219 msgid "Routing Static Files" msgstr "静态文件映射" #: ../../tutorial.rst:221 msgid "" "Static files such as images or CSS files are not served automatically. You " "have to add a route and a callback to control which files get served and " "where to find them::" msgstr "Bottle不会处理像图片或CSS文件的静态文件请求。你需要给静态文件提供一个route,一个回调函数(用于查找和控制静态文件的访问)。" #: ../../tutorial.rst:228 msgid "" "The :func:`static_file` function is a helper to serve files in a safe and " "convenient way (see :ref:`tutorial-static-files`). This example is limited " "to files directly within the ``/path/to/your/static/files`` directory " "because the ```` wildcard won't match a path with a slash in it. " "To serve files in subdirectories, change the wildcard to use the `path` " "filter::" msgstr ":func:`static_file` 函数用于响应静态文件的请求。 (详见 :ref:`tutorial-static-files` )这个例子只能响应在 ``/path/to/your/static/files`` 目录下的文件请求,因为 ```` 这样的通配符定义不能匹配一个路径(路径中包含\"/\")。 为了响应子目录下的文件请求,我们需要更改 `path` 过滤器的定义::" #: ../../tutorial.rst:234 msgid "" "Be careful when specifying a relative root-path such as " "``root='./static/files'``. The working directory (``./``) and the project " "directory are not always the same." msgstr "使用 ``root='./static/files'`` 这样的相对路径的时候,请注意当前工作目录 (``./``) 不一定是项目文件夹。" #: ../../tutorial.rst:242 msgid "Error Pages" msgstr "错误页面" #: ../../tutorial.rst:244 msgid "" "If anything goes wrong, Bottle displays an informative but fairly plain " "error page. You can override the default for a specific HTTP status code " "with the :func:`error` decorator::" msgstr "如果出错了,Bottle会显示一个默认的错误页面,提供足够的debug信息。你也可以使用 :func:`error` 函数来自定义你的错误页面::" #: ../../tutorial.rst:251 msgid "" "From now on, `404 File not Found` errors will display a custom error page to" " the user. The only parameter passed to the error-handler is an instance of " ":exc:`HTTPError`. Apart from that, an error-handler is quite similar to a " "regular request callback. You can read from :data:`request`, write to " ":data:`response` and return any supported data-type except for " ":exc:`HTTPError` instances." msgstr "从现在开始,在遇到404错误的时候,将会返回你在上面自定义的页面。传给error404函数的唯一参数,是一个 :exc:`HTTPError` 对象的实例。除此之外,这个回调函数与我们用来响应普通请求的回调函数没有任何不同。你可以从 :data:`request` 中读取数据, 往 :data:`response` 中写入数据和返回所有支持的数据类型,除了 :exc:`HTTPError` 的实例。" #: ../../tutorial.rst:253 msgid "" "Error handlers are used only if your application returns or raises an " ":exc:`HTTPError` exception (:func:`abort` does just that). Changing " ":attr:`Request.status` or returning :exc:`HTTPResponse` won't trigger the " "error handler." msgstr "只有在你的应用返回或raise一个 :exc:`HTTPError` 异常的时候(就像 :func:`abort` 函数那样),处理Error的函数才会被调用。更改 :attr:`Request.status` 或返回 :exc:`HTTPResponse` 不会触发错误处理函数。" #: ../../tutorial.rst:263 msgid "Generating content" msgstr "生成内容" #: ../../tutorial.rst:265 msgid "" "In pure WSGI, the range of types you may return from your application is " "very limited. Applications must return an iterable yielding byte strings. " "You may return a string (because strings are iterable) but this causes most " "servers to transmit your content char by char. Unicode strings are not " "allowed at all. This is not very practical." msgstr "在纯WSGI环境里,你的应用能返回的内容类型相当有限。应用必须返回一个iterable的字节型字符串。你可以返回一个字符串(因为字符串是iterable的),但这会导致服务器按字符来传输你的内容。Unicode字符串根本不允许。这不是很实用。" #: ../../tutorial.rst:267 msgid "" "Bottle is much more flexible and supports a wide range of types. It even " "adds a ``Content-Length`` header if possible and encodes unicode " "automatically, so you don't have to. What follows is a list of data types " "you may return from your application callbacks and a short description of " "how these are handled by the framework:" msgstr "Bottle支持返回更多的内容类型,更具弹性。它甚至能在合适的情况下,在HTTP头中添加 `Content-Length` 字段和自动转换unicode编码。下面列出了所有你能返回的内容类型,以及框架处理方式的一个简述。" #: ../../tutorial.rst:270 msgid "Dictionaries" msgstr "" #: ../../tutorial.rst:270 msgid "" "As mentioned above, Python dictionaries (or subclasses thereof) are " "automatically transformed into JSON strings and returned to the browser with" " the ``Content-Type`` header set to ``application/json``. This makes it easy" " to implement json-based APIs. Data formats other than json are supported " "too. See the :ref:`tutorial-output-filter` to learn more." msgstr "上面已经提及,Python中的字典类型(或其子类)会被自动转换为JSON字符串。返回给浏览器的时候,HTTP头的 ``Content-Type`` 字段被自动设置为 `` application/json`` 。可十分简单地实现基于JSON的API。Bottle同时支持json之外的数据类型,详见 :ref:`tutorial-output-filter` 。" #: ../../tutorial.rst:273 msgid "Empty Strings, False, None or other non-true values:" msgstr "" #: ../../tutorial.rst:273 msgid "" "These produce an empty output with the ``Content-Length`` header set to 0." msgstr "输出为空, ``Content-Length`` 设为0。" #: ../../tutorial.rst:276 msgid "Unicode strings" msgstr "Unicode的问题" #: ../../tutorial.rst:276 msgid "" "Unicode strings (or iterables yielding unicode strings) are automatically " "encoded with the codec specified in the ``Content-Type`` header (utf8 by " "default) and then treated as normal byte strings (see below)." msgstr "Unicode字符串 (or iterables yielding unicode strings) 被自动转码, ``Content-Type`` 被默认设置为utf8,接着视之为普通字符串(见下文)。" #: ../../tutorial.rst:279 msgid "Byte strings" msgstr "" #: ../../tutorial.rst:279 msgid "" "Bottle returns strings as a whole (instead of iterating over each char) and " "adds a ``Content-Length`` header based on the string length. Lists of byte " "strings are joined first. Other iterables yielding byte strings are not " "joined because they may grow too big to fit into memory. The ``Content-" "Length`` header is not set in this case." msgstr "Bottle将字符串当作一个整体来返回(而不是按字符来遍历),并根据字符串长度添加 ``Content-Length`` 字段。包含字节型字符串的列表先被合并。其它iterable的字节型字符串不会被合并,因为它们也许太大来,耗内存。在这种情况下, ``Content-Length`` 字段不会被设置。" #: ../../tutorial.rst:282 msgid "Instances of HTTPError or HTTPResponse" msgstr "" #: ../../tutorial.rst:282 msgid "" "Returning these has the same effect as when raising them as an exception. In" " case of an :exc:`HTTPError`, the error handler is applied. See :ref" ":`tutorial-errorhandling` for details." msgstr "返回它们和直接raise出来有一样的效果。对于 :exc:`HTTPError` 来说,会调用错误处理程序。详见 :ref:`tutorial-errorhandling` 。" #: ../../tutorial.rst:285 msgid "File objects" msgstr "" #: ../../tutorial.rst:285 msgid "" "Everything that has a ``.read()`` method is treated as a file or file-like " "object and passed to the ``wsgi.file_wrapper`` callable defined by the WSGI " "server framework. Some WSGI server implementations can make use of optimized" " system calls (sendfile) to transmit files more efficiently. In other cases " "this just iterates over chunks that fit into memory. Optional headers such " "as ``Content-Length`` or ``Content-Type`` are *not* set automatically. Use " ":func:`send_file` if possible. See :ref:`tutorial-static-files` for details." msgstr "任何有 ``.read()`` 方法的对象都被当成一个file-like对象来对待,会被传给 WSGI Server 框架定义的 ``wsgi.file_wrapper`` callable对象来处理。一些WSGI Server实现会利用优化过的系统调用(sendfile)来更有效地传输文件,另外就是分块遍历。可选的HTTP头,例如 ``Content-Length`` 和 ``Content-Type`` 不会被自动设置。尽可能使用 :func:`send_file` 。详见 :ref:`tutorial-static-files` 。" #: ../../tutorial.rst:288 msgid "Iterables and generators" msgstr "" #: ../../tutorial.rst:288 msgid "" "You are allowed to use ``yield`` within your callbacks or return an " "iterable, as long as the iterable yields byte strings, unicode strings, " ":exc:`HTTPError` or :exc:`HTTPResponse` instances. Nested iterables are not " "supported, sorry. Please note that the HTTP status code and the headers are " "sent to the browser as soon as the iterable yields its first non-empty " "value. Changing these later has no effect." msgstr "你可以在回调函数中使用 ``yield`` 语句,或返回一个iterable的对象,只要该对象返回的是字节型字符串,unicode字符串, :exc:`HTTPError` 或 :exc:`HTTPResponse` 实例。不支持嵌套iterable对象,不好意思。注意,在iterable对象返回第一个非空值的时候,就会把HTTP状态码和HTTP头发送给浏览器。稍后再更改它们就起不到什么作用了。" #: ../../tutorial.rst:290 msgid "" "The ordering of this list is significant. You may for example return a " "subclass of :class:`str` with a ``read()`` method. It is still treated as a " "string instead of a file, because strings are handled first." msgstr "以上列表的顺序非常重要。在你返回一个 :class:`str` 类的子类的时候,即使它有 ``.read()`` 方法,它依然会被当成一个字符串对待,而不是文件,因为字符串先被处理。" #: ../../tutorial.rst:293 msgid "Changing the Default Encoding" msgstr "改变默认编码" #: ../../tutorial.rst:294 msgid "" "Bottle uses the `charset` parameter of the ``Content-Type`` header to decide" " how to encode unicode strings. This header defaults to ``text/html; " "charset=UTF8`` and can be changed using the :attr:`Response.content_type` " "attribute or by setting the :attr:`Response.charset` attribute directly. " "(The :class:`Response` object is described in the section :ref:`tutorial-" "response`.)" msgstr "Bottle使用 ``Content-Type`` 的 `charset` 参数来决定编码unicode字符串的方式。默认的 ``Content-Type`` 是 ``text/html;charset=UTF8`` ,可在 :attr:`Response.content_type` 属性中修改,或直接设置 :attr:`Response.charset` 的值。关于 :class:`Response` 对象的介绍,详见 :ref:`tutorial-response` 。" #: ../../tutorial.rst:309 msgid "" "In some rare cases the Python encoding names differ from the names supported" " by the HTTP specification. Then, you have to do both: first set the " ":attr:`Response.content_type` header (which is sent to the client unchanged)" " and then set the :attr:`Response.charset` attribute (which is used to " "encode unicode)." msgstr "在极少情况下,Python中定义的编码名字和HTTP标准中的定义不一样。这样,你就必须同时修改 :attr:`Response.content_type`` (发送给客户端的)和设置 :attr:`Response.charset` 属性 (用于编码unicode)。" #: ../../tutorial.rst:314 msgid "Static Files" msgstr "静态文件" #: ../../tutorial.rst:316 msgid "" "You can directly return file objects, but :func:`static_file` is the " "recommended way to serve static files. It automatically guesses a mime-type," " adds a ``Last-Modified`` header, restricts paths to a ``root`` directory " "for security reasons and generates appropriate error responses (403 on " "permission errors, 404 on missing files). It even supports the ``If-" "Modified-Since`` header and eventually generates a ``304 Not Modified`` " "response. You can pass a custom MIME type to disable guessing." msgstr "" #: ../../tutorial.rst:329 msgid "" "You can raise the return value of :func:`static_file` as an exception if you" " really need to." msgstr "如果确实需要,你可将 :func:`static_file` 的返回值当作异常raise出来。" #: ../../tutorial.rst:332 msgid "Forced Download" msgstr "强制下载" #: ../../tutorial.rst:333 msgid "" "Most browsers try to open downloaded files if the MIME type is known and " "assigned to an application (e.g. PDF files). If this is not what you want, " "you can force a download dialog and even suggest a filename to the user::" msgstr "大多数浏览器在知道MIME类型的时候,会尝试直接调用相关程序来打开文件(例如PDF文件)。如果你不想这样,你可强制浏览器只是下载该文件,甚至提供文件名。::" #: ../../tutorial.rst:339 msgid "" "If the ``download`` parameter is just ``True``, the original filename is " "used." msgstr "如果 ``download`` 参数的值为 ``True`` ,会使用原始的文件名。" #: ../../tutorial.rst:344 msgid "HTTP Errors and Redirects" msgstr "HTTP错误和重定向" #: ../../tutorial.rst:346 msgid "" "The :func:`abort` function is a shortcut for generating HTTP error pages." msgstr ":func:`abort` 函数是生成HTTP错误页面的一个捷径。" #: ../../tutorial.rst:355 msgid "" "To redirect a client to a different URL, you can send a ``303 See Other`` " "response with the ``Location`` header set to the new URL. :func:`redirect` " "does that for you::" msgstr "为了将用户访问重定向到其他URL,你在 ``Location`` 中设置新的URL,接着返回一个 ``303 See Other`` 。 :func:`redirect` 函数可以帮你做这件事情。" #: ../../tutorial.rst:362 msgid "You may provide a different HTTP status code as a second parameter." msgstr "你可以在第二个参数中提供另外的HTTP状态码。" #: ../../tutorial.rst:365 msgid "" "Both functions will interrupt your callback code by raising an " ":exc:`HTTPError` exception." msgstr "这两个函数都会抛出 :exc:`HTTPError` 异常,终止回调函数的执行。" #: ../../tutorial.rst:368 msgid "Other Exceptions" msgstr "其他异常" #: ../../tutorial.rst:369 msgid "" "All exceptions other than :exc:`HTTPResponse` or :exc:`HTTPError` will " "result in a ``500 Internal Server Error`` response, so they won't crash your" " WSGI server. You can turn off this behavior to handle exceptions in your " "middleware by setting ``bottle.app().catchall`` to ``False``." msgstr "除了 :exc:`HTTPResponse` 或 :exc:`HTTPError` 以外的其他异常,都会导致500错误,所以不会造成WSGI服务器崩溃。你将 ``bottle.app().catchall`` 的值设为 ``False`` 来关闭这种行为,以便在你的中间件中处理异常。" #: ../../tutorial.rst:375 msgid "The :class:`Response` Object" msgstr ":class:`Response` 对象" #: ../../tutorial.rst:377 msgid "" "Response metadata such as the HTTP status code, response headers and cookies" " are stored in an object called :data:`response` up to the point where they " "are transmitted to the browser. You can manipulate these metadata directly " "or use the predefined helper methods to do so. The full API and feature list" " is described in the API section (see :class:`Response`), but the most " "common use cases and features are covered here, too." msgstr "诸如HTTP状态码,HTTP响应头,用户cookie等元数据都保存在一个名字为 :data:`response` 的对象里面,接着被传输给浏览器。你可直接操作这些元数据或使用一些更方便的函数。在API章节可查到所有相关API(详见 :class:`Response` ),这里主要介绍一些常用方法。" #: ../../tutorial.rst:380 msgid "Status Code" msgstr "状态码" #: ../../tutorial.rst:381 msgid "" "The `HTTP status code `_ controls the behavior of the browser and" " defaults to ``200 OK``. In most scenarios you won't need to set the " ":attr:`Response.status` attribute manually, but use the :func:`abort` helper" " or return an :exc:`HTTPResponse` instance with the appropriate status code." " Any integer is allowed, but codes other than the ones defined by the `HTTP " "specification `_ will only confuse the browser and break " "standards." msgstr "`HTTP状态码 `_ 控制着浏览器的行为,默认为 ``200 OK`` 。多数情况下,你不必手动修改 :attr:`Response.status` 的值,可使用 :func:`abort` 函数或return一个 :exc:`HTTPResponse` 实例(带有合适的状态码)。虽然所有整数都可当作状态码返回,但浏览器不知道如何处理 `HTTP标准 `_ 中定义的那些状态码之外的数字,你也破坏了大家约定的标准。" #: ../../tutorial.rst:384 msgid "Response Header" msgstr "响应头" #: ../../tutorial.rst:385 msgid "" "Response headers such as ``Cache-Control`` or ``Location`` are defined via " ":meth:`Response.set_header`. This method takes two parameters, a header name" " and a value. The name part is case-insensitive::" msgstr "``Cache-Control`` 和 ``Location`` 之类的响应头通过 :meth:`Response.set_header` 来定义。这个方法接受两个参数,一个是响应头的名字,一个是它的值,名字是大小写敏感的。" #: ../../tutorial.rst:392 msgid "" "Most headers are unique, meaning that only one header per name is send to " "the client. Some special headers however are allowed to appear more than " "once in a response. To add an additional header, use " ":meth:`Response.add_header` instead of :meth:`Response.set_header`::" msgstr "大多数的响应头是唯一的,meaning that only one header per name is send to the client。一些特殊的响应头在一次response中允许出现多次。使用 :meth:`Response.add_header` 来添加一个额外的响应头,而不是 :meth:`Response.set_header` ::" #: ../../tutorial.rst:397 msgid "" "Please note that this is just an example. If you want to work with cookies, " "read :ref:`ahead `." msgstr "请注意,这只是一个例子。如果你想使用cookie,详见 :ref:`ahead ` 。" #: ../../tutorial.rst:403 ../../tutorial.rst:532 msgid "Cookies" msgstr "" #: ../../tutorial.rst:405 msgid "" "A cookie is a named piece of text stored in the user's browser profile. You " "can access previously defined cookies via :meth:`Request.get_cookie` and set" " new cookies with :meth:`Response.set_cookie`::" msgstr "Cookie是储存在浏览器配置文件里面的一小段文本。你可通过 :meth:`Request.get_cookie` 来访问已存在的Cookie,或通过 :meth:`Response.set_cookie` 来设置新的Cookie。" #: ../../tutorial.rst:415 msgid "" "The :meth:`Response.set_cookie` method accepts a number of additional " "keyword arguments that control the cookies lifetime and behavior. Some of " "the most common settings are described here:" msgstr ":meth:`Response.set_cookie` 方法接受一系列额外的参数,来控制Cookie的生命周期及行为。一些常用的设置如下:" #: ../../tutorial.rst:417 msgid "**max_age:** Maximum age in seconds. (default: ``None``)" msgstr "**max_age:** 最大有效时间,以秒为单位 (默认: ``None``)" #: ../../tutorial.rst:418 msgid "" "**expires:** A datetime object or UNIX timestamp. (default: ``None``)" msgstr "**expires:** 一个datetime对象或一个UNIX timestamp (默认: ``None``)" #: ../../tutorial.rst:419 msgid "" "**domain:** The domain that is allowed to read the cookie. (default: " "current domain)" msgstr "**domain:** 可访问该Cookie的域名 (默认: 当前域名)" #: ../../tutorial.rst:420 msgid "**path:** Limit the cookie to a given path (default: ``/``)" msgstr "**path:** 限制cookie的访问路径 (默认: ``/``)" #: ../../tutorial.rst:421 msgid "**secure:** Limit the cookie to HTTPS connections (default: off)." msgstr "**secure:** 只允许在HTTPS链接中访问cookie (默认: off)" #: ../../tutorial.rst:422 msgid "" "**httponly:** Prevent client-side javascript to read this cookie (default:" " off, requires Python 2.7 or newer)." msgstr "**httponly:** 防止客户端的javascript读取cookie (默认: off, 要求python 2.7或以上版本)" #: ../../tutorial.rst:424 msgid "" "If neither `expires` nor `max_age` is set, the cookie expires at the end of " "the browser session or as soon as the browser window is closed. There are " "some other gotchas you should consider when using cookies:" msgstr "如果 `expires` 和 `max_age` 两个值都没设置,cookie会在当前的浏览器session失效或浏览器窗口关闭后失效。在使用cookie的时候,应该注意一下几个陷阱。" #: ../../tutorial.rst:426 msgid "Cookies are limited to 4 KB of text in most browsers." msgstr "在大多数浏览器中,cookie的最大容量为4KB。" #: ../../tutorial.rst:427 msgid "" "Some users configure their browsers to not accept cookies at all. Most " "search engines ignore cookies too. Make sure that your application still " "works without cookies." msgstr "一些用户将浏览器设置为不接受任何cookie。大多数搜索引擎也忽略cookie。确保你的应用在无cookie的时候也能工作。" #: ../../tutorial.rst:428 msgid "" "Cookies are stored at client side and are not encrypted in any way. Whatever" " you store in a cookie, the user can read it. Worse than that, an attacker " "might be able to steal a user's cookies through `XSS " "`_" " vulnerabilities on your side. Some viruses are known to read the browser " "cookies, too. Thus, never store confidential information in cookies." msgstr "cookie被储存在客户端,也没被加密。你在cookie中储存的任何数据,用户都可以读取。更坏的情况下,cookie会被攻击者通过 `XSS `_ 偷走,一些已知病毒也会读取浏览器的cookie。既然如此,就不要在cookie中储存任何敏感信息。" #: ../../tutorial.rst:429 msgid "Cookies are easily forged by malicious clients. Do not trust cookies." msgstr "cookie可以被伪造,不要信任cookie!" #: ../../tutorial.rst:434 msgid "Signed Cookies" msgstr "Cookie签名" #: ../../tutorial.rst:435 msgid "" "As mentioned above, cookies are easily forged by malicious clients. Bottle " "can cryptographically sign your cookies to prevent this kind of " "manipulation. All you have to do is to provide a signature key via the " "`secret` keyword argument whenever you read or set a cookie and keep that " "key a secret. As a result, :meth:`Request.get_cookie` will return ``None`` " "if the cookie is not signed or the signature keys don't match::" msgstr "上面提到,cookie容易被客户端伪造。Bottle可通过加密cookie来防止此类攻击。你只需在读取和设置cookie的时候,通过 `secret` 参数来提供一个密钥。如果cookie未签名或密钥不匹配, :meth:`Request.get_cookie` 方法返回 ``None`` " #: ../../tutorial.rst:455 msgid "" "In addition, Bottle automatically pickles and unpickles any data stored to " "signed cookies. This allows you to store any pickle-able object (not only " "strings) to cookies, as long as the pickled data does not exceed the 4 KB " "limit." msgstr "例外,Bottle自动序列化储存在签名cookie里面的数据。你可在cookie中储存任何可序列化的对象(不仅仅是字符串),只要对象大小不超过4KB。" #: ../../tutorial.rst:457 msgid "" "Signed cookies are not encrypted (the client can still see the content) and " "not copy-protected (the client can restore an old cookie). The main " "intention is to make pickling and unpickling safe and prevent manipulation, " "not to store secret information at client side." msgstr "签名cookie在客户端不加密(译者注:即在客户端没有经过二次加密),也没有写保护(客户端可使用之前的cookie)。给cookie签名的主要意义在于在cookie中存储序列化对象和防止伪造cookie,依然不要在cookie中存储敏感信息。" #: ../../tutorial.rst:470 msgid "Request Data" msgstr "请求数据 (Request Data)" #: ../../tutorial.rst:472 msgid "" "Cookies, HTTP header, HTML ``
`` fields and other request data is " "available through the global :data:`request` object. This special object " "always refers to the *current* request, even in multi-threaded environments " "where multiple client connections are handled at the same time::" msgstr "可通过全局的 :data:`request` 对象来访问Cookies,HTTP头,HTML的 ```` 字段,以及其它的请求数据。这个特殊的对象总是指向 *当前* 的请求,即使在同时处理多个客户端连接的多线程情况下。" #: ../../tutorial.rst:481 msgid "" "The :data:`request` object is a subclass of :class:`BaseRequest` and has a " "very rich API to access data. We only cover the most commonly used features " "here, but it should be enough to get started." msgstr ":data:`request` 对象继承自 :class:`BaseRequest` ,提供了丰富的API来访问数据。虽然我们只介绍最常用的特性,也足够入门了。" #: ../../tutorial.rst:486 msgid "Introducing :class:`FormsDict`" msgstr "介绍 :class:`FormsDict` " #: ../../tutorial.rst:488 msgid "" "Bottle uses a special type of dictionary to store form data and cookies. " ":class:`FormsDict` behaves like a normal dictionary, but has some additional" " features to make your life easier." msgstr "Bottle使用了一个特殊的字典来储存表单数据和cookies。 :class:`FormsDict` 表现得像一个普通的字典,但提供了更方便的额外功能。" #: ../../tutorial.rst:490 msgid "" "**Attribute access**: All values in the dictionary are also accessible as " "attributes. These virtual attributes return unicode strings, even if the " "value is missing or unicode decoding fails. In that case, the string is " "empty, but still present::" msgstr "**属性访问** :字典中所有的值都可以当做属性来访问。这些虚拟的属性返回unicode字符串。在字典中缺少对应的值,或unicode解码失败的情况下,属性返回的字符串为空。" #: ../../tutorial.rst:505 msgid "" "**Multiple values per key:** :class:`FormsDict` is a subclass of " ":class:`MultiDict` and can store more than one value per key. The standard " "dictionary access methods will only return a single value, but the " ":meth:`~MultiDict.getall` method returns a (possibly empty) list of all " "values for a specific key::" msgstr "**一个key对应多个value:** :class:`FormsDict` 是 :class:`MutilDict` 的子类,一个key可存储多个value。标准的字典访问方法只返回一个值,但 :meth:`~MultiDict.getall` 方法会返回一个包含了所有value的一个list(也许为空)。" #: ../../tutorial.rst:510 msgid "" "**WTForms support:** Some libraries (e.g. `WTForms " "`_) want all-unicode dictionaries as input." " :meth:`FormsDict.decode` does that for you. It decodes all values and " "returns a copy of itself, while preserving multiple values per key and all " "the other features." msgstr "**WTForms支持:** 一些第三方库(例如 `WTForms `_ )希望输入中的所有字典都是unicode的。 :meth:`FormsDict.decode` 帮你做了这件事情。它将所有value重新编码,并返回原字典的一个拷贝,同时保留所有特性,例如一个key对应多个value。" #: ../../tutorial.rst:514 msgid "" "In **Python 2** all keys and values are byte-strings. If you need unicode, " "you can call :meth:`FormsDict.getunicode` or fetch values via attribute " "access. Both methods try to decode the string (default: utf8) and return an " "empty string if that fails. No need to catch :exc:`UnicodeError`::" msgstr "在 **Python2** 中,所有的key和value都是byte-string。如果你需要unicode,可使用 :meth:`FormsDict.getunicode` 方法或像访问属性那样访问。这两种方法都试着将字符串转码(默认: utf8),如果失败,将返回一个空字符串。无需捕获 :exc:`UnicodeError` 异常。" #: ../../tutorial.rst:521 msgid "" "In **Python 3** all strings are unicode, but HTTP is a byte-based wire " "protocol. The server has to decode the byte strings somehow before they are " "passed to the application. To be on the safe side, WSGI suggests ISO-8859-1 " "(aka latin1), a reversible single-byte codec that can be re-encoded with a " "different encoding later. Bottle does that for :meth:`FormsDict.getunicode` " "and attribute access, but not for the dict-access methods. These return the " "unchanged values as provided by the server implementation, which is probably" " not what you want." msgstr "在 **Python3** 中,所有的字符串都是unicode。但HTTP是基于字节的协议,在byte-string被传给应用之前,服务器必须将其转码。安全起见,WSGI协议建议使用ISO-8859-1 (即是latin1),一个可反转的单字节编码,可被转换为其他编码。Bottle通过 :meth:`FormsDict.getunicode` 和属性访问实现了转码,但不支持字典形式的访问。通过字典形式的访问,将直接返回服务器返回的字符串,未经处理,这或许不是你想要的。" #: ../../tutorial.rst:528 msgid "" "If you need the whole dictionary with correctly decoded values (e.g. for " "WTForms), you can call :meth:`FormsDict.decode` to get a re-encoded copy." msgstr "如果你整个字典包含正确编码后的值(e.g. for WTForms),可通过 :meth:`FormsDict.decode` 方法来获取一个转码后的拷贝(译者注:一个新的实例)。" #: ../../tutorial.rst:534 msgid "" "Cookies are small pieces of text stored in the clients browser and sent back" " to the server with each request. They are useful to keep some state around " "for more than one request (HTTP itself is stateless), but should not be used" " for security related stuff. They can be easily forged by the client." msgstr "Cookie是客户端浏览器存储的一些文本数据,在每次请求的时候发送回给服务器。Cookie被用于在多次请求间保留状态信息(HTTP本身是无状态的),但不应该用于保存安全相关信息。因为客户端很容易伪造Cookie。" #: ../../tutorial.rst:536 msgid "" "All cookies sent by the client are available through " ":attr:`BaseRequest.cookies` (a :class:`FormsDict`). This example shows a " "simple cookie-based view counter::" msgstr "可通过 :attr:`BaseRequest.cookies` (一个 :class:`FormsDict`) 来访问所有客户端发来的Cookie。下面的是一个基于Cookie的访问计数。" #: ../../tutorial.rst:546 msgid "" "The :meth:`BaseRequest.get_cookie` method is a different way do access " "cookies. It supports decoding :ref:`signed cookies ` as described in a separate section." msgstr ":meth:`BaseRequest.get_cookie` 是访问cookie的另一种方法。它支持解析 :ref:`signed cookies ` 。" #: ../../tutorial.rst:549 msgid "HTTP Headers" msgstr "HTTP头" #: ../../tutorial.rst:551 msgid "" "All HTTP headers sent by the client (e.g. ``Referer``, ``Agent`` or " "``Accept-Language``) are stored in a :class:`WSGIHeaderDict` and accessible " "through the :attr:`BaseRequest.headers` attribute. A :class:`WSGIHeaderDict`" " is basically a dictionary with case-insensitive keys::" msgstr "所有客户端发送过来的HTTP头(例如 ``Referer``, ``Agent`` 和 ``Accept-Language``)存储在一个 :class:`WSGIHeaderDict` 中,可通过 :attr:`BaseRequest.headers` 访问。 :class:`WSGIHeaderDict` 基本上是一个字典,其key大小写敏感。" #: ../../tutorial.rst:563 msgid "Query Variables" msgstr "查询变量" #: ../../tutorial.rst:565 msgid "" "The query string (as in ``/forum?id=1&page=5``) is commonly used to transmit" " a small number of key/value pairs to the server. You can use the " ":attr:`BaseRequest.query` attribute (a :class:`FormsDict`) to access these " "values and the :attr:`BaseRequest.query_string` attribute to get the whole " "string." msgstr "查询字符串(例如 ``/forum?id=1&page=5`` )一般用于向服务器传输键值对。你可通过 :attr:`BaseRequest.query` ( :class:`FormsDict` 类的实例) 来访问,和通过 :attr:`BaseRequest.query_string` 来获取整个字符串。" #: ../../tutorial.rst:578 msgid "HTML `` Handling" msgstr "处理HTML的 `` 标签" #: ../../tutorial.rst:580 msgid "" "Let us start from the beginning. In HTML, a typical ```` looks " "something like this:" msgstr "让我们从头开始。在HTML中,一个典型的 ```` 标签看起来是这样的。" #: ../../tutorial.rst:590 msgid "" "The ``action`` attribute specifies the URL that will receive the form data. " "``method`` defines the HTTP method to use (``GET`` or ``POST``). With " "``method=\"get\"`` the form values are appended to the URL and available " "through :attr:`BaseRequest.query` as described above. This is considered " "insecure and has other limitations, so we use ``method=\"post\"`` here. If " "in doubt, use ``POST`` forms." msgstr "``action`` 属性指定了用于接收表单数据的URL, ``method`` 定义了使用的HTTP方法( ``GET`` 或 ``POST`` )。如果使用GET方法,表单中的数据会附加到URL后面,可通过 :attr:`BaseRequest.query` 来访问。这被认为是不安全的,且有其它限制。所以这里我们使用POST方法。如果有疑惑,就使用 ``POST`` 吧。" #: ../../tutorial.rst:592 msgid "" "Form fields transmitted via ``POST`` are stored in :attr:`BaseRequest.forms`" " as a :class:`FormsDict`. The server side code may look like this::" msgstr "通过POST方法传输的表单字段,作为一个 :class:`FormsDict` 存储在 :attr:`BaseRequest.forms` 中。服务器端的代码看起来是这样的。" #: ../../tutorial.rst:615 msgid "" "There are several other attributes used to access form data. Some of them " "combine values from different sources for easier access. The following table" " should give you a decent overview." msgstr "有其它一些属性也可以用来访问表单数据。为了方便,一些属性包含了多个来源的数据。下面的表格可给你一个直观的印象。" #: ../../tutorial.rst:618 msgid "Attribute" msgstr "属性" #: ../../tutorial.rst:618 msgid "GET Form fields" msgstr "" #: ../../tutorial.rst:618 msgid "POST Form fields" msgstr "POST表单数据" #: ../../tutorial.rst:618 msgid "File Uploads" msgstr "" #: ../../tutorial.rst:620 msgid ":attr:`BaseRequest.query`" msgstr "" #: ../../tutorial.rst:620 ../../tutorial.rst:621 ../../tutorial.rst:622 #: ../../tutorial.rst:623 ../../tutorial.rst:623 ../../tutorial.rst:624 #: ../../tutorial.rst:625 ../../tutorial.rst:625 msgid "yes" msgstr "" #: ../../tutorial.rst:620 ../../tutorial.rst:620 ../../tutorial.rst:621 #: ../../tutorial.rst:621 ../../tutorial.rst:622 ../../tutorial.rst:622 #: ../../tutorial.rst:623 ../../tutorial.rst:624 ../../tutorial.rst:624 #: ../../tutorial.rst:625 msgid "no" msgstr "" #: ../../tutorial.rst:621 msgid ":attr:`BaseRequest.forms`" msgstr "" #: ../../tutorial.rst:622 msgid ":attr:`BaseRequest.files`" msgstr "" #: ../../tutorial.rst:623 msgid ":attr:`BaseRequest.params`" msgstr "" #: ../../tutorial.rst:624 msgid ":attr:`BaseRequest.GET`" msgstr "" #: ../../tutorial.rst:625 msgid ":attr:`BaseRequest.POST`" msgstr "" #: ../../tutorial.rst:630 msgid "File uploads" msgstr "文件上传" #: ../../tutorial.rst:632 msgid "" "To support file uploads, we have to change the ```` tag a bit. First, " "we tell the browser to encode the form data in a different way by adding an " "``enctype=\"multipart/form-data\"`` attribute to the ```` tag. Then, " "we add ```` tags to allow the user to select a file. " "Here is an example:" msgstr "为了支持文件上传,我们需要小改一下上面 ```` 标签,加上 ``enctype=\"multipart/form-data\"`` 属性,告诉浏览器用另一种方式编码表单数据。接下来,我们添加 ```` 标签,让用户可以选择需要上传的文件。例子如下。" #: ../../tutorial.rst:642 msgid "" "Bottle stores file uploads in :attr:`BaseRequest.files` as " ":class:`FileUpload` instances, along with some metadata about the upload. " "Let us assume you just want to save the file to disk::" msgstr "Bottle将上传的文件当做一个 :class:`FileUpload` 实例存储在 :attr:`BaseRequest.files` 中,伴随着一些这次上传的元数据。我们假设你仅是想把上传的文件保存到磁盘中。" #: ../../tutorial.rst:656 msgid "" ":attr:`FileUpload.filename` contains the name of the file on the clients " "file system, but is cleaned up and normalized to prevent bugs caused by " "unsupported characters or path segments in the filename. If you need the " "unmodified name as sent by the client, have a look at " ":attr:`FileUpload.raw_filename`." msgstr ":attr:`FileUpload.filename` 包含客户端传上来的文件的文件名,但为了防止异常字符带来的bug,这里的文件名已经被处理过。如果你需要未经改动的文件名,看看 :attr:`FileUpload.raw_filename` 。" #: ../../tutorial.rst:658 msgid "" "The :attr:`FileUpload.save` method is highly recommended if you want to " "store the file to disk. It prevents some common errors (e.g. it does not " "overwrite existing files unless you tell it to) and stores the file in a " "memory efficient way. You can access the file object directly via " ":attr:`FileUpload.file`. Just be careful." msgstr "如果你想将文件保存到磁盘,强烈建议你使用 :attr:`FileUpload.save` 方法。它避免了一些常见的错误(例如,它不会覆盖已经存在的文件,除非你告诉它可以覆盖),并且更有效地使用内存。你可以通过 :attr:`FileUpload.file` 来直接访问文件对象,但是要谨慎。" #: ../../tutorial.rst:662 msgid "JSON Content" msgstr "JSON内容" #: ../../tutorial.rst:664 msgid "" "Some JavaScript or REST clients send ``application/json`` content to the " "server. The :attr:`BaseRequest.json` attribute contains the parsed data " "structure, if available." msgstr "一些JavaScript或支持REST的客户端会发送 ``application/json`` 内容给服务器。如果可用(合法的JSON), :attr:`BaseRequest.json` 会包含解析后的数据结构。" #: ../../tutorial.rst:668 msgid "The raw request body" msgstr "原始的请求数据" #: ../../tutorial.rst:670 msgid "" "You can access the raw body data as a file-like object via " ":attr:`BaseRequest.body`. This is a :class:`BytesIO` buffer or a temporary " "file depending on the content length and :attr:`BaseRequest.MEMFILE_MAX` " "setting. In both cases the body is completely buffered before you can access" " the attribute. If you expect huge amounts of data and want to get direct " "unbuffered access to the stream, have a look at ``request['wsgi.input']``." msgstr "你可以把 :attr:`BaseRequest.body` 当做一个file-like 对象来访问。根据内容的长度,以及 :attr:`BaseRequest.MEMFILE_MAX` 中的设置,它可以是一个 :class:`BytesIO` 缓存或一个磁盘上的临时文件。无论如何,它都是被缓存的。如果你无需缓存,想直接访问文件流,可看看 ``request['wsgi.input']`` 。" #: ../../tutorial.rst:675 msgid "WSGI Environment" msgstr "WSGI环境" #: ../../tutorial.rst:677 msgid "" "Each :class:`BaseRequest` instance wraps a WSGI environment dictionary. The " "original is stored in :attr:`BaseRequest.environ`, but the request object " "itself behaves like a dictionary, too. Most of the interesting data is " "exposed through special methods or attributes, but if you want to access " "`WSGI environ variables `_ directly, you can do so::" msgstr "每一个 :class:`BaseRequest` 类的实例都包含一个WSGI环境的字典。最初存储在 :attr:`BaseRequest.environ` 中,但request对象也表现的像一个字典。大多数有用的数据都通过特定的方法或属性暴露了出来,但如果你想直接访问 `WSGI环境变量 `_ ,可以这样做::" #: ../../tutorial.rst:695 msgid "Templates" msgstr "模板" #: ../../tutorial.rst:697 msgid "" "Bottle comes with a fast and powerful built-in template engine called " ":doc:`stpl`. To render a template you can use the :func:`template` function " "or the :func:`view` decorator. All you have to do is to provide the name of " "the template and the variables you want to pass to the template as keyword " "arguments. Here’s a simple example of how to render a template::" msgstr "Bottle内置了一个快速的,强大的模板引擎,称为 :doc:`stpl` 。可通过 :func:`template` 函数或 :func:`view` 修饰器来渲染一个模板。只需提供模板的名字和传递给模板的变量。下面是一个渲染模板的简单例子::" #: ../../tutorial.rst:704 msgid "" "This will load the template file ``hello_template.tpl`` and render it with " "the ``name`` variable set. Bottle will look for templates in the " "``./views/`` folder or any folder specified in the ``bottle.TEMPLATE_PATH`` " "list." msgstr "这会加载 ``hello_template.tpl`` 模板文件,并提供 ``name`` 变量。默认情况,Bottle会在 ``./views/`` 目录查找模板文件(译者注:或当前目录)。可在 ``bottle.TEMPLATE_PATH`` 这个列表中添加更多的模板路径。" #: ../../tutorial.rst:706 msgid "" "The :func:`view` decorator allows you to return a dictionary with the " "template variables instead of calling :func:`template`::" msgstr ":func:`view` 修饰器允许你在回调函数中返回一个字典,并将其传递给模板,和 :func:`template` 函数做同样的事情。" #: ../../tutorial.rst:715 msgid "Syntax" msgstr "语法" #: ../../tutorial.rst:718 msgid "" "The template syntax is a very thin layer around the Python language. Its " "main purpose is to ensure correct indentation of blocks, so you can format " "your template without worrying about indentation. Follow the link for a full" " syntax description: :doc:`stpl`" msgstr "模板语法类似于Python的语法。它要确保语句块的正确缩进,所以你在写模板的时候无需担心会出现缩进问题。详细的语法描述可看 :doc:`stpl` 。" #: ../../tutorial.rst:720 msgid "Here is an example template::" msgstr "简单的模板例子::" #: ../../tutorial.rst:731 msgid "Caching" msgstr "缓存" #: ../../tutorial.rst:732 msgid "" "Templates are cached in memory after compilation. Modifications made to the " "template files will have no affect until you clear the template cache. Call " "``bottle.TEMPLATES.clear()`` to do so. Caching is disabled in debug mode." msgstr "模板在经过编译后被缓存在内存里。你在修改模板文件后,要调用 ``bottle.TEMPLATES.clear()`` 函数清除缓存才能看到效果。在debug模式下,缓存被禁用了,无需手动清除缓存。" #: ../../tutorial.rst:742 msgid "Plugins" msgstr "插件" #: ../../tutorial.rst:746 msgid "" "Bottle's core features cover most common use-cases, but as a micro-framework" " it has its limits. This is where \"Plugins\" come into play. Plugins add " "missing functionality to the framework, integrate third party libraries, or " "just automate some repetitive work." msgstr "Bottle的核心功能覆盖了常见的使用情况,但是作为一个迷你框架,它有它的局限性。所以我们引入了插件机制,插件可以给框架添加其缺少的功能,集成第三方的库,或是自动化一些重复性的工作。" #: ../../tutorial.rst:748 msgid "" "We have a growing :doc:`/plugins/index` and most plugins are designed to be " "portable and re-usable across applications. The chances are high that your " "problem has already been solved and a ready-to-use plugin exists. If not, " "the :doc:`/plugindev` may help you." msgstr "我们有一个不断增长的 :doc:`/plugins/index` 插件列表,大多数插件都被设计为可插拔的。有很大可能,你的问题已经被解决,而且已经有现成的插件可以使用了。如果没有现成的插件, :doc:`/plugindev` 有介绍如何开发一个插件。" #: ../../tutorial.rst:750 msgid "" "The effects and APIs of plugins are manifold and depend on the specific " "plugin. The ``SQLitePlugin`` plugin for example detects callbacks that " "require a ``db`` keyword argument and creates a fresh database connection " "object every time the callback is called. This makes it very convenient to " "use a database::" msgstr "插件扮演着各种各样的角色。例如, ``SQLitePlugin`` 插件给每个route的回调函数都添加了一个 ``db`` 参数,在回调函数被调用的时候,会新建一个数据库连接。这样,使用数据库就非常简单了。" #: ../../tutorial.rst:770 msgid "" "Other plugin may populate the thread-safe :data:`local` object, change " "details of the :data:`request` object, filter the data returned by the " "callback or bypass the callback completely. An \"auth\" plugin for example " "could check for a valid session and return a login page instead of calling " "the original callback. What happens exactly depends on the plugin." msgstr "其它插件或许在线程安全的 :data:`local` 对象里面发挥作用,改变 :data:`request` 对象的细节,过滤回调函数返回的数据或完全绕开回调函数。举个例子,一个用于登录验证的插件会在调用原先的回调函数响应请求之前,验证用户的合法性,如果是非法访问,则返回登录页面而不是调用回调函数。具体的做法要看插件是如何实现的。" #: ../../tutorial.rst:774 msgid "Application-wide Installation" msgstr "整个应用的范围内安装插件" #: ../../tutorial.rst:776 msgid "" "Plugins can be installed application-wide or just to some specific routes " "that need additional functionality. Most plugins can safely be installed to " "all routes and are smart enough to not add overhead to callbacks that do not" " need their functionality." msgstr "可以在整个应用的范围内安装插件,也可以只是安装给某些route。大多数插件都可安全地安装给所有route,也足够智能,可忽略那些并不需要它们的route。" #: ../../tutorial.rst:778 msgid "" "Let us take the ``SQLitePlugin`` plugin for example. It only affects route " "callbacks that need a database connection. Other routes are left alone. " "Because of this, we can install the plugin application-wide with no " "additional overhead." msgstr "让我们拿 ``SQLitePlugin`` 插件举例,它只会影响到那些需要数据库连接的route,其它route都被忽略了。正因为如此,我们可以放心地在整个应用的范围内安装这个插件。" #: ../../tutorial.rst:780 msgid "" "To install a plugin, just call :func:`install` with the plugin as first " "argument::" msgstr "调用 :func:`install` 函数来安装一个插件::" #: ../../tutorial.rst:785 msgid "" "The plugin is not applied to the route callbacks yet. This is delayed to " "make sure no routes are missed. You can install plugins first and add routes" " later, if you want to. The order of installed plugins is significant, " "though. If a plugin requires a database connection, you need to install the " "database plugin first." msgstr "插件没有马上应用到所有route上面,它被延迟执行来确保没有遗漏任何route。你可以先安装插件,再添加route。有时,插件的安装顺序很重要,如果另外一个插件需要连接数据库,那么你就需要先安装操作数据库的插件。" #: ../../tutorial.rst:789 msgid "Uninstall Plugins" msgstr "卸载插件" #: ../../tutorial.rst:790 msgid "" "You can use a name, class or instance to :func:`uninstall` a previously " "installed plugin::" msgstr "调用 :func:`uninstall` 函数来卸载已经安装的插件" #: ../../tutorial.rst:800 msgid "" "Plugins can be installed and removed at any time, even at runtime while " "serving requests. This enables some neat tricks (installing slow debugging " "or profiling plugins only when needed) but should not be overused. Each time" " the list of plugins changes, the route cache is flushed and all plugins are" " re-applied." msgstr "在任何时候,插件都可以被安装或卸载,即使是在服务器正在运行的时候。一些小技巧应用到了这个特征,例如在需要的时候安装一些供debug和性能测试的插件,但不可滥用这个特性。每一次安装或卸载插件的时候,route缓存都会被刷新,所有插件被重新加载。" #: ../../tutorial.rst:803 msgid "" "The module-level :func:`install` and :func:`uninstall` functions affect the " ":ref:`default-app`. To manage plugins for a specific application, use the " "corresponding methods on the :class:`Bottle` application object." msgstr "模块层面的 :func:`install` 和 :func:`unistall` 函数会影响 :ref:`default-app` 。针对应用来管理插件,可使用 :class:`Bottle` 应用对象的相应方法。" #: ../../tutorial.rst:807 msgid "Route-specific Installation" msgstr "安装给特定的route" #: ../../tutorial.rst:809 msgid "" "The ``apply`` parameter of the :func:`route` decorator comes in handy if you" " want to install plugins to only a small number of routes::" msgstr ":func:`route` 修饰器的 ``apply`` 参数可以给指定的route安装插件" #: ../../tutorial.rst:819 msgid "Blacklisting Plugins" msgstr "插件黑名单" #: ../../tutorial.rst:821 msgid "" "You may want to explicitly disable a plugin for a number of routes. The " ":func:`route` decorator has a ``skip`` parameter for this purpose::" msgstr "如果你想显式地在一些route上面禁用某些插件,可使用 :func:`route` 修饰器的 ``skip`` 参数::" #: ../../tutorial.rst:843 msgid "" "The ``skip`` parameter accepts a single value or a list of values. You can " "use a name, class or instance to identify the plugin that is to be skipped. " "Set ``skip=True`` to skip all plugins at once." msgstr "``skip`` 参数接受单一的值或是一个list。你可使用插件的名字,类,实例来指定你想要禁用的插件。如果 ``skip`` 的值为True,则禁用所有插件。" #: ../../tutorial.rst:846 msgid "Plugins and Sub-Applications" msgstr "插件和子应用" #: ../../tutorial.rst:848 msgid "" "Most plugins are specific to the application they were installed to. " "Consequently, they should not affect sub-applications mounted with " ":meth:`Bottle.mount`. Here is an example::" msgstr "大多数插件只会影响到安装了它们的应用。因此,它们不应该影响通过 :meth:`Bottle.mount` 方法挂载上来的子应用。这里有一个例子。" #: ../../tutorial.rst:859 msgid "" "Whenever you mount an application, Bottle creates a proxy-route on the main-" "application that forwards all requests to the sub-application. Plugins are " "disabled for this kind of proxy-route by default. As a result, our " "(fictional) `WTForms` plugin affects the ``/contact`` route, but does not " "affect the routes of the ``/blog`` sub-application." msgstr "在你挂载一个应用的时候,Bottle在主应用上面创建一个代理route,将所有请求转接给子应用。在代理route上,默认禁用了插件。如上所示,我们的 ``WTForms`` 插件影响了 ``/contact`` route,但不会影响挂载在root上面的 ``/blog`` 。" #: ../../tutorial.rst:861 msgid "" "This behavior is intended as a sane default, but can be overridden. The " "following example re-activates all plugins for a specific proxy-route::" msgstr "这个是一个合理的行为,但可被改写。下面的例子,在指定的代理route上面应用了插件。" #: ../../tutorial.rst:865 msgid "" "But there is a snag: The plugin sees the whole sub-application as a single " "route, namely the proxy-route mentioned above. In order to affect each " "individual route of the sub-application, you have to install the plugin to " "the mounted application explicitly." msgstr "这里存在一个小难题: 插件会整个子应用当作一个route看待,即是上面提及的代理route。如果想在子应用的每个route上面应用插件,你必须显式地在子应用上面安装插件。" #: ../../tutorial.rst:870 msgid "Development" msgstr "开发" #: ../../tutorial.rst:872 msgid "" "So you have learned the basics and want to write your own application? Here " "are some tips that might help you beeing more productive." msgstr "" #: ../../tutorial.rst:878 msgid "Default Application" msgstr "默认应用" #: ../../tutorial.rst:880 msgid "" "Bottle maintains a global stack of :class:`Bottle` instances and uses the " "top of the stack as a default for some of the module-level functions and " "decorators. The :func:`route` decorator, for example, is a shortcut for " "calling :meth:`Bottle.route` on the default application::" msgstr "Bottle维护一个全局的 :class:`Bottle` 实例的栈,模块层面的函数和修饰器使用栈顶实例作为默认应用。例如 :func:`route` 修饰器,相当于在默认应用上面调用了 :meth:`Bottle.route` 方法。" #: ../../tutorial.rst:888 msgid "" "This is very convenient for small applications and saves you some typing, " "but also means that, as soon as your module is imported, routes are " "installed to the global default application. To avoid this kind of import " "side-effects, Bottle offers a second, more explicit way to build " "applications::" msgstr "" #: ../../tutorial.rst:898 msgid "" "Separating the application object improves re-usability a lot, too. Other " "developers can safely import the ``app`` object from your module and use " ":meth:`Bottle.mount` to merge applications together." msgstr "分离应用对象,大大提高了可重用性。其他开发者可安全地从你的应用中导入 ``app`` 对象,然后通过 :meth:`Bottle.mount` 方法来合并到其它应用中。" #: ../../tutorial.rst:903 msgid "" "Starting with bottle-0.13 you can use :class:`Bottle` instances as context " "managers::" msgstr "" #: ../../tutorial.rst:928 msgid "Debug Mode" msgstr "调试模式" #: ../../tutorial.rst:930 msgid "During early development, the debug mode can be very helpful." msgstr "在开发的早期阶段,调试模式非常有用。" #: ../../tutorial.rst:938 msgid "" "In this mode, Bottle is much more verbose and provides helpful debugging " "information whenever an error occurs. It also disables some optimisations " "that might get in your way and adds some checks that warn you about possible" " misconfiguration." msgstr "在调试模式下,当错误发生的时候,Bottle会提供更多的调试信息。同时禁用一些可能妨碍你的优化措施,检查你的错误设置。" #: ../../tutorial.rst:940 msgid "Here is an incomplete list of things that change in debug mode:" msgstr "下面是调试模式下会发生改变的东西,但这份列表不完整:" #: ../../tutorial.rst:942 msgid "The default error page shows a traceback." msgstr "默认的错误页面会打印出运行栈。" #: ../../tutorial.rst:943 msgid "Templates are not cached." msgstr "模板不会被缓存。" #: ../../tutorial.rst:944 msgid "Plugins are applied immediately." msgstr "插件马上生效。" #: ../../tutorial.rst:946 msgid "Just make sure not to use the debug mode on a production server." msgstr "请确保不要在生产环境中使用调试模式。" #: ../../tutorial.rst:949 msgid "Auto Reloading" msgstr "自动加载" #: ../../tutorial.rst:951 msgid "" "During development, you have to restart the server a lot to test your recent" " changes. The auto reloader can do this for you. Every time you edit a " "module file, the reloader restarts the server process and loads the newest " "version of your code." msgstr "在开发的时候,你需要不断地重启服务器来验证你最新的改动。自动加载功能可以替你做这件事情。在你编辑完一个模块文件后,它会自动重启服务器进程,加载最新版本的代码。" #: ../../tutorial.rst:961 msgid "" "How it works: the main process will not start a server, but spawn a new " "child process using the same command line arguments used to start the main " "process. All module-level code is executed at least twice! Be careful." msgstr "它的工作原理,主进程不会启动服务器,它使用相同的命令行参数,创建一个子进程来启动服务器。请注意,所有模块级别的代码都被执行了至少两次。" #: ../../tutorial.rst:966 msgid "" "The child process will have ``os.environ['BOTTLE_CHILD']`` set to ``True`` " "and start as a normal non-reloading app server. As soon as any of the loaded" " modules changes, the child process is terminated and re-spawned by the main" " process. Changes in template files will not trigger a reload. Please use " "debug mode to deactivate template caching." msgstr "子进程中 ``os.environ['BOOTLE_CHILD']`` 变量的值被设为 ``True`` ,它运行一个不会自动加载的服务器。在代码改变后,主进程会终止掉子进程,并创建一个新的子进程。更改模板文件不会触发自动重载,请使用debug模式来禁用模板缓存。" #: ../../tutorial.rst:972 msgid "" "The reloading depends on the ability to stop the child process. If you are " "running on Windows or any other operating system not supporting " "``signal.SIGINT`` (which raises ``KeyboardInterrupt`` in Python), " "``signal.SIGTERM`` is used to kill the child. Note that exit handlers and " "finally clauses, etc., are not executed after a ``SIGTERM``." msgstr "自动加载需要终止子进程。如果你运行在Windows等不支持 ``signal.SIGINT`` (会在Python中raise ``KeyboardInterrupt`` 异常)的系统上,会使用 ``signal.SIGTERM`` 来杀掉子进程。在子进程被 ``SIGTERM`` 杀掉的时候,exit handlers和finally等语句不会被执行。" #: ../../tutorial.rst:980 msgid "Command Line Interface" msgstr "命令行接口" #: ../../tutorial.rst:984 msgid "Starting with version 0.10 you can use bottle as a command-line tool:" msgstr "从0.10版本开始,你可像一个命令行工具那样使用Bottle:" #: ../../tutorial.rst:1008 msgid "" "The `ADDRESS` field takes an IP address or an IP:PORT pair and defaults to " "``localhost:8080``. The other parameters should be self-explanatory." msgstr "`ADDRESS` 参数接受一个IP地址或IP:端口,其默认为 ``localhost:8080`` 。其它参数都很好地自我解释了。" #: ../../tutorial.rst:1010 msgid "" "Both plugins and applications are specified via import expressions. These " "consist of an import path (e.g. ``package.module``) and an expression to be " "evaluated in the namespace of that module, separated by a colon. See " ":func:`load` for details. Here are some examples:" msgstr "插件和应用都通过一个导入表达式来指定。包含了导入的路径(例如: ``package.module`` )和模块命名空间内的一个表达式,两者用\":\"分开。下面是一个简单例子,详见 :func:`load` 。" #: ../../tutorial.rst:1031 msgid "Deployment" msgstr "部署" #: ../../tutorial.rst:1033 msgid "" "Bottle runs on the built-in `wsgiref WSGIServer " "`_" " by default. This non-threading HTTP server is perfectly fine for " "development and early production, but may become a performance bottleneck " "when server load increases." msgstr "Bottle默认运行在内置的 `wsgiref `_ 服务器上面。这个单线程的HTTP服务器在开发的时候特别有用,但其性能低下,在服务器负载不断增加的时候也许会是性能瓶颈。" #: ../../tutorial.rst:1035 msgid "" "The easiest way to increase performance is to install a multi-threaded " "server library like paste_ or cherrypy_ and tell Bottle to use that instead " "of the single-threaded server::" msgstr "最早的解决办法是让Bottle使用 paste_ 或 cherrypy_ 等多线程的服务器。" #: ../../tutorial.rst:1039 msgid "" "This, and many other deployment options are described in a separate article:" " :doc:`deployment`" msgstr "在 :doc:`deployment` 章节中,会介绍更多部署的选择。" #: ../../tutorial.rst:1047 msgid "Glossary" msgstr "词汇表" #: ../../tutorial.rst:1050 msgid "callback" msgstr "" #: ../../tutorial.rst:1052 msgid "" "Programmer code that is to be called when some external action happens. In " "the context of web frameworks, the mapping between URL paths and application" " code is often achieved by specifying a callback function for each URL." msgstr "" #: ../../tutorial.rst:1056 msgid "decorator" msgstr "" #: ../../tutorial.rst:1058 msgid "" "A function returning another function, usually applied as a function " "transformation using the ``@decorator`` syntax. See `python documentation " "for function definition " "`_ for more " "about decorators." msgstr "" #: ../../tutorial.rst:1059 msgid "environ" msgstr "" #: ../../tutorial.rst:1061 msgid "" "A structure where information about all documents under the root is saved, " "and used for cross-referencing. The environment is pickled after the " "parsing stage, so that successive runs only need to read and parse new and " "changed documents." msgstr "" #: ../../tutorial.rst:1065 msgid "handler function" msgstr "" #: ../../tutorial.rst:1067 msgid "" "A function to handle some specific event or situation. In a web framework, " "the application is developed by attaching a handler function as callback for" " each specific URL comprising the application." msgstr "" #: ../../tutorial.rst:1070 msgid "source directory" msgstr "" #: ../../tutorial.rst:1072 msgid "" "The directory which, including its subdirectories, contains all source files" " for one Sphinx project." msgstr ""