Kundan
Kundan

Reputation: 590

How do I pass application context to a child function in flask?

Here is the project Structure.

|-- a_api/
|    |- a1.py
|
|-- b_api/
|    |-b1.py
|
|-- c_api/
|    |-c1.py
|    |-c2.py
|
|-- utils/
|    |-db.py
|
|-- main.py

db.py connects to mongo and stores connection in g from flask.


from flask import g
from pymongo import MongoClient

mongo_db = 'mongo_db'

def get_mongo_db():
    """Function will create a connection to mongo db for the current Request

    Returns:
        mongo_db: THe connection to Mongo Db
    """
    if mongo_db not in g:
        print('New Connection Created for mongo db')
        mongo_client = MongoClient('the_url')

        # Store the Client
        g.mongo_db = mongo_client
    else:
        print('Old Connection reused for mongo db')
    # Return The db
    return g.mongo_db['db_name']
  1. main.py calls two functions a1.py and b1.py
  2. for a1: it interacts directly with the db.py file and updates data, this happens without any error and task is completed successfully.
  3. for b1: it first calls c1 in a separate process, which used db.py and updates data - but in this case an error is thrown set up an application context with app.app_context()

How do I pass the application context to db.py when it is called from c1, which is called from b1?

How Do I create a single connection point to mongodb and use it across all requests or process in flask?

Traceback (most recent call last):
  File "C:\Users\kunda\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py", line 315, in _bootstrap
    self.run()
  File "C:\Users\kunda\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "W:\xx\offers_api\offer_ops.py", line 60, in update_offer
    response = aser(id=id, d=d)
  File "W:\xx\offers_api\offer_ops.py", line 86, in aser
    x = get_mongo_db()
  File "W:\xx\utils\db.py", line 13, in get_mongo_db
    if mongo_db not in g:
  File "C:\Users\kunda\AppData\Local\Programs\Python\Python310\lib\site-packages\werkzeug\local.py", line 278, in __get__
    obj = instance._get_current_object()
  File "C:\Users\kunda\AppData\Local\Programs\Python\Python310\lib\site-packages\werkzeug\local.py", line 407, in _get_current_object
    return self.__local()  # type: ignore
  File "C:\Users\kunda\AppData\Local\Programs\Python\Python310\lib\site-packages\flask\globals.py", line 40, in _lookup_app_object
    raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().  See the
documentation for more information.

Upvotes: 0

Views: 672

Answers (1)

Adrian Kurzeja
Adrian Kurzeja

Reputation: 833

Try something like this:

from flask import g
from pymongo import MongoClient

# import main flask app
from X import app

mongo_db = 'mongo_db'

def get_mongo_db():
    """Function will create a connection to mongo db for the current Request

    Returns:
        mongo_db: THe connection to Mongo Db
    """
    # if circular dependency error try importing app here
    from X import app
    with app.app_context():
        if mongo_db not in g:
            print('New Connection Created for mongo db')
            mongo_client = MongoClient('the_url')

            # Store the Client
            g.mongo_db = mongo_client
        else:
            print('Old Connection reused for mongo db')
        # Return The db
        return g.mongo_db['db_name']

Upvotes: 1

Related Questions