如何以最少的代码行数整合Pyramid 1.1和MongoDB
目标: 我想把Mongo DB和Pyramid 1.1的基本应用结合起来。
背景: 这个应用是根据一本书创建的(https://docs.pylonsproject.org/projects/pyramid/1.1/narr/project.html#creating-the-project),使用的基本命令是“paste create -t pyramid_starter”。
我参考了这篇食谱文章: https://docs.pylonsproject.org/projects/pyramid_cookbook/dev/mongo.html
问题: 似乎每当我在请求中添加MongoDB连接时,就会出现“内部服务器错误”。
我尝试了几篇文章,似乎我需要启动调试系统更多一些?有没有人找到简单的解决办法?
如果有专家能帮忙,这里有个异常信息。
Exception happened during processing of request from ('127.0.0.1', 53697)
Traceback (most recent call last):
File "virtualenv\lib\site-packages\paste-1.7.5.1-py2.7.egg\paste\httpserver.py", line 1068, in process_request_in_thread
self.finish_request(request, client_address)
File "C:\Python27\Lib\SocketServer.py", line 323, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Python27\Lib\SocketServer.py", line 639, in __init__
self.handle()
File "virtualenv\lib\site-packages\paste-1.7.5.1-py2.7.egg\paste\httpserver.py", line 442, in handle
BaseHTTPRequestHandler.handle(self)
File "C:\Python27\Lib\BaseHTTPServer.py", line 343, in handle
self.handle_one_request()
...
File "C:\Python27\lib\site-packages\pyramid_debugtoolbar-0.8-py2.7.egg\pyramid_debugtoolbar\panels\__init__.py", line 24, in render
return render(template_name, vars, request=request)
File "virtualenv\lib\site-packages\pyramid-1.2a1-py2.7.egg\pyramid\renderers.py", line 69, in render
return helper.render(value, None, request=request)
File "virtualenv\lib\site-packages\pyramid-1.2a1-py2.7.egg\pyramid\renderers.py", line 418, in render
result = renderer(value, system_values)
File "C:\Python27\lib\site-packages\pyramid_jinja2-1.1-py2.7.egg\pyramid_jinja2\__init__.py", line 277, in __call__
return self.template.render(system)
File "C:\Python27\lib\site-packages\jinja2-2.6-py2.7.egg\jinja2\environment.py", line 894, in render
return self.environment.handle_exception(exc_info, True)
File "C:\Python27\lib\site-packages\pyramid_debugtoolbar-0.8-py2.7.egg\pyramid_debugtoolbar\panels\templates\request_vars.jinja2", line 110, in top-level template code
<td>{{ value|escape }}</td>
File "virtualenv\lib\site-packages\markupsafe-0.15-py2.7.egg\markupsafe\_native.py", line 20, in escape
return s.__html__()
File "virtualenv\lib\site-packages\pymongo-2.0.1-py2.7-win-amd64.egg\pymongo\collection.py", line 1156, in __call__
self.__name)
TypeError: 'Collection' object is not callable. If you meant to call the '__html__' method on a 'Database' object it is failing because no such method exists.
3 个回答
这个错误的意思是你在尝试调用一个方法(html),但是在数据库实例中并不存在这个方法。
>>> conn = Connection()
>>> db = conn.mydb
>>> col = db.mycoll
>>> col = db.mycoll()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/virtualenvs/myenv/lib/python2.7/site-packages/pymongo-2.0-py2.7-macosx-10.6-x86_64.egg/pymongo/collection.py", line 1156, in __call__
self.__name)
TypeError: 'Collection' object is not callable. If you meant to call the 'mycoll' method on a 'Database' object it is failing because no such method exists.
如果你没有修改代码,那么可能是markupsafe这个库里有个bug,它试图在数据库实例中调用html()这个方法。
s.__html__()
另一个可能的解决办法是,在你的配置文件中使用 'debugtoolbar.panels' 设置来禁用 request_vars 面板(这个面板正是导致问题的原因):
[app:main]
.. other stuff ...
debugtoolbar.panels =
pyramid_debugtoolbar.panels.versions.VersionDebugPanel
pyramid_debugtoolbar.panels.settings.SettingsDebugPanel
pyramid_debugtoolbar.panels.headers.HeaderDebugPanel
# pyramid_debugtoolbar.panels.request_vars.RequestVarsDebugPanel
pyramid_debugtoolbar.panels.renderings.RenderingsDebugPanel
pyramid_debugtoolbar.panels.logger.LoggingPanel
pyramid_debugtoolbar.panels.performance.PerformanceDebugPanel
pyramid_debugtoolbar.panels.routes.RoutesDebugPanel
pyramid_debugtoolbar.panels.sqla.SQLADebugPanel
Pymongo中的Database
和Collection
对象会对__getattr__
做出响应,这样可以提供更友好的接口,让你可以写出像下面这样的代码:
db.foo.bar.find(...)
任何对__getattr__
的调用都会成功,但不幸的是,这让一些库感到困惑,因为它们期望某些属性是可以调用的(Pymongo的Collection
对象是不可调用的,除了会抛出你上面看到的那个异常)。
在我的Pyramid项目中,我只在资源内部使用数据库,这样可以防止在视图或其他代码的模块级别引用数据库或集合。这样做还有一个额外的好处,就是能够很好地实现关注点分离,让资源负责数据库操作,而视图只负责将这些操作的结果显示在模板中。