【问题标题】:How to cache a variable with Flask?如何使用 Flask 缓存变量?
【发布时间】:2020-10-09 22:00:18
【问题描述】:

我正在使用 Flask 构建一个 Web 表单,并希望用户能够输入多个条目,并让他们有机会在将数据发送到数据库之前使用撤消按钮对条目感到遗憾。我正在尝试使用Flask-Caching,但未能正确设置。

我已关注The Flask Mega-Tutorial 设置 Flask(这是我的第一个 Flask 应用程序)。

+---app
|   |   forms.py
|   |   routes.py
|   |   __init__.py
|   +---static
|   +---templates

我想知道我需要如何配置 Flask 应用程序才能基本上能够执行以下操作:

cache.add("variable_name", variable_data)
variable_name = cache.get("variable_name")
cache.clear()

在其中一个页面中(带有@app.route 装饰器的函数)?

在 app.init.py 我有:

from flask import Flask
from config import Config
from flask_caching import Cache

app = Flask(__name__)
app.config.from_object(Config)
cache = Cache(app, config={'CACHE_TYPE': 'simple'})

from app import routes

在 routes.py 我有:

from flask import current_app

当我尝试调用缓存时,我使用下面的代码。

current_app.cache.add("variable_name", variable_data)

我在尝试使用表单时得到以下错误:

AttributeError: 'Flask' object has no attribute 'cache'

我发现的几乎所有教程都只是在同一个模块中包含了应用声明和所有路由。但是当我在另一个模块中有路由时如何访问缓存?

【问题讨论】:

    标签: python flask caching flask-caching


    【解决方案1】:

    为了在routes.py 中使用cache 对象,您必须先导入它(从您创建它的位置,即app/__init__.py):

    from app import cache
    

    然后使用它:

    cache.add("variable_name", variable_data)
    

    【讨论】:

    • 谢谢!这行得通。没想到这个解决方案是周期性的,出于某种原因,我认为该应用程序会以某种方式更加“自我意识”,尤其是使用“import current_app”。
    【解决方案2】:

    1 客户端缓存(内置)

    • 所有会话数据作为 Cookie 存储在客户端。

    显式存储变量示例:username

    from flask import Flask, session, request 
    
    app = Flask(__name__)
    app.config["SECRET_KEY"] = "any random string"
    
    @app.route("/login", methods=["GET", "POST"])
    def login():
        if request.method == "POST":
            session["username"] = request.form["username"]
        # to get value use session["username"]
    

    2 服务器端缓存 - (Flask-Caching 包)

    显式存储变量示例:username

    from flask import Flask, request 
    from flask_caching import Cache
    
    app = Flask(__name__)
    app.config["SECRET_KEY"] = "any random string"
    app.config["CACHE_TYPE"] = "SimpleCache" # better not use this type w. gunicorn
    cache = Cache(app)
    
    @app.route("/login", methods=["GET", "POST"])
    def login():
        if request.method == "POST":
            cache.set("username", request.form["username"])
        # to get value use cache.get("username")
    

    如果是带有 gunicorn 的多线程服务器,我刚刚测试过最好的方法是 ['CACHE_TYPE'] = 'FileSystemCache' 采用 look here

    【讨论】:

      【解决方案3】:

      在从互联网上拼凑出很多东西之后,我终于得到了这个解决方案,用于在使用应用程序工厂功能构建的应用程序中使用 Flask-Caching 显式缓存数据。布局和应用工厂设置遵循 Flask 教程。

      (在我的特定用例中,我使用的是 Google 日历 API,并希望缓存为连接和身份验证而构建的服务以及查询结果。无需每次用户重新查询与页面交互。)

      我的烧瓶应用的简图:

      /.../mysite/
      |--- mysite_flask/
      |    |--- __init__.py   (application factory)
      |    |--- cache.py      (for the flask_caching extension)
      |    |--- site.py       (a blueprint, views, and related functions)
      

      __init__.py:

      from flask import Flask
      
      def create_app(test_config=None):
          # create and configure app as desired
          app = Flask(__name__, instance_relative_config=True)
          app.config.from_mapping(
              ...
          )
      
          # check whether testing and for instance folder
          ...
      
          # importing and initializing other blueprints and views
          ...
      
          # import site blueprint, views, and functionality
          from . import site
          app.register_blueprint(site.bp)
          app.add_url_rule('/', endpoint='index')
      
          # Extensions
          # import cache functionality
          from .cache import cache
          cache.init_app(app)
      
          return app
      

      缓存.py

      from flask_caching import Cache
      cache = Cache(config={'CACHE_TYPE': 'SimpleCache'})
      

      网站.py

      # Other required imports
      ...
      from .cache import cache
      
      bp = Blueprint('site', __name__)
      
      # other views and functions
      ...
      
      @bp.route('/book', methods=('GET', 'POST'))
      def book():
          # Connect to calendar or fail gracefully
          service = cache.get("service") # now the cache is available within a view
          if service is None: # service hasn't been added to cache or is expired
              try: # rebuild the service to connect to calendar
                  service = connectToCalendar() # uses google.oauth2 and googleapiclient.discovery
                  cache.set("service", service) # store service in cache
                  g.error = False
              except Exception as e:
                  flash(e)
                  g.error = True
                  return render_template('site/book.html') # jinja2 template that checks for g.error
      
          # remaining logic for the 'book' view
          ...
      
          # Cache results of queries
          if cache.get("week_{}".format(offset)) is None:
              # get new results
              week = getWeek(service)
              cache.set("week_{}".format(offset), week)
          else:
              week = cache.get("week_{}".format(offset))
      
          return render_template('site/book.html', <...arguments...>)
      

      【讨论】:

        猜你喜欢
        • 2014-01-27
        • 2014-01-20
        • 2015-04-15
        • 2017-12-04
        • 2013-09-04
        • 2019-02-22
        • 2017-06-05
        • 2011-10-26
        • 1970-01-01
        相关资源
        最近更新 更多