Caching and deletion of Flask-caching – pitfall avoidance guide

Basic usage

Flask-based applications will inevitably use Flask-cache (or Flask-cacheing, the two APIs are basically the same). It implements caching of function calls very elegantly through decorators. Decorators can be added directly to view functions or ordinary functions, similar to the following:

@app.route('/demo/student/all', methods=['GET'])
@cache.cached(timeout=600)
def get():
    students = Student.query.all()
    return response_ok(students)

(If the function has parameters and you want to cache different values ​​for different actual parameters, use _@cache.memerized _a decorator.)
After the function with the decorator is called for the first time, the return value will be cached within the cache validity period. Example The parameters in timeoutensure that the cache will expire after 600 seconds, and the function body will be called again to obtain the latest data.

view function cache control

But sometimes we need to control the update of this cache – for example, in the above example, every time a new student is added or student data is changed, the cache is refreshed without waiting for it to naturally time out. At this time, you need to explicitly call the delete function, for example:

del_res = cache.delete('/demo/student/all')

For the view function, the parameter of delete here is exactly equal to the path in the route. If the route comes from a superior blueprint, remember to bring the superior path.
If you want to specify the cache key, you can add the key_prefix parameter, similar to the following:

@app.route('/demo/student/all', methods=['GET'])
@cache.cached(timeout=600, key_prefix='res_student_all')
def get():
    ...

Note that the first pitfall is here: because there is a prefix in the name, you may think that it is the prefix of the key. When deleting, you will think about how to combine the parameter and the path; however, in fact, no combination is needed, the path is in This is no longer valid. Just use this key_prefix as a parameter when deleting:

del_res = cache.delete('res_student_all')

In fact, this key_prefix is ​​neither the prefix of the key nor the entire key. It should be called the suffix of the key more reasonably. The prefix of the real saved key (where it exists depends on the configuration, there can be memory cache SimpleCache, redis cache, etc.) is this It looks like: **flask_cache_**, and both path and key_prefix will be spliced ​​after the hash.

Common function cache control

simple function

If it is an ordinary function, use the @cache.memoize decorator, which also supports the timeout parameter, as follows:

@cache.memoize(timeout=60)
def get_number():
    return 5

Deleting memoize is more intuitive, just pass the function directly:

del_res = cache.delete_memoize(get_number)

If the function has parameters:

@cache.memoize(timeout=60)
def get_number(x):
    return 5 + x

Adding a parameter when deleting means only deleting the cache corresponding to this parameter. Not adding a parameter means deleting the cache corresponding to all actual parameter values ​​of the function:

del_res = cache.delete_memoize(get_number, 5 )     # Delete only the cache with x=5 
del_res = cache.delete_memoize(get_number)     # Delete all get_number caches

class function

At this time the second pit comes, what if this is a class function?

@cache.memoize(timeout=60)
class Calc:
    @classmethod
    def get_number(x):
        return 5 + x

When deleting, passing only the function name, or the function name plus parameters will not be deleted:

del_res = cache.delete_memoize(Calc.get_number, 5 )     # Unable to delete the cache of x=5 
del_res = cache.delete_memoize(Calc.get_number)     # Unable to delete all get_number caches

The official documentation says, “The class should be passed in as the first parameter.” This expression is very easy to misunderstand. In fact, it should be the first one in the parameter list, so it should be passed as follows:

del_res = cache.delete_memoize(Calc.get_number, Calc, 5 )     # Delete the cache of x=5 
del_res = cache.delete_memoize(Calc.get_number, Calc)     # Delete all get_number caches