flask-cache‘s key_prefix

13720 ワード

Question:
For example like this, is it necessary to use  key_prefix ?
@cache.cached(timeout=50, key_prefix='all_comments') def get_all_comments(): comments = do_serious_dbio() return [x.author for x in comments] cached_comments = get_all_comments()

In the document, it says that the  key_prefix 's default value is  request.path cache_key.: , what does  cache_key  mean, how can I use it? What does  key_prefix  do?
Answer:
First the  request.path  is everything (except params) after your  script_root . For example:
For a url like,  http://127.0.0.1:5000/users/login/ , request data is:
request.path is: /users/login/

For a url like in the example from the link above,  http://www.example.com/myapplication/page.html?x=y , request data is:
request.path is: /page.html

Q. What does cache_key mean, how can I use it?
The  cache_key  is the key that is used to access the particular cached value. As you know that the cache is a key-value store.
In Flask-Cache the  cache_key  is generated by the extension and we are not supposed to use it ourselves.
Q. What does key_prefix do? key_prefix  is used to generate the  cache_key  for a cached value. See  make_cache_key  sourceto see how exactly it is done.
Q. Is it necessary to use key_prefix?
Let's say you are calling  get_all_comments  from 2 different view functions, say  manage() , and  view() . And you don't specify a  key_prefix , while caching  get_all_comments  with  @cached .
The first time you view a post through  view  the  get_all_comments  output is cached with a default key like:  view/view  or  view/module/view , or whatever the value of  view/%s  is, where  %s  is  request.path .
Next when you manage a post through  manage , the  get_all_comments  output is not read from the cache, since the  cache_key  applied to get data from the cache has changed to  view/manage  and is not the old  view/view , because the request.path has now changed.
The whole point of caching  get_all_comments  here was to get the data from the cache whenever possible and not the db, but since the keys have changed between view functions the data is actually retrieved both the times from the db itself.
However in case you had specified a  key_prefix  like  all_comments , then the first time data is retrieved from the db, and the next time the  cache_key  is still  all_comments  and value is found, and data is accessed from the cache instead of db.
So when you have cases like the above it is obviously better to use a  key_prefix , in other cases when the function is always called from a single path/view function then it is ok to let the default one be used.
Note: The cache_key is generated/calculated for every request, see the source:
cache_key = decorated_function.make_cache_key(*args, **kwargs)

demo:
(pythonenv)[xluren@test Flask-Cache_for_function_02]$ tree -L  3
.
├── config.py
├── config.pyc
└── run.py

0 directories, 3 files

1.config file
(pythonenv)[xluren@test Flask-Cache_for_function_02]$ cat config.py
import os
class Config(object):
    DEBUG=True
    CACHE_TYPE = 'simple'
    SECRET_KEY = "d73b04b0e696b0945283defa3eee4538"
    BASE_DIR = os.path.abspath(os.path.dirname(__file__))  
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(BASE_DIR, 'app.db')
class MysqlConfig(Config):
    SQLALCHEMY_DATABASE_URI = 'mysql://hello:[email protected]:3306/sqlalchemy'
class MongoDBConfig(Config):
    MONGOALCHEMY_DATABASE="mydb"
    MONGOALCHEMY_SERVER="10.210.71.145"
    MONGOALCHEMY_PORT=8888
POST_PER_PAGE = 3 

2.run.py
(pythonenv)[xluren@test Flask-Cache_for_function_02]$ cat run.py 
from flask  import Flask
from flask.ext.cache import Cache
import random,time



app=Flask(__name__)
app.config.from_object("config.Config")
app.cache=Cache(app)


@app.cache.cached(timeout=10,key_prefix="hello")
def get_number():
    s=random.randint(0,100)
    return str(s)

'''
    @app.cache.cached(timeout=10,key_prefix="hello")
    add or remove the  deractor to see the function of  key_prefix
'''
def get_datetime():
    return time.ctime()

@app.route("/")
def main_index():
    return """<lu>
            <li>the datetime is {datetime}</li>
            <li>the number is {random_number}</li>
            </lu>""".format(
                datetime=get_datetime(),
                random_number=get_number()
            )

if __name__ == "__main__":
    app.run(host="0.0.0.0",debug=True)