【问题标题】:Sharing objects between view and application with Pyramid使用 Pyramid 在视图和应用程序之间共享对象
【发布时间】:2015-06-11 12:21:53
【问题描述】:

我正在尝试使用 Pyramid 为数据分析管道创建 Web 界面。我正在使用变形和滤锅制作表格。我一直在改编这个例子:

http://pyramid-tutorials.readthedocs.org/en/latest/humans/security/step02/

大部分工作在提交表单后完成,但有几个通用步骤只需运行一次。我可以在服务器启动时将一些内容加载到内存中,以便可以从视图中访问它们吗?

【问题讨论】:

    标签: python pyramid deform colander


    【解决方案1】:

    您可以在应用程序的主文件中定义一些模块级变量(或者可能在其他地方),然后根据您的要求通过导入它们来使用它们。

    我使用这种方法从环境变量中为 SQLAlchemy 创建数据库连接字符串等设置。

    默认情况下,一个模块在 Python 中只会被解析一次,所以你的模块级代码只会运行一次。

    更新 1

    假设金字塔项目的目录结构如下:

    .
    ├── __init__.py
    ├── models
    │   ├── __init__.py
    │   ├── meta
    │   │   ├── base.py
    │   │   ├── __init__.py
    │   │   ├── orm.py
    │   │   ├── schema.py
    │   │   ├── types.py
    │   ├── users.py
    ├── security.py
    ├── settings
    │   ├── database.py
    │   ├── email.py
    │   ├── __init__.py
    │   ├── redis.py
    │   ├── security.py
    ├── static
    │   ├── css
    │   │   └── main.css
    │   └── js
    │       ├── app.js
    │       ├── app-services.js
    │       ├── controllers
    │       │   └── excel_preview.js
    ├── templates
    │   ├── auth
    │   │   └── login.html
    │   ├── base.html
    │   ├── home.html
    ├── views
    │   ├── auth.py
    │   ├── home.py
    │   ├── __init__.py
    

    假设我们在settings/redis.py 中有以下代码:

    import os
    import redis
    
    
    def get_redis_client():
        # Read settings from environment variables
        redis_db_name = os.environ.get('REDIS_NAME')
        redis_host = os.environ.get('REDIS_HOST')
        redis_port = os.environ['REDIS_PORT']
    
        # create a redis connection
        redis_client = redis.StrictRedis(
            host=redis_host,
            port=redis_port,
            db=redis_db_name,
        )
    
        # return newly created redis connection
        return redis_client
    
    
    redis_client = get_redis_client()
    
    SOME_SETTING_STORED_IN_REDIS = redis_client.get('some_setting_stored_in_redis')
    

    您可以在任何地方使用这个SOME_SETTING_STORED_IN_REDIS 变量。如果您的应用名称是example_app,那么在example_app/views/home.py 中您可以这样使用它:

    from pyramid.view import view_config
    
    from example_app.settings.redis import SOME_SETTING_STORED_IN_REDIS
    
    
    def includeme(config):
        config.add_route('home', '/')
    
    
    @view_config(
        route_name='home',
        renderer='home.html',
        permission='authenticated'
    )
    def home_view(request):
    
        return {
            "some_setting": SOME_SETTING_STORED_IN_REDIS,
        }
    

    我认为您正在尝试实现类似的目标。

    【讨论】:

    • 谢谢,我是 Pyramid 的新手,所以我可能遗漏了一些明显的东西。如果我像这样在应用程序中设置全局:global foo foo = "this is a global" 当我尝试从视图中打印它时仍然出现错误:NameError: global name 'foo' is not defined 我注意到的一件事是应用程序和视图不相互导入明确地。我认为服务器使用装饰器识别要运行的视图块。
    • 我已经为你添加了一些示例代码。我使用了模块级变量而不是全局变量。
    • 谢谢!这个解决方案对我有用,虽然我花了一点时间才明白为什么。我想我现在在 Python 中的控制流要好一些。
    【解决方案2】:

    如果“只需要运行一次的东西”是指数据库连接、一些配置数据等 - 换句话说,在流程的生命周期中永远不会改变的东西,然后将它们定义为全局变量并重用整个应用程序都很好。示例:

    APP_TITLE = 'Data Analysis Pipeline using Pyramid'
    
    @view_config(...)
    def home_view(request):
        return "Welcome to %s" % APP_TITLE
    

    如果您正在考虑存储一些 全局状态 并在视图中重新使用它,那么这不是一个好主意。示例(不好,不要这样做):

    subscription_step = 1
    
    @view_config(...)
    def next_subscription_step(request):
        global subscription_step
        subscription_step += 1 
        return HTTPFound('/subscription/step_%s' % subscription_step)
    

    上面的代码似乎在本地可以为您工作,但是一旦有多个用户访问该应用程序,或者如果网络服务器产生另一个工作进程,或者如果网络服务器重新启动,或者一百万其他原因。

    【讨论】:

    • 好建议。我不需要跨视图更新数据,我只是将一些数据加载到内存中,以便每个视图都能看到。
    猜你喜欢
    • 1970-01-01
    • 2015-04-04
    • 2013-05-02
    • 1970-01-01
    • 2011-03-15
    • 2010-11-06
    • 1970-01-01
    • 2012-10-15
    相关资源
    最近更新 更多