Anne Aunyme
Anne Aunyme

Reputation: 506

What is the intended way to pass a parameter to a flask blueprint?

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:

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

Answers (2)

Serge Tahé
Serge Tahé

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

Steve H
Steve H

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

Related Questions