请求和响应对象

备注

本章改编自 WebOb 文件,最初由伊恩·比金撰写。

Pyramid 使用 WebOb 包作为ITS requestresponse 对象实现。这个 request 对象,该对象传递给 Pyramid view 是一个实例, pyramid.request.Request 类,它是 webob.request.Request 。这个 responsePyramid view renderer 是一个实例, pyramid.response.Response 类的子类,它是 webob.response.Response 班级。用户还可以返回 pyramid.response.Response 如有必要,可直接从视图查看。

webob是一个独立于 Pyramid 一组独立的作者和一个完全独立的 set of documentation . Pyramid 向标准WebOB请求添加一些功能,这些功能记录在 pyramid.request API文档。

Webob为HTTP请求和响应提供对象。具体来说,它通过包装 WSGI 请求环境和响应状态、头列表和app-iter(body)值。

WebOB请求和响应对象为解析wsgi请求和形成wsgi响应提供了许多便利。Webob是一种表示“原始”WSGi请求和响应的好方法。但是,在本文档中,作为 Pyramid 通常不需要直接使用Webob的与wsgi相关的特性。这个 reference documentation 然而,显示了许多以这种方式创建请求和使用响应对象的示例。

请求

请求对象是 WSGI environ dictionary . 此字典包含每个头的键、描述请求的键(包括路径和查询字符串)、请求主体的类似文件的对象以及各种自定义键。您可以随时使用 req.environ .

请求对象的一些最重要和最有趣的属性如下。

req.method

请求方法,例如, GETPOST

req.GET

A multidict 查询字符串中的所有变量。

req.POST

A multidict 请求主体中的所有变量。只有当请求是 POST 这是一个表格提交。

req.params

A multidict 把所有的东西结合在一起 req.GETreq.POST .

req.body

请求正文的内容。它以字符串形式包含整个请求主体。当请求是 POST 那就是 not 表单提交或请求,如 PUT . 你也可以得到 req.body_file 对于类似文件的对象。

req.json_body

JSON解码了请求主体的内容。见 处理JSON编码的请求体 .

req.cookies

所有饼干的简单字典。

req.headers

所有标题的字典。这本词典不区分大小写。

req.urlvars and req.urlargs

req.urlvars 是与请求URL关联的关键字参数。 req.urlargs 是位置参数。这些是由如下产品设置的 RoutesSelector .

另外,对于标准HTTP请求头,通常有如下属性: req.accept_languagereq.content_lengthreq.user_agent . 这些属性公开了 解析 每个头的形式,无论解析有什么意义。例如, req.if_modified_since 返回A datetime 对象(如果未提供头,则为无)。

备注

完整的API文档 Pyramid 请求对象在中可用 pyramid.request .

由添加到请求的特殊属性 Pyramid

除了标准 WebOb 属性, Pyramid 向每个请求添加特殊属性: contextregistryrootsubpathtraversedview_namevirtual_rootvirtual_root_pathsessionmatchdictmatched_route . 这些属性在 pyramid.request.Request API文档。

URLs

除了这些属性之外,还有几种方法可以获取请求的URL及其部分。我们将显示示例URL的各种值 http://localhost/app/blog?id=10 ,安装应用程序的位置 http://localhost/app .

req.url

带有查询字符串的完整请求URL,例如, http://localhost/app/blog?id=10

req.host

URL中的主机信息,例如, localhost

req.host_url

主机的URL,例如, http://localhost

req.application_url

应用程序的URL(仅 SCRIPT_NAME 路径的一部分,而不是 PATH_INFO ),例如, http://localhost/app

req.path_url

应用程序的URL,包括 PATH_INFO ,例如, http://localhost/app/blog

req.path

网址包括 PATH_INFO 没有主机或方案,例如, /app/blog

req.path_qs

网址包括 PATH_INFO 以及查询字符串,例如, /app/blog?id=10

req.query_string

URL中的查询字符串,例如, id=10

req.relative_url(url, to_application=False)

提供相对于当前URL的URL。如果 to_application 为真,然后相对于 req.application_url .

方法

请求对象的方法记录在 pyramid.request.Request 但是你会发现你不会用很多。以下是一些可能有用的:

Request.blank(base_url)

基于给定的URL创建一个包含空白信息的新请求。这对于子请求和人工请求很有用。您也可以使用 req.copy() 复制现有请求或子请求 req.copy_get() 它复制请求,但始终将其转换为GET(这样子请求共享更安全)。

req.get_response(wsgi_application)

此方法使用此请求调用给定的wsgi应用程序,并返回 pyramid.response.Response 对象。您也可以将其用于子请求或测试。

文本(Unicode)

请求对象的大多数属性都是文本值。中的值 req.POSTreq.GETreq.paramsreq.cookies 将包含文本并假定使用UTF-8字符集生成。客户 can 用类似的符号表示字符集 Content-Type: application/x-www-form-urlencoded; charset=utf8 但是浏览器很少设置。可以使用重置现有请求的字符集 newreq = req.decode('utf-8') 或在实例化期间 Request(environ, charset='utf8') .

多重字典

WebOB请求的几个属性是多层次结构(例如 request.GETrequest.POSTrequest.params )multict是一个字典,其中一个键可以有多个值。最典型的例子是 ?pref=red&pref=bluepref 变量有两个值: redblue .

当你这样做的时候 request.GET['pref'] 你只能回去了 "blue" (最后一个值 pref )此返回的结果可能不是预期的,有时返回字符串,有时返回列表,可能是频繁出现异常的原因。如果你想要 all 返回值,使用 request.GET.getall('pref') . 如果你想确定 一个而且只有一个 使用价值 request.GET.getone('pref') ,如果的值为零或多个,则将引发异常 pref .

当你使用诸如 request.GET.items() 你会回来的 [('pref', 'red'), ('pref', 'blue')] . 将显示所有键/值对。同样地 request.GET.keys() 收益率 ['pref', 'pref'] . multict是元组列表上的一个视图;所有键都是有序的,所有值都是有序的。

多学科的API文档存在于 pyramid.interfaces.IMultiDict .

处理JSON编码的请求体

在 1.1 版本加入.

pyramid.request.Request.json_body 是返回 JSON -请求主体的解码表示。如果请求没有主体,或者主体不是正确的JSON编码值,那么访问该属性时将引发异常。

当您调用 Pyramid 例如,通过jquery的 $.ajax 函数,它可以用JSON编码的主体发送请求。

使用 request.json_body 相当于:

from json import loads
loads(request.body, encoding=request.charset)

下面介绍如何使用JavaScript构造Ajax请求 jQuery 它允许你使用 request.json_body 当请求发送到 Pyramid 应用:

jQuery.ajax({type:'POST',
             url: 'http://localhost:6543/', // the pyramid server
             data: JSON.stringify({'a':1}),
             contentType: 'application/json'});

当此类请求到达应用程序中的视图时, request.json_body 属性将在视图可调用主体中可用。

@view_config(renderer='string')
def aview(request):
    print(request.json_body)
    return 'OK'

对于上述视图,打印到控制台的内容如下:

{'a': 1}

对于奖励积分,这里有一点客户端代码,它将生成一个请求,该请求具有一个适合通过 request.json_body 使用Python的 urllib2 而不是Javascript Ajax请求:

import urllib2
import json

json_payload = json.dumps({'a':1})
headers = {'Content-Type':'application/json'}
req = urllib2.Request('http://localhost:6543/', json_payload, headers)
resp = urllib2.urlopen(req)

如果您正在执行跨源站资源共享(CORS),则标准要求浏览器执行飞行前HTTP选项请求。最简单的处理方法是添加一个 view_config 对于同一条路线, request_method 设置为 OPTIONS ,并在返回前设置所需的响应头。您可以找到响应头的示例 Access control CORS, Preflighted requests .

请求后清理

有时,当涉及数据库连接时,需要在请求结束时执行一些清理。

例如,假设您有 mypackage Pyramid 使用sqlachemy的应用程序包,您希望在每次请求后删除当前的sqlachemy数据库会话。将以下内容放入 mypackage.__init__ 模块:

 1from mypackage.models import DBSession
 2
 3from pyramid.events import subscriber
 4from pyramid.events import NewRequest
 5
 6def cleanup_callback(request):
 7    DBSession.remove()
 8
 9@subscriber(NewRequest)
10def add_cleanup_callback(event):
11    event.request.add_finished_callback(cleanup_callback)

注册 cleanup_callback 在请求开始时完成回调(通过 add_cleanup_callback 接收 pyramid.events.NewRequest 每个请求开始时的事件)将导致在请求处理结束时删除dbsession。请注意,在上面的示例中, pyramid.events.subscriber 装修工,装修工 pyramid.config.Configurator.scan() 必须针对您的 mypackage 应用程序初始化期间的包。

备注

这只是一个例子。特别是,没有必要 DBSession.remove 在从生成的应用程序中调用 Pyramid 因为这些都使用 pyramid_tm 包裹。清理工作由 DBSession.removepyramid_tm middleware 配置到应用程序中。

更多细节

有关请求对象API的更多详细信息如下。

  • pyramid.request.Request API文档

  • WebOb documentation <https://docs.pylonsproject.org/projects/webob/en/latest/index.html> ②A的所有方法和属性 webob.Request WebOB文档中的文档将与由 Pyramid .

响应

这个 Pyramid 响应对象可以导入为 pyramid.response.Response 。此类是 webob.reponse.Response 班级。该子类不添加或更改任何功能,因此WebOb响应文档也将与此类完全相关。

响应对象有三个基本部分:

response.status

响应代码加上原因消息,比如 200 OK . 要设置不带消息的代码,请使用 status_int ,即 response.status_int = 200 .

response.headerlist

所有标题的列表,比如 [('Content-Type', 'text/html')] . 有个不区分大小写的 multidict 在里面 response.headers 这也允许您访问这些相同的头文件。

response.app_iter

将生成响应内容的可ITable(如列表或生成器)。这也可以作为 response.body (字节) response.text (一个Unicode字符串,由 response.charsetresponse.body_file (像文件一样的物体;写在上面附加在 app_iter

对象中的其他所有内容通常都源于此基础状态。以下是一些亮点:

response.content_type

内容类型 not 包括 charset 参数。

典型用途: response.content_type = 'text/html' .

默认值: response.content_type = 'text/html' .

response.charset

这个 charset 内容类型的参数,它还通知 response.text . response.content_type_params 是所有参数的字典。

response.set_cookie(name, value, max_age=None, path='/', ...)

放饼干。关键字参数控制各种cookie参数。这个 max_age 参数是cookie的生存时间(秒)(也可以使用TimeDelta对象)。这个 Expires 键也将基于 max_age .

response.delete_cookie(name, path='/', domain=None)

从客户端删除cookie。这套 max_age 到0,cookie值到 '' .

response.cache_expires(seconds=0)

这使得响应在给定的秒数内可缓存,或者如果 seconds0 那么响应是不可缓存的(这也设置了 Expires 标题)。

response(environ, start_response)

响应对象是一个wsgi应用程序。作为一个应用程序,它根据您创建它的方式进行操作。它 can 如果通过,则执行条件响应 conditional_response=True 在实例化(或稍后设置该属性)时。它还可以执行头部和范围请求。

报头

与请求类似,大多数HTTP响应头都是作为属性提供的。这些是解析的,所以您可以执行以下操作 response.last_modified = os.path.getmtime(filename) .

详情见 webob.response API文档。

实例化响应

当然,大多数时候你只是想 make 反应。通常,响应的任何属性都可以作为关键字参数传递给类,例如:

1from pyramid.response import Response
2response = Response(body='hello world!', content_type='text/plain')

状态默认为 '200 OK' .

价值 content_type 默认为 webob.response.Response.default_content_type ,这就是 text/html . 您可以子类 pyramid.response.Response 并设置 default_content_type 覆盖此行为。

异常响应

以便于错误响应,如 404 Not Found ,模块 pyramid.httpexceptions 包含各种错误响应的类。这些包括无聊但适当的误差体。当在下面使用时,此模块公开的异常 Pyramid ,应从 pyramid.httpexceptions 模块。此导入位置包含子类和替换,这些子类和替换与 webob.exc 模块。

每个类都有名称 pyramid.httpexceptions.HTTP* 在哪里 * 是导致错误的原因。例如, pyramid.httpexceptions.HTTPNotFound 子类 pyramid.response.Response ,这样您就可以以相同的方式操作实例。一个典型的例子是:

1from pyramid.httpexceptions import HTTPNotFound
2from pyramid.httpexceptions import HTTPMovedPermanently
3
4response = HTTPNotFound('There is no such resource')
5# or:
6response = HTTPMovedPermanently(location=new_url)

更多细节

有关响应对象API的更多详细信息,请参见 pyramid.response 文档。有关异常响应的更多详细信息,请参见 pyramid.httpexceptions API文档。这个 WebOb documentation 也是有用的。