Search code examples
pythonmongodbflaskpymongoflask-pymongo

Python Flask Pymongo global db object is returned as None


I am trying to create an API to fetch data from my Atlas MongoDB using Flask. I was following this tutorial https://www.mongodb.com/compatibility/setting-up-flask-with-mongodb

However I get the following Error when trying to get some data from my database:

  File "C:\Users\salad\PycharmProjects\crypto_project\crypto\db.py", line 59, in get_currencies
    total_num_currencies = db.prices.count_documents(pipeline[0])
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'prices'

this is how I create the global db:

def get_db():
    """Configuration method to return db instance"""

    # All database access is routed through the global “db” object initialising the PyMongo client.
    db = getattr(g, "coin_markets", None)  # is equivalent to g._database

    if db is None:
        # The special variable object “g” is used here to define the PyMongo database in the global application context.
        db = g.coin_markets = PyMongo(current_app).db

    return db

db = LocalProxy(get_db)

In my run.py I config the app to use my variable in .env which contains the connection string to my mongodb:

from crypto.factory import create_app

from crypto.credentials.creds import DB_CONNECTION


if __name__ == "__main__":
    app = create_app()
    app.config['DEBUG'] = True
    app.config['MONGO_URI'] = DB_CONNECTION

    app.run()

if I print app.config['MONGO_URI'] I get the connection string so I don't understand why I get NoneType.

if it helps I use a factory pattern to create the app:

import os

from flask import Flask, render_template
from flask.json import JSONEncoder
from flask_cors import CORS

from bson import json_util, ObjectId
from datetime import datetime, timedelta

from crypto.api.currencies import currencies_api_v1

def create_app():

    app = Flask(__name__)
    CORS(app)

    app.register_blueprint(currencies_api_v1)

    @app.route('/', defaults={'path': ''})
    @app.route('/<path:path>')
    def serve(path):
        return render_template('index.html')

    return app

Solution

  • So with rickhg12hs help the problem got solved. I didn't specify a database in my connection string that's why PyMongo(current_app).db was not working. If you don't want to add the database name to your connection string like me, you can use rickhg12hs suggestion PyMongo(current_app).cx['your_database_name']