我用于在Django和gunicorn上开发Web应用程序。如何在Pyramid应用程序启动时间获取注册表()。设置?
在Django的情况下,Django应用程序中的任何应用程序模块都可以通过django.conf.settings获得部署设置。 “settings.py”是用Python编写的,所以任何设置和预处理都可以动态定义。
在gunicorn的情况下,有优先顺序的三个配置的地方,和一个设置注册表类实例相结合的。(但通常仅用于gunicorn不应用这些设置。)
- 命令行参数。
- 配置文件。 (如Django,编写于 Python,它可以有任意的 设置动态。)
- Paster应用程序设置。
在金字塔的情况下,根据金字塔文档,部署设置通常可以投入pyramid.registry.Registry()。设置。但它似乎只在存在pyramid.router.Router()实例时才被访问。 这是pyramid.threadlocal.get_current_registry()。设置返回None,在应用程序“main.py”的启动过程中。
例如,我通常在SQLAlchemy模型模块中定义一些业务逻辑,这需要部署设置如下。
myapp/models.py
from sqlalchemy import Table, Column, Types
from sqlalchemy.orm import mapper
from pyramid.threadlocal import get_current_registry
from myapp.db import session, metadata
settings = get_current_registry().settings
mytable = Table('mytable', metadata,
Column('id', Types.INTEGER, primary_key=True,)
(other columns)...
)
class MyModel(object):
query = session.query_property()
external_api_endpoint = settings['external_api_uri']
timezone = settings['timezone']
def get_api_result(self):
(interact with external api ...)
mapper(MyModel, mytable)
但是, “设置[ 'external_api_endpoint']” 引发一个TypeError异常,因为 “设置” 莫属。
我想到了两种解决方案。
定义一个可调用的,其接受在“models.py”和“main.py”,“配置”的说法用 配置()实例调用它。
myapp/models.py
from sqlalchemy import Table, Column, Types from sqlalchemy.orm import mapper from myapp.db import session, metadata _g = globals() def initialize(config): settings = config.get_settings() mytable = Table('mytable', metadata, Column('id', Types.INTEGER, rimary_key = True,) (other columns ...) ) class MyModel(object): query = session.query_property() external_api_endpoint = settings['external_api_endpoint'] def get_api_result(self): (interact with external api)... mapper(MyModel, mytable) _g['MyModel'] = MyModel _g['mytable'] = mytable
或者,换一个空模块 “应用程序/ settings.py”,并把后来设置了进去。
myapp/__init__.py
from pyramid.config import Configurator from .resources import RootResource def main(global_config, **settings): config = Configurator( settings = settings, root_factory = RootResource, ) import myapp.settings myapp.setting.settings = config.get_settings() (other configurations ...) return config.make_wsgi_app()
都和其他解决方案符合要求,但我觉得麻烦。我想要的是以下。
development.ini
定义,因为发展的粗略设置。ini只能有字符串类型常量。
[app:myapp] use = egg:myapp env = dev0 api_signature = xxxxxx
MYAPP/settings.py
定义了基于development.ini详细设置,东阳任意变量(类型)可以被设置。
import datetime, urllib from pytz import timezone from pyramid.threadlocal import get_current_registry pyramid_settings = get_current_registry().settings if pyramid_settings['env'] == 'production': api_endpoint_uri = 'http://api.external.com/?{0}' timezone = timezone('US/Eastern') elif pyramid_settings['env'] == 'dev0': api_endpoint_uri = 'http://sandbox0.external.com/?{0}' timezone = timezone('Australia/Sydney') elif pyramid_settings['env'] == 'dev1': api_endpoint_uri = 'http://sandbox1.external.com/?{0}' timezone = timezone('JP/Tokyo') api_endpoint_uri = api_endpoint_uri.format(urllib.urlencode({'signature':pyramid_settings['api_signature']}))
然后,其他模块可以通过 “进口myapp.settings” 获得任意部署设置。 或者,如果Registry()。设置优于“settings.py”,** settings kwargs和“settings.py”可以在“main.py”启动过程中结合并注册到Registry()。设置中。
无论如何,如何在启动时间获取设置dictionay?或者,金字塔轻轻地强迫我们将需要部署设置的每个代码放在“视图”可调参数中,这可以通过request.registry.settings随时获取设置字典?
编辑
谢谢,迈克尔和克里斯。
我终于明白为什么金字塔使用threadlocal变量(注册表和请求),特别是多个金字塔应用程序的注册表对象。
但是,在我看来,部署设置通常会影响可能定义特定应用程序的业务逻辑。这些逻辑通常放在一个或多个Python模块中,该模块可能不同于可轻松访问Config()或Registry()的“app/init .py”或“app/views.py”。 Python进程级别的Python模块通常是“全局”的。
也就是说,即使有多个金字塔应用程序共存,尽管它们有自己的threadlocal变量,但它们必须在Python进程级别共享那些可能包含特定于应用程序的somethings的“全局”Python模块。
因此,每个模块都可以通过应用程序“main”可调用或通过Registory()或Request()对象通过如此长的函数系列调用Configurator()来初始化callalbe通话可以满足通常的要求。但是,我猜金字塔的起源者(像我一样)或者开发者“拥有大量应用程序或许多设置”可能会感到麻烦,尽管这是金字塔设计。因此,我认为,Registry()。设置应该只有真正的“线程本地”变量,并且不应该具有正常的业务逻辑设置。开发人员应负责分离多个特定于应用程序的模块,类,可调用变量等。 截至目前,从我的观点来看,我会拿克里斯的答案。或者在“main”中调用,执行“execfile('settings.py',settings,settings)”并将其放入一些“全局”空间。
谢谢!我接受你的解决方案。原因在上面描述了“编辑”部分(请允许我编辑,因为 详细描述) – takaomag