I have been using flask_restful for a while in my project because I like separating my resources into different files for basic organization. Now I would like to add flask_caching and I ran into a (simple?) circular import issue
my project structure is like this
flask_api.py
-resources
--my_resource.py
--my_other_resource.py
--so_many_more_resources.py
The Endpoints of my_resources.py are added inside flask_api.py, where I'm also creating the flask_cache Cache object, as follows:
# flask_api.py
from flask import Flask
from flask_restful import Api
from flask_caching import Cache
from resources import my_resource
app = Flask(__name__)
cache = Cache(app, config={'sample config'})
api = Api(app)
api.add_resource(my_resource.GetStuff, '/api/v2/stuff/get')
# this file also runs the app
I am then (attempting to) import the cache into my_resource.py - where I'm using the @cache decorator
# resources/my_resource.py
from flask_api import cache
class GetStuff(Resource):
@cache.memoize(timeout=30)
def get():
return "Stuff"
but this causes the dreaded circular import issue.
I could sandwich all my resource imports below the cache = Cache(...)
line, above api.add_resource()
. However, this feels like a hacky code smell and makes for a very, very meaty sandwich. I'd much rather have them all at the top of the file.
Whats the correct way to resolve this problem? (hopefully, without overhauling large parts of the codebase)
tl;dr: flask_api creates cache and imports resources -> resources can't import cache from flask_api
Alright so, the easy fix was to move the cache generation into the __init__.py file within the resources folder
flask_api.py
-resources
--__init__.py
--my_resource.py
--my_other_resource.py
--so_many_more_resources.py
and initiating the cache without the "app" parameter, like so
# __init__.py
cache = Cache(config={'...'})
flask_api.py can then import it and do cache.init_app(app)
# flask_api.py
from resources import cache
cache.init_app(app)
and resources can import the cache from __init__.py
as well
# my_resource.py
from . import cache
class GetStuff(Resource):
@cache.memoize(timeout=30)
def get():
return "Stuff"
This doesn't cause a ton of structural changes for my flask app and allows me to import resources into flask_api without sandwiching them after app generation to avoid circular imports.
I hope this helps anyone else encountering similar problems.