Adds caching support to Flask applications.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Function and view decorators that provide transparent caching capabilities for Flask applications. The @cached decorator caches view results based on request path, while @memoize caches function results based on arguments.
Cache Flask view functions and regular functions with intelligent key generation based on request context.
def cached(
timeout: Optional[int] = None,
key_prefix: str = "view/%s",
unless: Optional[Callable] = None,
forced_update: Optional[Callable] = None,
response_filter: Optional[Callable] = None,
query_string: bool = False,
hash_method: Callable = hashlib.md5,
cache_none: bool = False,
make_cache_key: Optional[Callable] = None,
source_check: Optional[bool] = None,
response_hit_indication: Optional[bool] = False
) -> Callable:
"""
Decorator for caching function results.
Parameters:
- timeout: Cache timeout in seconds (None uses default)
- key_prefix: Key prefix template, '%s' replaced with request.path
- unless: Function to bypass cache when returns True
- forced_update: Function to force cache update when returns True
- response_filter: Function to filter responses before caching
- query_string: Include query string in cache key
- hash_method: Hash function for key generation
- cache_none: Cache None values
- make_cache_key: Custom cache key generation function
- source_check: Include function source code in cache key
- response_hit_indication: Add 'hit_cache' header when cache is used
Returns:
Decorated function with caching behavior
"""Basic Usage:
from flask import Flask
from flask_caching import Cache
app = Flask(__name__)
cache = Cache(app)
# Cache view for 5 minutes
@app.route('/expensive-data')
@cache.cached(timeout=300)
def get_expensive_data():
# Expensive database query or API call
data = perform_expensive_operation()
return jsonify(data)
# Cache with custom key prefix
@app.route('/user/<int:user_id>/profile')
@cache.cached(timeout=600, key_prefix='user_profile_%s')
def user_profile(user_id):
profile = get_user_profile(user_id)
return render_template('profile.html', profile=profile)Advanced Usage:
# Cache with query string consideration
@app.route('/search')
@cache.cached(timeout=300, query_string=True)
def search():
query = request.args.get('q', '')
page = request.args.get('page', 1, type=int)
results = perform_search(query, page)
return jsonify(results)
# Conditional caching
def skip_cache_for_admin():
return current_user.is_admin if current_user else False
@app.route('/dashboard')
@cache.cached(timeout=60, unless=skip_cache_for_admin)
def dashboard():
return render_template('dashboard.html')
# Custom cache key generation
def make_user_cache_key():
return f"user_{current_user.id}_dashboard"
@app.route('/user-dashboard')
@cache.cached(timeout=300, make_cache_key=make_user_cache_key)
def user_dashboard():
return render_template('user_dashboard.html')Cache function results based on their arguments, enabling efficient memoization of expensive computations.
def memoize(
timeout: Optional[int] = None,
make_name: Optional[Callable] = None,
unless: Optional[Callable] = None,
forced_update: Optional[Callable] = None,
response_filter: Optional[Callable] = None,
hash_method: Callable = hashlib.md5,
cache_none: bool = False,
source_check: Optional[bool] = None,
args_to_ignore: Optional[List[str]] = None
) -> Callable:
"""
Decorator for memoizing function results based on arguments.
Parameters:
- timeout: Cache timeout in seconds
- make_name: Function to customize cache key name
- unless: Function to bypass cache when returns True
- forced_update: Function to force cache update when returns True
- response_filter: Function to filter results before caching
- hash_method: Hash function for key generation
- cache_none: Cache None values
- source_check: Include function source in cache key
- args_to_ignore: List of argument names to ignore in cache key
Returns:
Decorated function with memoization behavior
"""Basic Usage:
# Memoize expensive computation
@cache.memoize(timeout=3600)
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
# Memoize database queries
@cache.memoize(timeout=600)
def get_user_posts(user_id, include_drafts=False):
query = Post.query.filter_by(user_id=user_id)
if not include_drafts:
query = query.filter_by(published=True)
return query.all()
# Usage
result = fibonacci(50) # Computed and cached
result = fibonacci(50) # Retrieved from cache
posts = get_user_posts(123, include_drafts=False) # Cached separately from drafts=TrueAdvanced Usage:
# Ignore certain arguments in cache key
@cache.memoize(timeout=300, args_to_ignore=['current_time'])
def get_daily_stats(date, current_time=None):
# current_time is used for logging but not cache key
log_request(current_time)
return calculate_daily_stats(date)
# Custom function naming
def custom_name_func(func_name):
return f"analytics_{func_name}"
@cache.memoize(timeout=1800, make_name=custom_name_func)
def calculate_conversion_rate(campaign_id, date_range):
return perform_analytics_calculation(campaign_id, date_range)
# Class method memoization
class UserService:
@cache.memoize(timeout=600)
def get_user_permissions(self, user_id):
return database.get_user_permissions(user_id)
@cache.memoize(timeout=300)
@classmethod
def get_system_config(cls, config_name):
return database.get_system_config(config_name)Functions decorated with @cached and @memoize get additional cache management methods.
# Available on @cached decorated functions
decorated_function.uncached # Original undecorated function
decorated_function.cache_timeout # Current cache timeout
decorated_function.make_cache_key # Cache key generation function
# Available on @memoize decorated functions
decorated_function.uncached # Original undecorated function
decorated_function.cache_timeout # Current cache timeout
decorated_function.make_cache_key # Cache key generation function
decorated_function.delete_memoized # Function to clear this function's cacheUsage:
@cache.memoize(timeout=600)
def expensive_calculation(x, y):
return x ** y + complex_math(x, y)
# Call original function without caching
result = expensive_calculation.uncached(10, 3)
# Change timeout dynamically
expensive_calculation.cache_timeout = 1200
# Clear cached results for this function
expensive_calculation.delete_memoized()
# Generate cache key for inspection
cache_key = expensive_calculation.make_cache_key(expensive_calculation, 10, 3)Manual cache invalidation for decorated functions.
def delete_memoized(f: Callable, *args, **kwargs) -> None:
"""
Delete cached results for a memoized function.
Parameters:
- f: The memoized function
- args: Positional arguments (deletes cache for specific args)
- kwargs: Keyword arguments (deletes cache for specific args)
If no args/kwargs provided, deletes all cached results for the function.
"""
def delete_memoized_verhash(f: Callable, *args) -> None:
"""
Delete the version hash for a memoized function.
Forces regeneration of all cached results.
Parameters:
- f: The memoized function
- args: Additional arguments (rarely used)
"""Usage:
@cache.memoize(timeout=3600)
def get_user_profile(user_id):
return User.query.get(user_id).to_dict()
# Delete all cached profiles
cache.delete_memoized(get_user_profile)
# Delete cached profile for specific user
cache.delete_memoized(get_user_profile, 123)
# Force regeneration of all cached results (use carefully)
cache.delete_memoized_verhash(get_user_profile)
# Delete via function method
get_user_profile.delete_memoized() # All cached resultsOverride cache timeout dynamically using CachedResponse.
class CachedResponse(Response):
"""
Response wrapper that allows dynamic cache timeout override.
Attributes:
- timeout: Cache timeout in seconds for this specific response
"""
def __init__(self, response, timeout: Optional[int]): ...Usage:
from flask_caching import Cache, CachedResponse
@cache.cached(timeout=300)
def dynamic_content():
data = get_content()
# Cache VIP content longer
if data.get('is_vip'):
return CachedResponse(jsonify(data), timeout=3600)
# Cache regular content with default timeout
return jsonify(data)Install with Tessl CLI
npx tessl i tessl/pypi-flask-caching