Implementing Flask-WhooshAlchemy using an Application Factory - python

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)

Related

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')
...

Flask x Apscheduler - RuntimeError: RuntimeError: Working outside of application context

I am getting the following error when trying to set up a scheduled job for my flask app:
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.
I have tried to include the function 'print_session' (which is just a dummy function to check the session data will pull through - in reality this function will query a database) with a 'current_app.appcontext() with loop as I have seen on a few other apps but no joy. Does anyone know why it is still out of the application context?
main.py
from website import create_app
app = create_app()
if __name__=="__main__":
app.run(debug=True,host='localhost',port=5000,threaded=True)
init.py
from flask import Flask, session
from flask_sqlalchemy import SQLAlchemy
from os import path
from flask_session import Session
from flask_login import LoginManager
import redis
db = SQLAlchemy()
DB_NAME = 'sqlite:///db.sqlite3'
sess=Session()
login_manager = LoginManager()
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = "SECRET_KEY"
app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI
app.config['SESSION_TYPE'] = 'SESSION_TYPE'
app.config['SESSION_REDIS'] = 'SESSION_REDIS'
db.init_app(app)
sess.init_app(app)
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
# with app.app_context():
from .views import views
from .auth import auth
app.register_blueprint(views,url_prefix='/')
app.register_blueprint(auth,url_prefix='/')
from .models import User,Token
create_database(app)
return app
def create_database(app):
db.create_all(app=app)
print('Created database')
views.py
from flask import Blueprint,render_template,session,redirect,request,url_for
from flask import current_app
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
import datetime
from flask_login import login_required,current_user
from requests_oauthlib import OAuth2Session
from . import db
from .models import Token
from functools import wraps
def print_session(value):
with current_app.app_context():
print('Yes',value)
return(redirect(url_for('views.home')))
#views.route('/start_schedule')
#login_required
def start_xero_schedule():
with app.app_context():
sched = BackgroundScheduler()
sched.add_job(print_session,'interval',args=[session['value']],seconds=10)
sched.start()
return(redirect(url_for('views.xero')))

Cannot import name 'db' (flask, sqlalchemy) [duplicate]

This question already has an answer here:
Import Flask extension when it is created in an app factory [duplicate]
(1 answer)
Closed 4 years ago.
I'm trying to import database and get an error "cannot import name 'db'". I've seen answers on such problem, but none of them helped in my case.
Tree of my project:
chat
| chat.py
└─ app
│ models.py
│ __init__.py
│
├─── main
│ events.py
│ forms.py
│ routes.py
│ __init__.py
chat.py:
from app import create_app, socketio
app = create_app(debug=True)
if __name__ == '__main__':
socketio.run(app)
app\init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_socketio import SocketIO
socketio = SocketIO()
def create_app(debug=False):
app = Flask(__name__)
app.debug = debug
app.config['SECRET_KEY'] = 'gjr39dkjn344_!67#'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql:///site.db'
db = SQLAlchemy(app)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
socketio.init_app(app)
return app
app\main\init.py:
from flask import Blueprint
main = Blueprint('main', __name__)
from . import routes, events
app\models.py:
from app import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(15), nullable=False)
session_id = db.Column(db.String(200), nullable=False)
isready = db.Column(db.Boolean, default='False')
room = db.relationship('Room', backref='spy')
def __repr__(self):
return f"User('{self.username}')"
So, when I'm trying from app import db in python terminal I get
ImportError: cannot import name 'db'
Since I'm new to flask (and web at all), I have no idea, what to do. I've tried this solution (kinda closest to my case) and all alike answers but it didn't work.
What can I try?
db is just a local variable in the create_app() function. You'll need to create that object outside of the create_app() factory.
You can create the Flask-SQLAlchemy db plugin object without passing in an app argument, and in the factory connect that object to te Flask app with the .init_app() method, just like you already do for the Flask-SocketIO plugin:
db = SQLAlchemy()
def create_app(debug=False):
app = Flask(__name__)
app.debug = debug
app.config['SECRET_KEY'] = 'gjr39dkjn344_!67#'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql:///site.db'
db.init_app(app)
socketio.init_app(app)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
return app
Now db is available as a global in the module, and so can be imported elsewhere.

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

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)

ImportError: No module named app

I working with Flask-Testing and make file test_app.py to test But I got this error File "test_app.py", line 4, in from app import create_app, db ImportError: No module named app.
so please help how can I fix it and what is the problem Thanx :)
here is my Structure:
myapplication
app
__ init __.py
model.py
form.py
autho
layout
static
templates
migrations
test
-test_app.py
config.py
manage.py
test_app.py
#!flask/bin/python
import unittest
from flask.ext.testing import TestCase
from app import create_app, db
from app.model import Users
from flask import request, url_for
import flask
class BaseTestCase(TestCase):
def create_app(self):
self.app = create_app('testing')
return self.app
config.py
class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \
'sqlite:///' + os.path.join(basedir, 'mytest.sqlite')
__ init __.py
#!flask/bin/python
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.login import LoginManager
import psycopg2
from config import basedir
from config import config
db = SQLAlchemy()
lm = LoginManager()
lm.login_view = 'login'
login_manager = LoginManager()
login_manager.login_view = 'layout.login'
def create_app(config_name):
app = Flask(__name__)
app.config['DEBUG'] = True
app.config.from_object(config[config_name])
db.init_app(app)
login_manager.init_app(app)
# login_manager.user_loader(load_user)
from .layout import layout as appr_blueprint
# register our blueprints
app.register_blueprint(appr_blueprint)
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
return app
From the comments:
There could have been two issues:
The path to myapplication/ hadn't been added to the $PYTHONPATH environment variable (more info here and here)
Let's say the code lives under /home/peg/myapplication/. You need to type in your terminal
export PYTHONPATH=${PYTHONPATH}:/home/peg/myapplication/
__init__.py could have had a typo. There shouldn't be whitespaces between the underscores __ and the init.py chunk (__init__.py is good, __ init __.py is not)

Categories