我的假设是正确的请求对象不是保证的结果,但我想确切地知道为什么不建议这样做,推荐的方法是从视图函数将请求对象传递到管道中。
2 回答
在请求对象到达视图后,建议您不要将“原样”传递给任何非 Web 特定的代码。任何处理数据库等的代码都不应该与金字塔的请求概念相结合。这种模式在 Pyramid 中更容易遵循,因为它避免了全局请求对象。
请求对象包含有关为什么调用视图的所有内容,并且与该对象耦合的代码比必要的多,这将导致您在管道中进一步编写可能做“太多”的函数。
我同意 Michael Merickel 的说法,但是我有很多遗留的 Pylons 应用程序已经被移植,并且需要在很多不同的代码中访问请求对象。
为了实现这一点,我几乎所有“面向网络”的函数都期望请求作为它们的第一个参数。我说几乎所有,因为有些没有。不是因为我不希望它们这样做,而是因为我还没有将它们移植到这个范例中。有一些模块没有与网络耦合,并且以其他方式命名和构造。[诸如文本处理之类的东西,由基于非金字塔的应用程序用于我的项目] 但是任何可能对请求起作用或与请求交互的东西——无论我目前是否将请求作为第一个参数需要它。
我的代码不标准的原因是我没有听像 Michael 这样的人,我仍然使用 get_current_request ......直到我开始遇到问题并理解他们警告我的内容——所以我一直我可以零零碎碎地修理东西。
让我远离使用 get_current_request() 的两个主要因素是:
当我想要传递请求时:单元测试。我来自 Pylons,在那里我们拥有全局
g
和c
对象。我真的很喜欢他们的便利。然后我尝试编写单元测试,这简直是一场噩梦。你经常不得不重写代码来阻塞一个请求对象。当我想要请求时:并非所有内容都与网络耦合。在某个项目中,我有几个守护进程通过 Twisted 框架运行定期工作。他们处理大量相同的数据并共享一些任务。我还有迁移脚本、crontabs 等。如果这些需要与 Pyramid 交互,我必须在重复项目中维护相同的功能。
所以我的方法是创建与金字塔紧密耦合并需要请求对象的库的一部分,以及与金字塔完全不可知的库的另一部分。
我的金字塔请求对象中有很多有用的东西——标头、会话、数据库连接等。这是一个非常方便的地方来存储面向“请求”的数据。每当有非金字塔系统可能使用的任务时,我都会这样实现它:
- 真正的函数位于 lib.universal 中,并且需要像 'dbSession' 这样的参数
- 如果需要,我还会创建一个位于 lib.pyramid 中的包装函数,并且只包装通用——从“请求”传入相关内容
他是一个简单而愚蠢的例子:
lib.universal
from ... import model
def get_user_by_id( dbSession , id , permissionsObject ):
if not validate_permissions( permissionsObject ):
raise ValueError('Not allowed')
return dbSession.query( model.User ).filter( id=id ).first()
lib.pyramid
from .. import universal
def get_user_by_id( request , id ):
return universal.get_user_by_id( request.dbSession , id , request.permissionsObject )