意见

主要工作之一 Pyramid 是查找和调用 view callable 当A request 到达您的应用程序。视图可调用文件是一些代码,它们在响应对应用程序的请求时做一些有趣的事情。它们是任何有趣的Web应用程序的“肉”。

注解

A Pyramid view callable 通常在会话速记中被称为 view . 然而,在本文档中,我们需要使用不太含糊的术语,因为视图之间存在显著差异 配置 ,实现视图的代码 可赎回的 以及观察的过程 查找 .

本章描述如何定义视图可调用文件。我们得等到下一章(题为 查看配置 )了解我们的实际情况 Pyramid 将视图可调用连接到特定的URL模式和其他请求情况。

查看可调用

视图可调用对象存在听起来明显、可调用的python对象的风险。具体来说,视图可调用文件可以是实现 __call__ 方法(使实例可调用)。

视图可调用文件必须至少接受一个名为 request . 此参数表示 Pyramid Request 对象。请求对象表示 WSGI 环境提供给 Pyramid 通过上游的wsgi服务器。正如您可能期望的那样,请求对象包含应用程序需要了解的关于正在发出的特定HTTP请求的所有信息。

视图Callable的最终责任是创建 Pyramid Response 对象。这可以通过创建 Response 对象,并直接返回它,或从视图可调用的主体中引发特殊类型的异常。

将可调用视图定义为函数

定义视图可调用的最简单方法之一是创建一个接受名为 request ,返回 Response 对象。例如,这是一个“hello world”视图,可作为函数实现:

1
2
3
4
from pyramid.response import Response

def hello_world(request):
    return Response('Hello world!')

将可调用视图定义为类

视图可调用也可以由python类而不是函数表示。当一个视图可调用是一个类时,调用语义与当它是一个函数或另一个非类可调用时略有不同。当视图可调用为类时,类的 __init__ 方法是用 request 参数。因此,将创建类的实例。后来,那个例子 __call__ 调用方法时没有参数。定义为类的视图必须具有以下特性。

  • 一个 __init__ 接受 request 论点
  • __call__ (或其他)不接受任何参数并返回响应的方法

例如:

1
2
3
4
5
6
7
8
from pyramid.response import Response

class MyView(object):
    def __init__(self, request):
        self.request = request

    def __call__(self):
        return Response('hello')

传递给的请求对象 __init__ 与中描述的请求对象类型相同 将可调用视图定义为函数 .

如果您想使用不同于 __call__ 要表示预期返回响应的方法,可以使用 attr 值作为视图配置的一部分。见 查看配置参数 . 同一个视图可调用类可以在具有不同视图配置语句的不同视图配置语句中使用 attr 值,如果希望类表示相关视图可调用文件的集合,则每个值都指向类的不同方法。

查看可调用响应

可调用视图可能返回实现 Pyramid Response 接口。返回实现 Response 接口将返回 pyramid.response.Response 直接对象实例。例如:

1
2
3
4
from pyramid.response import Response

def view(request):
    return Response('OK')

Pyramid 提供从继承的不同“异常”类的范围 pyramid.response.Response . 例如,类的一个实例 pyramid.httpexceptions.HTTPFound 也是有效的响应对象,因为它继承自 Response . 有关示例,请参见 HTTP异常使用可调用的视图执行HTTP重定向 .

注解

还可以从视图中返回不属于 pyramid.response.Response 在各种情况下。这在编写测试和尝试在视图可调用文件之间共享代码时非常有用。见 渲染器 为了共同的方式考虑到这一点。允许视图可调用文件返回非响应对象的一种不太常见的方法记录在 更改金字塔处理视图响应的方式 .

在视图可调用文件中使用特殊异常

通常,当在可调用视图中引发python异常时, Pyramid 允许异常一直传播到 WSGI 调用应用程序的服务器。它通常被捕获并记录在那里。

但是,为了方便起见,存在一组特殊的异常。当在可调用视图中引发这些异常之一时,它将始终导致 Pyramid 以生成响应。这些被称为 HTTP exception 物体。

HTTP异常

所有 pyramid.httpexceptions 记录为继承自 pyramid.httpexceptions.HTTPExceptionhttp exception 物体。HTTP异常对象的实例可以是 返回提高 从视图内代码。无论哪种情况(返回或提升),实例都将用作视图的响应。

例如, pyramid.httpexceptions.HTTPUnauthorized 可以引发异常。这将导致使用 401 Unauthorized 状态:

1
2
3
4
from pyramid.httpexceptions import HTTPUnauthorized

def aview(request):
    raise HTTPUnauthorized()

HTTP异常不是引发的,而是可以 返回 (HTTP异常也是有效的响应对象):

1
2
3
4
from pyramid.httpexceptions import HTTPUnauthorized

def aview(request):
    return HTTPUnauthorized()

创建HTTP异常的快捷方式是 pyramid.httpexceptions.exception_response() 功能。此函数接受HTTP状态代码并返回相应的HTTP异常。例如,不是导入和构造 HTTPUnauthorized 响应对象,可以使用 exception_response() 函数构造并返回同一对象。

1
2
3
4
from pyramid.httpexceptions import exception_response

def aview(request):
    raise exception_response(401)

情况就是这样,因为 401 是“http unauthorized”的http状态代码。因此, raise exception_response(401) 在功能上等同于 raise HTTPUnauthorized() . 其中提供了将每个HTTP响应代码映射到其用途及其关联的HTTP异常对象的文档 pyramid.httpexceptions .

1.1 新版功能: 这个 exception_response() 功能。

金字塔如何使用HTTP异常

HTTP异常是应用程序开发人员直接使用的。但是,在正常操作期间,金字塔本身会在不同的点上引发两个HTTP异常。

如果 HTTPNotFound 是由金字塔本身或在视图代码中引发的, Not Found View 将返回到执行请求的用户代理。

如果 HTTPForbidden 是由金字塔本身或在视图代码中引发的, Forbidden View 将返回到执行请求的用户代理。

自定义异常视图

允许特殊视图引发和捕获HTTP异常的机制,如中所述。 在视图可调用文件中使用特殊异常 应用程序开发人员也可以使用它将任意异常转换为响应。

注册一个 exception view 每当从内部引发特定异常时都应该调用 Pyramid 查看代码,使用 pyramid.config.Configurator.add_exception_view() 要注册与异常(或异常的子类)匹配的视图配置,并指向要为其生成响应的可调用视图。异常将作为 context 对任何论点 view predicate 注册到视图以及视图本身。为了方便起见,有了一个新的装饰器, pyramid.views.exception_view_config ,可用于轻松注册异常视图。

例如,在名为 helloworld.exceptions

1
2
3
class ValidationFailure(Exception):
    def __init__(self, msg):
        self.msg = msg

您可以连接一个可在任何时候调用的视图 其他 代码引发 helloworld.exceptions.ValidationFailure 例外:

1
2
3
4
5
6
7
8
from pyramid.view import exception_view_config
from helloworld.exceptions import ValidationFailure

@exception_view_config(ValidationFailure)
def failed_validation(exc, request):
    response =  Response('Failed validation: %s' % exc.msg)
    response.status_int = 500
    return response

假设A scan 运行以获取此视图注册,每当 helloworld.exceptions.ValidationFailure 由应用程序的视图代码引发。自定义根工厂、自定义遍历器、自定义视图或路由谓词引发的相同异常也被捕获并挂接。

其他普通视图谓词也可以与异常视图注册一起使用:

1
2
3
4
5
6
7
8
from pyramid.view import view_config
from helloworld.exceptions import ValidationFailure

@exception_view_config(ValidationFailure, route_name='home')
def failed_validation(exc, request):
    response =  Response('Failed validation: %s' % exc.msg)
    response.status_int = 500
    return response

上述异常视图将 route_name 属于 home ,表示只有匹配的路由的名称为时才会调用它。 home . 因此,对于系统中的任何给定异常,您都可以有多个异常视图:“最具体”的视图将在请求环境集与视图注册匹配时调用。

创建异常视图配置时无法成功使用的唯一视图谓词是 name . 用于查找异常视图的名称总是空字符串。注册为具有名称的异常视图的视图将被忽略。

注解

在大多数情况下,您应该注册一个 exception view 通过使用 pyramid.config.Configurator.add_exception_view() . 但是,可以针对继承自的上下文资源类型注册“普通”(即非异常)视图。 Exception (即, config.add_view(context=Exception) )处理视图配置时, two 视图已注册。一个是“正常”视图,另一个是 exception view . 这意味着您可以将异常用作 context 对于普通视图。

包装这两个视图的视图派生器的行为可能不同。见 异常视图和视图派生器 有关此的详细信息。

可以使用任何视图注册机制配置异常视图: @exception_view_config 装饰或命令 add_exception_view 风格。

注解

皮拉米德 exception view 处理逻辑作为tween工厂功能实现: pyramid.tweens.excview_tween_factory() . 如果需要金字塔异常视图处理,并且通过 pyramid.tweens 配置设置, pyramid.tweens.excview_tween_factory() 函数必须添加到 pyramid.tweens 配置设置列表。如果它不存在,金字塔将不执行异常视图处理。

使用可调用的视图执行HTTP重定向

您可以使用 pyramid.httpexceptions.HTTPFound 班级。引发或返回此类的实例将导致客户端收到“302找到”响应。

要做到这一点,你可以 返回pyramid.httpexceptions.HTTPFound 实例。

1
2
3
4
from pyramid.httpexceptions import HTTPFound

def myview(request):
    return HTTPFound(location='http://example.com')

或者,你可以 提升 httpFound异常而不是返回异常。

1
2
3
4
from pyramid.httpexceptions import HTTPFound

def myview(request):
    raise HTTPFound(location='http://example.com')

引发实例时,默认情况下会捕获该实例 exception response 处理程序并转换为响应。

处理视图可调用文件中的表单提交(Unicode和字符集问题)

大多数Web应用程序需要接受来自Web浏览器和各种其他客户端的表单提交。在 Pyramid ,表单提交处理逻辑始终是 view . 有关如何使用 WebOb API,参见 请求和响应对象"Query and POST variables" within the WebOb documentation . Pyramid 遵从WebOB的请求和响应实现,处理表单提交数据是请求实现的一个属性。了解Webob的请求API是了解如何处理表单提交数据的关键。

当您尝试在 Pyramid 查看。在表单提交中包含的数据中具有高阶(即非ASCII)字符非常常见,而UTF-8编码是Web上用于字符数据的最常见编码。因为unicode值比处理和存储字节串要理智得多, Pyramid 配置 WebOb 请求机器尝试将表单提交值隐式地从UTF-8解码为Unicode。当视图代码通过 request.paramsrequest.GETrequest.POST API(见) pyramid.request 有关这些API的详细信息)。

注解

许多人发现unicode和utf-8的区别令人困惑。Unicode是表示支持世界上大多数书写系统的文本的标准。但是,有许多方法可以将Unicode数据编码为字节,以便传输和存储。UTF-8是Unicode的一种特定编码,与ASCII向后兼容。这使得UTF-8非常方便地对数据进行编码,其中一大部分数据都是ASCII字符,这在Web上基本上是正确的。UTF-8也是URL的标准字符编码。

作为一个例子,我们假设下面的表单页面被提供给浏览器客户机,并且 action 某点 Pyramid 查看代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<html xmlns="http://www.w3.org/1999/xhtml">
  <form method="POST" action="myview" accept-charset="UTF-8">
    <div>
      <input type="text" name="firstname"/>
    </div>
    <div>
      <input type="text" name="lastname"/>
    </div>
    <input type="submit" value="Submit"/>
  </form>
</html>

这个 myview 在中查看代码 Pyramid 应用 must 期望返回的值 request.params 将是类型 str ,与类型相反 bytes . 以下内容适用于接受上述表格中的表格邮寄:

1
2
3
def myview(request):
    firstname = request.params['firstname']
    lastname = request.params['lastname']

为了使隐式解码可靠地工作,您应该确保将该发布到 Pyramid 视图显式定义了一个UTF-8字符集编码。这可以通过具有 ;charset=UTF-8 在其 Content-Type 标题;或者,如上面的形式,带有 accept-charset 属性,通知浏览器服务器希望使用UTF-8对表单内容进行编码。必须显式地执行此操作,因为所有已知的浏览器客户端都假定它们应该使用 Content-Type 随后提交表单时包含表单的响应的值。没有其他公认的方法来告诉浏览器客户端使用哪个字符集来编码表单数据。如果您没有显式指定编码,浏览器客户端将选择在提交表单数据之前以其默认字符集对表单数据进行编码,这可能不是服务器期望的UTF-8。如果请求包含以非UTF-8编码的表单数据 charset 是由视图代码处理的,当视图中访问的请求代码无法对表单数据中另一个字符集中编码的某些高阶字符进行解码时(例如,当 request.params['somename'] 被访问。

如果您正在使用 Response 类来生成响应,或者如果使用 pyramid.renderers.render_* 模板化API,UTF-8 charset 通过自动设置为默认值 Content-Type 标题。如果你返回 Content-Type 没有显式的头 charset ,请求将添加 ;charset=utf-8 拖车到 Content-Type 文本响应内容类型的标题值(例如, text/htmlapplication/xml )在渲染时。如果您使用自己的响应对象,则需要确保自己这样做。

可选视图可调用参数/调用约定

通常,视图可调用文件被定义为只接受一个参数: request . 但是,视图可调用可以交替定义为接受 two 位置参数:A context 作为第一个参数的资源和 request 作为第二个论点。

这个 contextrequest 传递给此样式中定义的视图函数的参数可以定义如下:

语境
这个 resource 通过树找到的对象 traversalURL dispatch .
请求
A Pyramid 表示当前wsgi请求的请求对象。

以下类型用作此样式中的视图可调用文件:

  1. 接受两个参数的函数: contextrequest ,例如:

    1
    2
    3
    4
    from pyramid.response import Response
    
    def view(context, request):
        return Response('OK')
    
  2. 类具有 __init__ 接受的方法 context, request 和A __call__ 不接受参数的方法,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from pyramid.response import Response
    
    class view(object):
        def __init__(self, context, request):
            self.context = context
            self.request = request
    
        def __call__(self):
            return Response('OK')
    
  3. 具有 __call__ 接受的方法 context, request ,例如:

    1
    2
    3
    4
    5
    6
    from pyramid.response import Response
    
    class View(object):
        def __call__(self, context, request):
            return Response('OK')
    view = View() # this is the view callable
    

这种类型的调用约定对 traversal 基于应用程序,其中上下文对象经常在视图可调用代码本身中使用。

无论使用哪种视图调用约定,视图代码始终可以通过 request.context .

将配置变量传递给视图

有关将变量从configuration.ini文件传递到视图的信息,请参见 部署设置 .

塔架-1.0型“控制器”调度

一个名为 pyramid_handlers (可从PYPI获得)提供 Pylons -样式“Controllers”,这是一种特殊的视图类,当应用程序使用 URL dispatch 仅仅。