-1

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
Samat
  • 43
  • 5
  • i think this can help https://stackoverflow.com/questions/41055265/attributeerror-nonetype-object-has-no-attribute – Tobok Sitanggang Mar 03 '23 at 22:45
  • 1
    Does your connection string include the database name? – rickhg12hs Mar 05 '23 at 07:03
  • @TobokSitanggang sorry I forgot to add that I am doing `db = LocalProxy(get_db)` and I think that could be causing the error but I don't really understand how this LocalProxy works. I am new to Flask and in the documentation it says "Accessing db will call get_db internally, in the same way that current_app works" Hence I don't think it is the same because I actually return db – Samat Mar 05 '23 at 20:11
  • @rickhg12hs thanks, that was the problem. I thought `db = g.coin_markets = PyMongo(current_app).db` is the same as `db = client.get_database('coin_markets')`. Just out of curiosity, is there a way for the client thing without adding the database name to the connection string? – Samat Mar 05 '23 at 21:59
  • 1
    @Samat I've never used `flask_pymongo`, but looking at the [source code](https://github.com/dcrosta/flask-pymongo/blob/master/flask_pymongo/__init__.py#L113-#L115), I'm wondering if `db = g.coin_markets = PyMongo(current_app).cx["your_database_name"]` might work. Or perhaps, `my_PyMongo = PyMongo(current_app); my_PyMongo.db = my_PyMongo.cx["your_database_name"]; db = g.coin_markets = my_PyMongo.db`. Let us know if you get it working by adding an answer. – rickhg12hs Mar 05 '23 at 23:48

1 Answers1

1

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']

Samat
  • 43
  • 5