I tried to use Flask-Dance with normal flask app and it works and if I try to implement with flask blueprints it doesn't work. How to register flask-dance to flask blueprints?
My views.py for auth blueprint
from flask import render_template, url_for, redirect, current_app, request
from app.auth import auth
from flask_dance.contrib import github
#auth.route('/login')
def login():
return render_template('auth/login.html')
#auth.route("/")
def github():
if not github.authorized:
return redirect(url_for("github.login"))
resp = github.get("/user")
assert resp.ok
return "You are #{login} on GitHub".format(login=resp.json()["login"])
my init.py for auth blueprint
from flask import Blueprint
from flask_dance.contrib.github import make_github_blueprint, github
auth = Blueprint('auth', __name__, url_prefix='/auth')
blueprint = make_github_blueprint(client_id="m-client-id",client_secret="my-client-secret")
auth.register_blueprint(blueprint, url_prefix="/auth")
from app.auth import views
and my main init.py file:
from flask import Flask
from flask_fontawesome import FontAwesome
from app.config import Config
fa = FontAwesome()
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(Config)
fa.init_app(app)
from app.public import public
app.register_blueprint(public)
from app.auth import auth
app.register_blueprint(auth)
return app
First you should create and register different blueprint for github.
github/init.py
from flask_dance.contrib import github
from flask_dance.contrib.github import make_github_blueprint
github_blueprint = make_github_blueprint(client_id='your-client-id',client_secret='your-client-secret')
from app.github import views
github/views.py
#github_blueprint.route("/")
def github_login():
if not github.authorized:
return redirect(url_for('github.login'))
account_info = github.get('/user')
if account_info.ok:
account = account_info.json()
return '<h1>Your Github name is {}'.format(account['login'])
and finally in your main init.py file
from flask import Flask
from flask_fontawesome import FontAwesome
from app.config import Config
fa = FontAwesome()
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(Config)
fa.init_app(app)
from app.public import public
app.register_blueprint(public)
from app.auth import auth
app.register_blueprint(auth)
from app.github import github_blueprint
app.register_blueprint(github_blueprint, url_prefix='/github_login')
#/github_login=callback url
return app
Related
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')))
I am trying to set the expiration for a cookie to be longer than the browser session. My config.py is:
from datetime import timedelta
SESSION_FILE_DIR = 'C:/some/path15'
SECRET_KEY= 'abcdefg'
DEBUG = True
SESSION_PERMANENT = True
PERMANENT_SESSION_LIFETIME = timedelta(days=30)
And then to mimic my app structure for this example, I have the main app which registers a blueprint:
from flask import Flask, render_template, request, session, current_app
from flask_session import Session
import tempfile
server = Flask(__name__)
server.config.from_pyfile('config.py')
### Import and Register Blueprints
from tools.routes import my_bp
server.register_blueprint(my_bp)
#server.route('/')
def homepage():
return "Hello"
if __name__ == '__main__':
server.run(debug=True)
And then a blueprint called routes.py living in a subdirectory of the main app called tools
from flask import Flask, render_template, request, session, Blueprint, current_app
from flask_session import Session
import tempfile
my_bp = Blueprint("my_bp", __name__)
#my_bp.route('/new', methods=['POST', 'GET'])
def path():
if 'path' not in session: ##new
session['path'] = tempfile.mkdtemp() ##new
path = session['path'] ##new
return path
When running this app (head over the /new route), if I Inspect Element under Storage in the browser, it shows that the cookies expire/max_age is Session.
How can I get this to respect the 30-day expiration I have set in the config.py file?
from flask import session, app
#app.before_request
def before_request():
session.permanent = True
app.permanent_session_lifetime = datetime.timedelta(minutes=20) # session will be alive for 20 minutes
I'm trying to turn my Flask code into a python package structure, but now that I've done that, when I try running the code, none of the HTML templates are found.
Here is the simplified structure of my current flask package. run.py is what I use to execute the Flask code. routes.py contains all my #app.routes where the HTML templates are called.
pipeline-ui/
run.py
pipeline_app/
__init__.py
routes.py
models.py
forms.py
templates/
pipeline-alt.html
The error message I get is: TemplateNotFound: pipeline-alt.html
init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
app = Flask('__name__')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
login_manager.login_message_category = 'info'
from pipeline_app import routes
run.py:
from pipeline_app import app
if __name__ == '__main__':
app.run(debug=True)
routes.py:
from flask import url_for, render_template, request, flash, redirect
from pipeline_app import app
from pipeline_app.forms import InputForm, RegistrationForm, LoginForm
from pipeline_app.models import User, Post
from flask_login import login_user, current_user, logout_user, login_required
from math import ceil
import json
import subprocess
import os
import sys
from pprint import pprint
#app.route('/', methods=['GET', 'POST'])
def pipeline():
form = InputForm(request.form)
if request.method == 'POST':
if form.validate_on_submit():
STACK_NAME = request.form['stack_name']
# Store data in database for future use
db.create_all()
db_inputs = Post(stack_name=STACK_NAME)
db.session.add(db_inputs)
db.session.commit()
return render_template('pipeline-alt.html',
title='Pipeline Input',
form=form,
STACK_NAME=STACK_NAME)
Change app = Flask('__name__') to app = Flask(__name__). Flask uses this parameter to find resources on the filesystem, so if it is not set correctly it will not be able to find your templates.
I want to set up a basic admin interface using flask-admin, and I want all of this to sit in a blueprint. Here's a minimal version my code:
#app.py
from flask import Flask
from bp import bp
app = Flask(__name__)
app.register_blueprint(bp)
if __name__ == "__main__":
app.run(debug=True)
#bp.py
from flask import Blueprint, current_app
from flask_admin import Admin
from flask_admin.contrib.pymongo import ModelView
import pymongo
conn = pymongo.MongoClient()
bp = Blueprint('bp', __name__,
template_folder='templates')
admin = Admin(current_app)
admin.add_view(ModelView(conn.my_db.my_collection))
When running python app.py, it crashes with RuntimeError: working outside of application context, because admin is in no way hooked (or whatever word is used to describe that) to bp.
Normally, one would write
#bp.route('/<page>')
def show(page):
pass
But I can't find the right decorator in the context of creating an Admin object. One thing I tried is to do admin = Admin() in bp.py, import admin in app.py and then admin.app = app in app.py. That works, but it feels like I'm splitting logic in several files, so I'm not really comfortable with that. What's the pythonic way to deal with this situation?
You need the actual app object to init the Flask admin Class. Current_app won't work. This call should be placed on app.py. Then on the blueprint you can use
from app import admin
It work out in this way. just for your reference.
#YourApp/init.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_admin import Admin
db = SQLAlchemy()
admin = Admin(name='TuozhanOA', template_mode='bootstrap3')
def create_app(config_class=Config):
app = Flask(name)
app.config.from_object(Config)
db.init_app(app)
admin.init_app(app)
from YourApp.main.routes import main
app.register_blueprint(main)
from YourApp.adminbp.routes import adminbp, user_datastore
app.register_blueprint(adminbp)
security = Security(app, user_datastore)
return app
#YourApp/adminbp/routes.py
from flask import render_template, Blueprint
from YourApp.models import User, Role
from YourApp import db, admin
from flask_admin.contrib.sqla import ModelView
from wtforms.fields import PasswordField
from flask_admin.contrib.fileadmin import FileAdmin
import os.path as op
from flask_security import current_user, login_required, RoleMixin, Security,
SQLAlchemyUserDatastore, UserMixin, utils
adminbp = Blueprint('adminbp', name)
admin.add_view(ModelView(User, db.session, category="Team"))
admin.add_view(ModelView(Role, db.session, category="Team"))
path = op.join(op.dirname(file), 'tuozhan')
admin.add_view(FileAdmin(path, '/static/tuozhan/', name='File Explore'))
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