Reputation: 506
After asking a previous question someone told me the organization of my application was weird, so I looked at other examples to see how I could handle what I want to do.
The clearest example I found is a school case of flask application. From what I understand:
The app
object is declared in the app module
Routes are declared in the routes module
The blueprint import the routes as I want
However in my application to answer some of the routes I need to access parameters that are defined in the app module (they are used before creating the app object).
How can I make these parameters accessible in the routes module?
I can't just import them from app since that would be a circular import.
I could use a constructor function like suggested in this question but considering the remarks to my previous question it seems like it is not the usual way to deal with this issue.
Upvotes: 0
Views: 3357
Reputation: 2079
following Steve's answer spirit, I got this working solution :
in routes.py
:
class Routes:
# constructor
def __init__(self, config: dict):
self.__config = config
# init_session
def init_session(self, type_response: str):
# using the config
config = self.__config
...
# authenticate_user
def authenticate_user(self):
# using the config
config = self.__config
...
In main.py
config={...}
# Flask app
app = Flask(__name__, template_folder="../templates", static_folder="../static")
# routes # routes
from routes import Routes
# class instance with needed parameters
routes = Routes(config)
# adjusting urls with routes
app.add_url_rule('/init-session/<string:type_response>', methods=['GET'],
view_func=routes.init_session)
app.add_url_rule('/authenticate-user', methods=['POST'],
view_func=routes.authenticate_user)
Upvotes: 1
Reputation: 101
It sounds like you might need to use class-based views.
The problem that you're facing is that you need values in your view functions when they run, but it's difficult to get them imported in your routes module where the functions are defined. You originally tried to solve this problem with your functions in a function (which, while perfectly valid, isn't very Python-y).
I would suggest creating a views.py
file and defining a class-based view (or you can call it routes.py
, it doesn't really matter):
from flask.views import View
class MyView(View):
methods = ['GET']
def __init__(self, param1, param2):
self.param1 = param1
self.param2 = param2
def dispatch_request(self):
return 'param1: {}\nparam2: {}'.format(self.param1, self.param2)
def add_routes(app, param1, param2):
# `param1` and `param2` will get passed to the view class constructor
app.add_url_rule('/', view_func=MyView.as_view('myview', param1, param2))
Then, in your server.py
file (or whatever you've called it), you can pass the app and the parameters to the add_routes
function:
from flask import Flask
from .views import add_routes
param1 = 'foo'
param2 = 'bar'
app = Flask(__name__)
add_routes(app, param1, param2)
add_routes
doesn't have to live in views.py
, it could live anywhere. Or, you could just get rid of it altogether if you don't have many routes:
from flask import Flask
from .views import MyView
param1 = 'foo'
param2 = 'bar'
app = Flask(__name__)
app.add_url_rule('/', view_func=MyView.as_view('myview', param1, param2))
Note that the class will be instantiated on each request, not just once. So you shouldn't do anything particularly intensive in the constructor (like reading a file).
Upvotes: 3