我在OS X 10.7.3上使用Pyramid 1.3和AppEngine 1.6.4 SDK。我正在使用Python 2.7并且在app.yaml中有线程安全。
@view_config(route_name='manager_swms', permission='manager', renderer='manager/swms.jinja2')
def manager_swms(request):
"""Generates blobstore url and passes users swms in swms table"""
# generate url for any form upload that may occur
upload_url = blobstore.create_upload_url('/upload_swm')
user = get_current_user(request)
swms = DBSession.query(SWMS).filter_by(owner_id=int(user.id)).all()
return {
"analytics_id": analytics_id,
"user": get_current_user(request),
"upload_url": upload_url,
"swms": [(x.filename, x.blob_key) for x in swms]
}
class BlobstoreUploadHandler(object):
"""Base class for creation blob upload handlers."""
def __init__(self, *args, **kwargs):
self.__uploads = None
def get_uploads(self, field_name=None):
"""Get uploads sent to this handler.
Args:
field_name: Only select uploads that were sent as a specific field.
Returns:
A list of BlobInfo records corresponding to each upload.
Empty list if there are no blob-info records for field_name.
"""
if self.__uploads is None:
self.__uploads = {}
for key, value in self.request.params.items():
if isinstance(value, cgi.FieldStorage):
if 'blob-key' in value.type_options:
self.__uploads.setdefault(key, []).append(
blobstore.parse_blob_info(value))
if field_name:
try:
return list(self.__uploads[field_name])
except KeyError:
return []
else:
results = []
for uploads in self.__uploads.itervalues():
results += uploads
return results
@view_config(route_name='upload_swm', permission='manager')
class UploadHandler(BlobstoreUploadHandler):
''' Handles redirects from Blobstore uploads. '''
def __init__(self, request):
self.request = request
super(UploadHandler, self).__init__()
def __call__(self):
user = get_current_user(self.request)
for blob_info in self.get_uploads('file'):
new_swm = SWMS(
owner_id = int(user.id),
blob_key = str(blob_info.key()),
filename = blob_info.filename,
size = blob_info.size,
)
DBSession.add(new_swm)
DBSession.flush()
# redirect to swms page
return HTTPFound(location='/manager/swms')
在上面的代码中,manager_swms()生成一个页面,其中包含一个用于将文件上载到Blobstore的表单。表单工作正常,我可以看到blob在使用表单时出现在Blobstore中。然后从blobstore POST重定向到/ upload_swm,我成功获取BlobInfo详细信息并将它们放入SQL表中。所有这一切都很好,我想做的最后一件事就是重定向到第一页,这样可以在需要时上传另一个文件,我可以显示上传的文件列表。
根据Pyramid文档,我使用HTTPFound(location ='/ manager / swms')[原始页面网址]来尝试重定向但是我得到:
ERROR 2012-03-29 22:56:38,170 wsgi.py:208]
Traceback (most recent call last):
File "/Users/tim/work/OHSPro/var/parts/google_appengine/google/appengine/runtime/wsgi.py", line 196, in Handle
result = handler(self._environ, self._StartResponse)
File "lib/dist/pyramid/router.py", line 195, in __call__
foo = response(request.environ, start_response)
File "lib/dist/pyramid/httpexceptions.py", line 291, in __call__
foo = Response.__call__(self, environ, start_response)
File "lib/dist/webob/response.py", line 922, in __call__
start_response(self.status, headerlist)
File "/Users/tim/work/OHSPro/var/parts/google_appengine/google/appengine/runtime/wsgi.py", line 150, in _StartResponse
_GetTypeName(header[1]))
InvalidResponseError: header values must be str, got 'unicode'
INFO 2012-03-29 22:56:38,174 dev_appserver_blobstore.py:408] Upload handler returned 500
INFO 2012-03-29 22:56:38,193 dev_appserver.py:2884] "POST /_ah/upload/ahJkZXZ-cHJvdG8tc2NvaHNwcm9yGwsSFV9fQmxvYlVwbG9hZFNlc3Npb25fXxgTDA HTTP/1.1" 500 -
AppEngine显然反对HTTP标头中的unicode,但我没有做任何异常的AFAIK。如果我进入pdb并查看HTTPFound对象,标题是:
ResponseHeaders([('Content-Type', 'text/html; charset=UTF-8'), ('Content-Length', '0'), ('Location', '/manager/swms')])
为什么我会从这些中获得unicode问题?
答案 0 :(得分:2)
所以看起来你覆盖了appengine支持的webob,2.7 runtime.上的1.1.1和金字塔1.3取决于webob> = 1.2。这很可能是问题,因为Blobstore处理程序的东西让sdk保持在webob == 0.9,直到SDK 1.6.4发布。
FWIW,这个问题预计将由SDK 1。6。5(4月底)解决。我知道这个的唯一原因是因为我试图在2.7运行时被认为准备好供一般使用时解决所有这些废话,但SDK不支持它。有关详细信息,请参阅此issue。
如果可能的话,我建议用金字塔1.2运行它,我知道它在appengine上工作正常。并暂缓推迟到1.3几周。 :)
答案 1 :(得分:0)
另一个答案......添加str()可以解决问题,但不是根本原因。我花了几个小时试图弄清楚为什么一个特定的重定向引发了这个错误,而其他人没有,在注意到错误的重定向的URL缺少初始“/".
我不知道为什么这种情况 - 可能不完整的路径与完整路径的处理方式不同。但如果您遇到此错误,请尝试更改:
self.redirect('home.view')
为:
self.redirect('/home.view')