如何将Flask-OpenID对象设为全局应用?
我在我的小练习应用中使用Flask-OpenID来处理用户登录。
首先要做的是创建一个openid对象,这个对象之后会用来装饰登录处理程序(还有其他一些功能):
oid = flask.ext.openid.OpenID(app, '/path/to/store')
@oid.loginhandler
def login():
...
@oid.after_login
def after_login():
...
不过,我想在应用的__init__.py
文件中初始化Flask-OpenID,但又想在其他文件中使用这个OpenId对象oid
,比如我的应用的views.py
文件和可能的其他文件。通常开发者是怎么做到的呢?Flask开发者一般是如何让像oid
这样的对象在整个应用中都能使用的呢?
在这个类似的问题中,SQLAlchemy对象被放到了models
模块中,但在应用设置时在其他地方初始化,这样做有点道理,因为db
对象是和模型紧密相关的。OpenID对象也遵循了同样的模式。但是我不想把oid
放在views.py
里;显然它不应该在那。那么我应该把它放在哪里呢?我能想到一些解决方案,但我想知道Flask开发者通常是怎么做的。以下是一些想法:
把
oid
放在__init__.py
里,并在那儿初始化它。那么在应用的其他部分怎么访问oid
呢?为与Flask-OpenID和Flask-Login相关的对象和方法创建一个
auth.py
文件。这样auth.oid
就可以在应用的任何地方使用。那我是不是要为每一个不直接关联的扩展都创建一个新文件?这样做是不是太麻烦了,还是说这是一个适合扩展和保持组织的方法?或者,创建一个单独的文件来存放所有这些小扩展对象,可能叫
globals.py
或exts.py
。这听起来有点尴尬和不太好。还是说大多数Flask应用最终都会有一个随机的地方来放这些其他需要找地方的东西?
1 个回答
这三种选择各有利弊(正如你已经发现的那样):
- 在
__init__.py
中创建auth
- 这样会导致你的视图和基础应用之间出现循环引用。虽然可以工作,但会让代码的组织变得更困难(因为移动两个本来无关的导入可能会导致错误)。 - 创建一个单独的模块来处理这个特定的功能 - 这样可以避免循环引用的问题,并且在大型项目中让结构更清晰(“哦,这里就是处理身份验证的代码所在”)。不过,对于一些小项目,如果有很多小扩展,可能会导致模块数量像Java那样激增。
- 创建一个单独的模块来初始化应用中使用的所有Flask扩展。这样也能避免循环引用的问题,并且可以防止小项目不必要地增加模块数量。然而,在大型项目中,这样的模块可能会变得非常复杂(“这里是配置身份验证、平面文件处理和错误处理的地方”)。
还有第四种选择 - 将 auth
添加到你的视图层,因为 你是如何进行身份验证的 是特定于你应用逻辑的(而不是你的领域模型,例如)。
我建议完全避免第一种选择(直接跳过“两个模块”阶段,进入“三个或更多模块阶段”的额外成本几乎可以忽略不计)。至于剩下的三种选择,哪一种适合你的项目,实际上是根据项目和开发者的具体情况而定的。