Flask-PyMongo - init_app() missing 1 required positional argument: 'app' - python

i am trying to initialise my db using flask-pymongo.
But i get the following error,
File "run.py", line 22, in
app = create_app("config")
File "run.py", line 11, in create_app
mongo.init_app(app)
TypeError: init_app() missing 1 required positional argument: 'app'
run.py
from flask import Flask
from app import api_bp
from db import mongo
def create_app(config_filename):
app = Flask(__name__)
app.config.from_object(config_filename)
app.register_blueprint(api_bp, url_prefix='/api')
mongo.init_app(app)
return app
# def logger():
# def database():
if __name__ == "__main__":
app = create_app("config")
app.run(host='0.0.0.0', port=8080, debug=True)
db.py
from flask_pymongo import PyMongo
mongo = PyMongo
config.py
DEBUG = True
SECRET_KEY = "secret"
MONGO_URI = "mongodb://localhost:27017/api"
app/__init__.py
import os
import json
import datetime
from flask import Blueprint
from flask import jsonify
from flask_restful import Api
from .users.resource import UsersResource
api_bp = Blueprint('api', __name__)
api = Api(api_bp)
api.add_resource(UsersResource, '/users')
app/users/resource.py
I want to them import the mongo to this resource so i can access the users collection.
from flask_restful import Resource
from flask import jsonify
from .repository import UsersRepository
class UsersResource(Resource):
def __init__(self):
self.repository = UsersRepository()
def get(self):
data = {"Users": "Resource"}
res = data, 200
return res
I am trying to setup a restful api with resources using Flask-restful and flask-pymongo. Any other suggestions to improve my approach is welcome.

You didn't instantiate the PyMongo class in db.py.
mongo = PyMongo()

You should use flask-pymongo like this:
from flask import Flask
from flask_pymongo import PyMongo
app = Flask(__name__)
app.config["MONGO_URI"] = "mongodb://localhost:27017/myDatabase"
mongo = PyMongo(app)
So in run.py, you should use this code:
from flask import Flask
from app import api_bp
from db import mongo
def create_app(config_filename):
app = Flask(__name__)
app.config.from_object(config_filename)
app.register_blueprint(api_bp, url_prefix='/api')
# mongo.init_app(app) # remove this line
return app
# def logger():
# def database():
if __name__ == "__main__":
app = create_app("config")
py_mongo = mongo(app)
app.run(host='0.0.0.0', port=8080, debug=True)

Related

Flask Application AttributeError: 'NoneType' object has no attribute 'todos'

I'm trying to learn Flask by following along this video.
MongoDB has been connected with the database name mydb and cluster name todos. Still, I'm getting this error:
File "C:\__init__.py", line 2, in <module>
from .main.routes import main
File "C:\routes.py", line 7, in <module>
todos_collection = mongo.db.todos
AttributeError: 'NoneType' object has no attribute 'todos'
This is the file routes.py
from flask import Blueprint, render_template, redirect, url_for, request
from ..extensions import mongo
main = Blueprint('main', __name__)
todos_collection = mongo.db.todos
#main.route('/')
def index():
return render_template('index.html')
#main.route('/add_todo', methods=['POST'])
def add_todo():
todo_item = request.form.get('add-todo')
todos_collection.insert_one({'text' : todo_item, 'complete' : False})
return redirect(url_for('main.index'))
This is the init.py file
from flask import Flask
from .main.routes import main
from .extensions import mongo
def create_app():
app = Flask(__name__)
app.config['MONGO_URI'] = 'mongodb+srv://admin:<password>#cluster0.r324nzc.mongodb.net/todos'
mongo.init_app(app)
app.register_blueprint(main)
return app
This is the extensions.py file
from flask_pymongo import PyMongo
mongo = PyMongo()
Looks like you have missing spacing in create_app func. Try to fix it for the beginning.
def create_app():
app = Flask(__name__)
app.config['MONGO_URI'] = 'mongodb+srv://admin:<password>#cluster0.r324nzc.mongodb.net/todos'
mongo.init_app(app)
app.register_blueprint(main)
return app

Logging Flask Application in Heroku

I am trying to find a way to structure my code such that I can view logs in the production server hosted on Heroku.
Every tutorial I found seems to do logging like this:
How to show stdout logs in Heroku using Flask?
However, I am using the application factory pattern which utilizes Blueprints. As such here are some sample:
main.py
from app import create_app
app = create_app()
if __name__ == "__main__":
app.run()
app/_ _ init _ _.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
...
db = SQLAlchemy()
...
def create_app():
app = Flask(__name__)
...
db.init_app(app)
from .routes.demo_blueprint import demo_blueprint
...
# Register the routes to the Flask object
app.register_blueprint(demo_blueprint)
...
app/routes/demo_blueprint.py
from app import db
...
demo_blueprint = Blueprint('demo_blueprint', __name__)
#demo_blueprint.route('/demo', methods=['GET'])
...
In order to perform logging at the blueprint level, I would need to import app from main.py. However, this would cause an import error since __init__.py imports the blueprint before app is created. I was wondering if there were any work arounds for this.
Turns out it was a simple fix. To access the application context in the Blueprint, just use current_app. Following the example:
How to show stdout logs in Heroku using Flask?
main.py
from app import create_app
app = create_app()
if __name__ == "__main__":
app.run()
app/_ _ init _ _.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
...
db = SQLAlchemy()
...
def create_app():
app = Flask(__name__)
if __name__ != '__main__':
gunicorn_logger = logging.getLogger('gunicorn.error')
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(gunicorn_logger.level)
...
db.init_app(app)
from .routes.demo_blueprint import demo_blueprint
...
# Register the routes to the Flask object
app.register_blueprint(demo_blueprint)
...
app/routes/demo_blueprint.py
from flask import ***current_user***
from app import db
...
demo_blueprint = Blueprint('demo_blueprint', __name__)
#demo_blueprint.route('/demo', methods=['GET'])
def demo():
current_app.logger.debug('debug message: %s', 'test')
...

how to import mongo variable from the app which is binded to app

i have a files like app.py and views.py
app.py
from flask import Flask
from flask_pymongo import PyMongo
app = Flask(__name__)
app.config["MONGO_URI"] = "mongodb://local:27017/local"
mongo = PyMongo(app)
from views import profileview
profileview.register(app, route_prefix='/profile/')
if __name__== "__main__":
app.run(debug=True)
views.py
from flask_classy import FlaskView , route
# i am unable to import the app in views
from app import mongo
class profileview(FlaskView):
route_base = '/'
#route("/user/",methods=["GET"])
def index(self):
pass
when i run the server it showing that cannot
import from views import profileview, how to avoid the circular import
this is how to avoid circular import :
db.py
from flask_pymongo import PyMongo
mongo = PyMongo()
app.py
if __name__ == '__main__':
from db import mongo
mongo.init_app(app)
views.py
from db import mongo
or you could use the factory pattern and make a create_app function.

Flask and Flask-SocketIO integration and import errors

I am trying to integrate Flask-SocketIO with my Flask application.
For some reason I am getting an import error that is triggered by the
from .. import socketio that I have in my events.py and I am not sure why.
I would greatly appreciate any help provided.
app.py
from factory import create_app
app = create_app()
factory.py
from flask import Flask
from flask.ext.socketio import SocketIO
from flask.ext.login import LoginManager
import os
from celery import Celery
lm = LoginManager()
socketio = SocketIO()
lm.login_view = 'main.login'
lm.session_protection = 'strong'
def create_app():
app = Flask(__name__)
app.config.from_object(os.environ.get('APP_CONFIG')) # export APP_CONFIG=settings.Development
lm.init_app(app)
from project.main import main as main_blueprint
app.register_blueprint(main_blueprint)
socketio.init_app(app)
return app
main/____init____.py
from flask import Blueprint
main = Blueprint('main', __name__)
import views, events
main/events.py
# from __future__ import absolute_import
from uuid import uuid4
from flask import current_app, session, request
from flask.ext.socketio import emit, disconnect
from .. import socketio
#socketio.on('status', namespace='/events')
def events_message(message):
print 'socketio.on: status'
emit('status', {'status': message['status']})
#socketio.on('disconnect request', namespace='/events')
def disconnect_request():
print 'socketio.on: disconnect request'
emit('status', {'status': 'Disconnected!'})
disconnect()
#socketio.on('connect', namespace='/events')
def events_connect():
print 'socketio.on: connect'
websocket_id = str(uuid4())
session['websocket_id'] = websocket_id
current_app.clients[websocket_id] = request.namespace
emit('websocket_id', {'websocket_id': websocket_id})
Rename main/____init____.py to main/__init__.py and you can do:
from . import socketio
if socketio is defined in __init__.py like you said. However, it looks like it's defined in factory.py, in which case you'd do:
from ..factory import socketio

Implementing Flask-WhooshAlchemy using an Application Factory

If app is created in global scope
__init__.py
from flask import Flask
app = Flask(__name__)
app.config.from_object('config')
from app import views
This code down below in run.py would be enuf to start using whoosh_search in views.py like post = Post.query.whoosh_search(name, limit=3).all()
run.py
import os
from app import app
from flask.ext.script import Manager
from flask.ext.moment import Moment
from flask.ext.sqlalchemy import SQLAlchemy
import flask.ext.whooshalchemy as whooshalchemy
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] =\
'sqlite:///' + os.path.join(basedir, 'post.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SECRET_KEY'] = 'hard to guess string'
db = SQLAlchemy(app)
manager = Manager(app)
moment = Moment(app)
class Post(db.Model):
__tablename__ = 'post'
__searchable__ = ['body']
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime))
def __repr__(self):
return '<Post %r>' % (self.body)
whooshalchemy.whoosh_index(app, Post)
if __name__ == '__main__':
db.create_all()
manager.run()
So how to implement Flask-WhooshAlchemy using an Application Factory.
__init__.py
from flask import Flask
from flask.ext.bootstrap import Bootstrap
from flask.ext.moment import Moment
from flask.ext.sqlalchemy import SQLAlchemy
from config import config
bootstrap = Bootstrap()
moment = Moment()
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
bootstrap.init_app(app)
moment.init_app(app)
db.init_app(app)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
return app
How to register app in whooshalchemy.whoosh_index(app, Post) with Application Factory so whoosh_search could be use in views.py like in last example.
In your application factory function fx. after initializing all the apps, and before registering your blueprints. You should import your model and run whoosh_index. Something along the lines of:
from .model import Post
whooshalchemy.whoosh_index(app, Post)

Categories