Home > Mobile >  How to use Flask app config while the app is being created (using an app factory)?
How to use Flask app config while the app is being created (using an app factory)?

Time:07-14

Suppose I have something like this in app/models.py:

from flask import current_app as app
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.sql import func

db = SQLAlchemy()

class LoginLink(db.Model):
    ...
    expiration_date = db.Column(
        db.DateTime(timezone=True), nullable=False,
        server_default=func.now()   str(app.config["LOGIN_LINK_EXP_TIME"])  # Error here!!!
    )

And this in app/__init__.py:

from flask import Flask
from config import CONFIG_OBJECT

def create_app(config_name):

    app = Flask(__name__)
    app.config.from_object(CONFIG_OBJECT[config_name])

    from app.models import db
    db.init_app(app)
    db.create_all(app=app)

    return app

Finally, this is my config.py:

from datetime import timedelta

CONFIG_OBJECT = {
    "dev": "config.DevConfig",
    "prod": "config.ProdConfig"
}

class Config:
    ...

class DevConfig(Config):
    LOGIN_LINK_EXP_TIME = timedelta(seconds=30)

class ProdConfig(Config):
    LOGIN_LINK_EXP_TIME = timedelta(minutes=30)

I tried to use app.app_context() everywhere (believe me) and I'm still getting this error:

RuntimeError: Working outside of application context.

I'm just trying to do the following: in a development environment I want the login links to expire in 30 seconds (for testing and demonstration purposes), but login links will last 30 minutes in a production environment.

How to accomplish this using different config environments?

Note: this is intended to be a generic question.

CodePudding user response:

I think I had a misconception about application factories. We have the following from the Flask documentation:

The downside is that you cannot use the application object in the blueprints at import time. You can however use it from within a request.

Additionally:

It’s preferable to create your extensions and app factories so that the extension object does not initially get bound to the application.

What is in bold is what I was doing wrong: using the application object outside a request and bounding the extension to the application.

Therefore, I only see two solutions:

  1. Use the app.config object (or dict) only within requests (the best IMHO).
  2. Don't include configs that require to be used outside of requests in the app.config object (although this may complicate testing a bit).
  • Related