Flask-Pymongo DB is returning as None - python

I am trying create a webapp with Flask-Pymongo, but it is saying that my database does not exist.
This is my __init__.py:
import os
from flask import Flask
from flask_pymongo import PyMongo
mongo = PyMongo()
def init_app():
app = Flask(__name__)
app.config.from_pyfile('config.py')
mongo.init_app(app)
with app.app_context():
from temp.routes.stage_routes import stage_route
app.register_blueprint(stage_route)
return app
This is my db.py (temp is the top level directory)
from temp.__init__ import mongo
db = mongo.db
and this is one of my blueprints with routes to query the database
from flask import Blueprint
from temp.db import db
stage_route = Blueprint('stage_route', __name__, url_prefix='/stages')
#stage_route.route('/')
def home():
return 'This is the home page for the stage blueprint'
#stage_route.route('/all')
def all():
stage = db.stages.find() # This is where the error is
print(stage)
For some reason I get the error saying that "NoneType does not have attribute 'stages'" because it is saying that the db variable is none. I can't figure out why this is is happening since the database and the collection does exist and the MONGO_URI string is loaded from the config file. I can see that it is connecting on the mongodb side, but i'm assuming it has something to do with my create_app() function in the init.py file. Do you see something that I am missing? Any help would be appreciated

The code is missing the connection URI string, as mentioned in the documentation -
from flask import Flask
from flask_pymongo import PyMongo
app = Flask(__name__)
# The missing URI
app.config["MONGO_URI"] = "mongodb://localhost:27017/myDatabase"
mongo = PyMongo(app)

Related

Flask SQLALCHEMY_DATABASE_URI is not defined

I am having a problem setting up the skeleton of my Flask API, where I am getting an error regarding the URI for my database.
I have it set up like this
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlite3 import Connection as SQLite3Connection
from datetime import datetime
from sqlalchemy import event
from sqlalchemy.engine import Engine
from flask import Flask, request, jsonify
app = Flask(__name__)
app.config[SQLALCHEMY_DATABASE_URI] = "sqlite:///sqlitedb.file"
app.config[SQLALCHEMY_TRACK_MODIFICATIONS] = 0
but I am getting the error in my IDE that [SQLALCHEMY_DATABASE_URI] is not defined and I also get the same error when trying to execute the program.
The modules import fine, so I'm not sure what I'm missing.
Edit: RESOLVED. I didn't have quotes around my config dictionary entries.
From the docs:
The config is actually a subclass of a dictionary and can be modified
just like any dictionary
this is how you modify app.config:
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///sqlitedb.file"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = 0
A crucial step is how SQLAlchemy gets informed of configuration. That'll look something like:
app = Flask(__name__)
# ... configuration
db = SQLAlchemy()
db.init_app(app)

What should I do with SQLAlchemy NameError: Name 'db' is not defined

I am building a web app with Flask and SQLAlchemy. I can't seem to find out the reason for this error NameError: name'db' is not defined Would really appreciate your help.
from flask import Flask, render_template
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
db=SQLAlchemy()
app=Flask(__name__)
#create a function that creates a web application
# a web server will run this web application
def create_app():
app.debug=True
app.secret_key='BetterSecretNeeded123'
#set the app configuration data
app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///bcib.sqlite'
#initialize db with flask app
db.init_app(app)
bootstrap = Bootstrap(app)
#importing modules here to avoid circular references, register blueprints of routes
from . import views
app.register_blueprint(views.bp)
#from . import admin
#app.register_blueprint(admin.bp)
return app
#app.errorhandler(404)
# inbuilt function which takes error as parameter
def not_found(e):
return render_template("404.html")
#app.errorhandler(500)
def internal_error(e):
return render_template("500.html")
When I try to input db.session.add(c1) in my terminal the error occurs
File "<stdin>", line 1, in <module>
NameError: name 'db' is not defined
Here the specific documentation : flask documentation
There is two ways to init the db :
you can binding the instance to a very specific Flask application like this
app = Flask(__name__)
db = SQLAlchemy(app)
you can create the object once and configure the application later to support :
db = SQLAlchemy()
def create_app():
*/
* Your code
/*
db = SQLAlchemy(app)
db.init_app(app) # HERE you need to call an init_app
return app
so in your case the best way is the second solution with the add of
db.init_app(app)
if you choose this solution, it will work normally.

Converting a flask app to an application factory pattern screws up all imports

So i've been building a flask app just using an app.py file and running it.
It has quite a big app now and i'm now just trying to convert it into an application factory because I need to use SQLAlchemy in my Celery tasks.
here is my init.py in my app folder
def create_app():
load_dotenv(".env")
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///data.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["PROPAGATE_EXCEPTIONS"] = True
app.config["BROKER_URL"] = os.getenv("REDIS_BACKEND_BROKER")
app.config["CELERY_BROKER_URL"] = os.getenv("REDIS_BACKEND_BROKER")
app.config["CELERY_IMPORTS"] = "celery_tasks"
app.secret_key = os.getenv("SECRET_KEY")
CORS(app)
api = Api(app)
jwt = JWTManager(app)
db.init_app(app)
ma.init_app(app)
celery.init_app(app)
#app.before_first_request
def create_tables():
db.create_all()
#jwt.invalid_token_loader
def invalid_token_callback(self):
return {"message": "invalid"}, 401
with app.app_context():
from .resources.auth import Auth, CheckUser
from .resources.period import Period
from .resources.project import Project
from .resources.session import Session
api.add_resource(Auth, "/auth")
api.add_resource(CheckUser, "/check")
api.add_resource(Project, "/createproject")
api.add_resource(Period, "/createperiod")
api.add_resource(Session, "/createsession")
return app
The problem is that all the resources that being imported breaks because they can no longer import based on modules either.
For example resources.period also imports SQLAlchemy models and Masrhmallow schemas
resources/period.py
#THESE ARE NO LONGER IMPORTED SUCCESSFULLY
from models.project import ProjectModel
from schemas.task import TaskSchema
from schemas.period import PeriodSchema
Here is my file structure
This is an awesome tutorial by Miguel Grinberg where he refactores a complete application like you want it, too:
https://www.youtube.com/watch?v=NH-8oLHUyDc&t=2934s
Did you try to make an "absolute" import like:
from app.models.project import ProjectModel
Since you're importing from resources/period.py using relative imports, you need to go up a level:
from ..models.project import ProjectModel
from ..schemas.task import TaskSchema
from ..schemas.period import PeriodSchema

How to define and access the database postgresql like flask sample code

I'm new use python flask, I want connected to postgresql use code like flask sample in this link, but in code sample use sqlite3. I try to search code sample and make me confused because every sample use different approach. This my code run but when use CLI to initialize database error.
Error: No such command "init-db".
My structure file
This my code:
run.py
#run.py
import os
from smart_app import create_app
app = create_app()
if __name__ == '__main__':
app.run()
init.py
#__init__.py
from flask import Flask
def create_app(config_filename=None):
app = Flask(__name__, instance_relative_config=True)
# load default configuration
app.config.from_object('config.default')
# load the configuration from the instance folder
app.config.from_pyfile('config.py')
# Load the file specified by the APP_CONFIG_FILE environment variable
# Variables defined here will override those in the default configuration
app.config.from_envvar('APP_CONFIG_FILE')
# Connect to database
from . import db
db.init_app(app)
return app
db.py
db.py
import click
from flask import current_app, g
from flask.cli import with_appcontext
from flask_sqlalchemy import SQLAlchemy
# db = SQLAlchemy()
def get_db():
if 'db' not in g:
g.db = SQLAlchemy()
return g.db
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db.close()
def init_db():
db = get_db()
with current_app.open_resource('schema.sql') as f:
db.executescript(f.read().decode('utf8'))
#click.command('init-db')
#with_appcontext
def init_db_command():
"""Clear the existing data and create new tables."""
init_db()
click.echo('Initialized the database')
def init_app(app):
app.teardown_appcontext(close_db)
app.cli.add_command(init_db_command)
If you familiar with SQL, use the psycopg2 to connect to your postgresql database.
Or if you want use ORM to operate the database in flask, you can use flask_sqlalchemy.

Access to Flask Global Variables in Blueprint Apps

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?
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 ?
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

Categories