8

my source code has this structure:

main.py:

from flask import Flask, g
app = Flask(__name__)
with app.app_context():
    g.my_db = PostgreSQL()
    app.register_blueprint(my_app, url_prefix="/my_app")

my_app.py:

from flask import Blueprint, g
my_app = Blueprint("my_app", __name__)
@my_app.route("/")
def index():
    return g.my_db.fetch_all()   <<< ERROR

but it shows this error:

AttributeError: '_AppCtxGlobals' object has no attribute 'my_db'

Even when I try to use g outside of app context, it shows this error:

RuntimeError: Working outside of application context.

So how to set and access to global variables in Flask?

mortymacs
  • 3,456
  • 3
  • 27
  • 53

2 Answers2

4

This happens because the data are lost when the context (with app.app_context()) ends (doc).

Inside the context, everything is ok :

from flask import Flask, g
app = Flask(__name__)
with app.app_context():
    g.my_db = 'database ok'
    print(g.my_db)

# >>> this prints 'database ok'

But outside, you cannot access the attribute :

from flask import Flask, g
app = Flask(__name__)
with app.app_context():
    g.my_db = 'database ok'

print(g.my_db)

# >>> this throws RuntimeError: Working outside of application context

even if you create a new context:

from flask import Flask, g
app = Flask(__name__)
with app.app_context():
    g.my_db = 'database ok'

with app.app_context():
    print(g.my_db)

>>> this throws AttributeError: '_AppCtxGlobals' object has no attribute 'my_db'

Your best call should be to declare the database object before the context, and then import it. Or maybe you can create it directly inside my_app.py where you need it ?

PRMoureu
  • 12,817
  • 6
  • 38
  • 48
  • Thanks, I've updated my question. would you please take an example? – mortymacs May 08 '18 at 12:40
  • i don't know the structure of your project, where do you need the database object, only in your module `my_app` ? – PRMoureu May 08 '18 at 12:53
  • In all modules (apps) of project. – mortymacs May 08 '18 at 12:55
  • 1
    it's hard to tell more to avoid circular imports nightmares. Don't store the database object inside `g`. For example you can create it inside the `__init__.py` of the apps root folder (if you have one). The code of your question is incomplete to reproduce and improve the structure you're using exactly. – PRMoureu May 08 '18 at 13:46
2

g isn't persistent in the way you're trying to use it. Write a function to create a connection each time you need it. Preferably use a database extension like Flask-SQLAlchemy to manage connections for you.

db.py:

import <postgresql dependencies>

def get_db():
   db = PostgreSQL()
   # config here
   return db

main.py:

from flask import Flask

app = Flask(__name__)
app.register_blueprint(my_app, url_prefix="/my_app")

my_app.py:

from flask import Blueprint, g
from db import get_db

my_app = Blueprint("my_app", __name__)

@my_app.route("/")
def index():
    db = get_db()
    data = db.fetch_all()
    db.close()
    return data
Gianfranco P.
  • 10,049
  • 6
  • 51
  • 68
Ali Yılmaz
  • 1,657
  • 1
  • 11
  • 28