简体   繁体   English

如何从 Flask 的方法路由中访问 c​​ontext_processor?

[英]How do I access a context_processor from within a method route in Flask?

I'd like to setup variables available to both my views and my methods without polluting the request object in a before_request decorator.我想设置对我的视图和方法都可用的变量,而不会污染 before_request 装饰器中的请求对象。

Context processors seems like a nice way to do this however, I can't figure out how to actually access them from within my methods.上下文处理器似乎是一种很好的方法,但是我不知道如何从我的方法中实际访问它们。

The best solution I have come up with is to memoize the context function so that it doesn't get called twice, once by me in my method and then again when Flask injects it into the template.我想出的最好的解决方案是记住上下文函数,这样它就不会被调用两次,一次是在我的方法中被我调用,然后是在 Flask 将它注入模板时再次调用。

However, this will cache the method for all future requests and I only want it cached per request.但是,这将为所有未来的请求缓存该方法,我只希望每个请求都缓存它。

Here is my working example这是我的工作示例

from functools import cache

@app.context_processor
@cache
def setup_context():
  return {
    'planet': db.query('select planet from planets order by random()').first() 
  }

@app.route("/")
def index():
   ctx = setup_context()
   if ctx['planet'] == 'pluto':
      return redirect('/pluto-is-not-a-planet')
   return render_template('planet_greeting.html')
   

Any ideas on how to accomplish this without using functools.cache?关于如何在不使用 functools.cache 的情况下完成此操作的任何想法?

There may be a more elegant way to do this but here is what I have come up with so far.可能有一种更优雅的方式来做到这一点,但这是我迄今为止提出的。

The basic idea is to use the extensions pattern and create an object "Current" that the app gets passed to.基本思想是使用扩展模式并创建应用程序传递给的对象“当前”。

I can then use properties on this object to access the _app_ctx_stack as well as populate templates with context variables using the context_processor hook.然后,我可以使用该对象上的属性来访问 _app_ctx_stack 以及使用 context_processor 钩子使用上下文变量填充模板。

This approach will allow me to have templates that don't use "g" and a nice object to work with in my routes.这种方法将允许我拥有不使用“g”的模板和一个可以在我的路线中使用的好对象。

from flask import (
    Flask, current_app, _app_ctx_stack,
    render_template as template
)
from random import shuffle

planets = ['earth', 'pluto', 'mars']

class Current(object):
    def __init__(self, app=None):
        self.app = app
        self.app.context_processor(self.context_processor)
        
    def context_processor(self):
        return _app_ctx_stack.top.__dict__

    @property
    def planet(self):
        ctx = _app_ctx_stack.top
        if not hasattr(ctx, 'planet'):
            shuffle(planets)
            ctx.planet = {
                'name': planets[0]
            }
        return ctx.planet

app = Flask(__name__)
current = Current(app)

@app.route("/")
def index():
    if current.planet['name'] == 'pluto':
        return "Pluto is not a planet!"

    return template("planet.html")
    
if __name__ == '__main__':
    app.run(debug=True)

And in my template在我的模板中

{%# in my template %}
The planet is {{ planet.name }}!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM