09. Caching
Caching is a process of storing frequently accessed data in a temporary storage area so that it can be quickly accessed when needed. Caching is a technique used to improve the performance of a web application. It works by storing the results of time-consuming operations in a temporary storage area, so that the next time the same operation needs to be performed, the results can be quickly retrieved from the cache instead of having to repeat the time-consuming operation.
Since our application is a small or toy application, I will implement caching on retrieving all categories and products in the cache. However, in a real-world large application, you cannot do so. Large applications typically have huge amounts of such data, which cannot be stored in cache memory. Cache memory is very small in size, so deciding what data to cache and what not to cache is a crucial task.
We will user Flask-Cache to implement caching on out flask application.
Installation
pip install Flask-Cache
Configuration
python filename=app.py
...
from flask_caching import Cache
...
cache = Cache(app) # [tl! add]
app.app_context().push()# [tl! add]
...
We are pushing the application context to make the cache available to all parts of the application and don't get out of context issues.
Usage
Let's cache all categories and products in the cache.
python filename=app.py
...
@app.route('/get/products', methods=['GET'])
@cache.cached(timeout=50, key_prefix="get_products")
def get_products():
try:
products = Product.query.all()
product_list = []
for new_product in products:
prod_data = {
'id': new_product.id,
'quantity': new_product.quantity,
'name': new_product.name,
'manufacture': new_product.manufacture,
'expiry': new_product.expiry,
'description': new_product.description,
'rpu': new_product.rpu,
'unit': new_product.unit,
# Assuming image is stored as a base64-encoded string
'image': base64.b64encode(new_product.image).decode('utf-8')
}
product_list.append(prod_data)
return jsonify(product_list), 200
except Exception as e:
return jsonify({'error': str(e)})
@app.route('/get/categories', methods=['GET'])
@cache.cached(timeout=50, key_prefix="get_category")
def get_categories():
try:
categories = Category.query.all()
categories_list = []
for category in categories:
cat = {
'id': category.id,
'name': category.name,
}
categories_list.append(cat)
return jsonify(categories_list)
except Exception as e:
return jsonify({'error': str(e)})
...
Now the entire list of products and categories will be cached for 50 seconds. If the cache has expired or does not exist, the lists will be fetched from the database and cached again. The key_prefix
argument is used to differentiate between different cache keys for different routes.
Note When using cached on a view, take care to put it between Flask’s @route decorator and your function definition. Example:
@app.route('/')
@cache.cached(timeout=50)
def index():
return 'Cached for 50s'
Note If you reverse both decorator, what will be cached is the result of @route decorator, and not the result of your view function.
Testing it out
You can see all the registered keys in redis-cli using this command:
bash
redis-cli
KEYS *
Commit the changes in the local repo using the following command:
git add .
git commit -m "added caching"