Splitting Flask code into different files [closed] - python

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Below is the python flask code.
All I want to do is split the code into different files as in
all the routes in views.py, configure db in db.py and use them in app.py or where ever required.
Also I want to use db in some of the routes so how do I call it in views.py
from flask import Flask, render_template, request, redirect, make_response, jsonify
from flask_mysqldb import MySQL
from flask_cors import CORS, cross_origin
import yaml
app = Flask(__name__)
# middleware
cors = CORS(app)
# configure db
db = yaml.safe_load(open('db.yaml'))
app.config['MYSQL_HOST'] = db['mysql_host']
app.config['MYSQL_USER'] = db['mysql_user']
app.config['MYSQL_PASSWORD'] = db['mysql_password']
app.config['MYSQL_DB'] = db['mysql_db']
mysql = MySQL(app)
# routes
#app.route("/", methods=['POST'])
def index():
cur = mysql.connection.cursor()
sql_select_query_check = """UPDATE users SET Password = %s, Password_Status = %s WHERE ID = %s"""
cur.execute(sql_select_query_check, (hashcode, 1, userid[0]))
mysql.connection.commit()
return jsonify({"message": "password updated"})
if __name__ == '__main__':
app.run(debug=True, use_reloader=True)

In flask documentation you can see Larger Applications which shows how to split code. And it mentions that main problem can be circular import - main imports views which has to import main to get app. The same problem is with db.py which would need to import main to get app
I move app to separated file application.py to skip circular import
I don't run code and maybe it would need to import mysql to views.py
But maybe it should be done with Blueprint() or with functions which will be imported to main.py and run with argument app.
application.py
from flask import Flask
app = Flask(__name__)
db.py
from application import app
from flask_mysqldb import MySQL
import yaml
db = yaml.safe_load(open('db.yaml'))
app.config['MYSQL_HOST'] = db['mysql_host']
app.config['MYSQL_USER'] = db['mysql_user']
app.config['MYSQL_PASSWORD'] = db['mysql_password']
app.config['MYSQL_DB'] = db['mysql_db']
mysql = MySQL(app)
views.py
from application import app
#app.route("/", methods=['POST'])
def index():
cur = mysql.connection.cursor()
sql_select_query_check = """UPDATE users SET Password = %s, Password_Status = %s WHERE ID = %s"""
cur.execute(sql_select_query_check, (hashcode, 1, userid[0]))
mysql.connection.commit()
return jsonify({"message": "password updated"})
main.py
from application import app
from flask import render_template, request, redirect, make_response, jsonify
from flask_cors import CORS, cross_origin
from views import *
# middleware
cors = CORS(app)
if __name__ == '__main__':
app.run(debug=True, use_reloader=True)
EDIT:
Version with code in functions init() and without application.py - but I didn't test if it will works. But it starts looking like code with Blueprint
db.py
from flask_mysqldb import MySQL
import yaml
def init(app):
db = yaml.safe_load(open('db.yaml'))
app.config['MYSQL_HOST'] = db['mysql_host']
app.config['MYSQL_USER'] = db['mysql_user']
app.config['MYSQL_PASSWORD'] = db['mysql_password']
app.config['MYSQL_DB'] = db['mysql_db']
return MySQL(app)
views.py
def init(app, mysql):
#app.route("/", methods=['POST'])
def index():
cur = mysql.connection.cursor()
sql_select_query_check = """UPDATE users SET Password = %s, Password_Status = %s WHERE ID = %s"""
cur.execute(sql_select_query_check, (hashcode, 1, userid[0]))
mysql.connection.commit()
return jsonify({"message": "password updated"})
main.py
from flask import Flask
from flask import render_template, request, redirect, make_response, jsonify
from flask_cors import CORS, cross_origin
import db
import views
app = Flask(__name__)
# middleware
cors = CORS(app)
myslq = db.init(app)
views.init(app, mysql)
if __name__ == '__main__':
app.run(debug=True, use_reloader=True)
But I would rather keep views with app = Flask(__name__) in one file.

Related

Flask with Flask-security and Blueprints - Error App-context

I try to combine flask with flask security and blueprints. But when I try to use the security.context_processor it doesn't work.
app.py
from flask import Flask
from views.default import default
from views.user import user
from views.permission import permission
from playhouse.flask_utils import FlaskDB
from modules.database import *
from flask_security import Security, PeeweeUserDatastore, UserMixin, RoleMixin, auth_required, hash_password
from flask_mailman import Mail
from config import *
import os
import pathlib
app = Flask(__name__)
app = Flask(__name__)
app.register_blueprint(default)
app.register_blueprint(user, url_prefix="/user")
app.register_blueprint(permission, url_prefix="/permission")
app.secret_key = SECRET_KEY
app.config["SESSION_TYPE"] = "filesystem"
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['ALLOWED_IMAGES'] = set(['png', 'jpg', 'jpeg', 'gif'])
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
app.config["SALT"] = ""
# Generate a nice key using secrets.token_urlsafe()
app.config['SECRET_KEY'] = os.environ.get("SECRET_KEY", '')
# Bcrypt is set as default SECURITY_PASSWORD_HASH, which requires a salt
# Generate a good salt using: secrets.SystemRandom().getrandbits(128)
app.config['SECURITY_PASSWORD_SALT'] = os.environ.get("SECURITY_PASSWORD_SALT", '')
app.config['DATABASE'] = {
'name': DB_NAME,
'engine': 'peewee.MySQLDatabase',
}
app.config['MAIL_SERVER'] = MAIL_SERVER
app.config['MAIL_PORT'] = MAIL_PORT
app.config['MAIL_USE_TLS'] = MAIL_TLS
app.config['MAIL_USERNAME'] = MAIL_USERNAME
app.config['MAIL_PASSWORD'] = MAIL_PASSWORD
mail = Mail(app)
# Setup Flask-Security
user_datastore = PeeweeUserDatastore(db, User, Role, UserRoles)
app.security = Security(app, user_datastore)
if __name__ == '__main__':
with app.app_context():
if not app.security.datastore.find_user(email="test#me.com"):
app.security.datastore.create_user(email="test#me.com", password=hash_password("password"))
app.run(host=HOST, port=PORT, threaded=True)
Blueprint file default.py:
from flask import Blueprint, render_template, abort, request, redirect, current_app, flash, session, current_app
from flask_security import Security, PeeweeUserDatastore, UserMixin, RoleMixin, auth_required, hash_password
from config import *
from modules.database import *
from modules.email import *
default = Blueprint('default', __name__, url_prefix="/")
#default.route('/', methods=['GET'])
#current_app.security.context_processor
def index():
return render_template('default.html')
Error message:
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.
How can I use the security.context_processor on a blueprint?
Or I have to structure the code to use the app Data in Blueprints. I read the current_app variable is only accessable in a request, but what is the alternative?

Running into NameError: name 'app' is not defined when trying to upload image into file [duplicate]

This question already has answers here:
Flask: How to use app context inside blueprints?
(2 answers)
Closed 8 months ago.
My problem occurs mainly when I try and upload a picture in a separate html form. Before I added the app.config I would successfully get POST and GET requests. On visual code it tells me that app is not defined but I'm not sure how to define it in my image.py file.
This is my image.py file app.config
from unicodedata import category
from flask import Flask, Blueprint, render_template, request, flash, jsonify, url_for, redirect
import urllib.request
from werkzeug.utils import secure_filename
from flask_login import login_required , current_user
from .models import Note
from .import db
import json
import os
image = Blueprint('image', __name__)
#image.route('/', methods=['GET','POST'])
#login_required
def Upload():
if request.method == "POST":
if request.files:
image = request.files["image"]
image.save(os.path.join(app.config['IMAGE_UPLOADS'], image.filename))
print("image saved")
return redirect(request.url)
return render_template("image.html", user=current_user)
My init.py file with my app configurations.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from os import path
from flask_login import LoginManager
db = SQLAlchemy()
DB_NAME = "database.db"
def create_app():
app = Flask(__name__)
#Secret key into app
app.config['SECRET_KEY'] = '****'
app.config['IMAGE_UPLOADS'] = r"C:\Users\qw\Desktop\StCh\website\static\Images"
app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
and finally my main.py file to run the app.
from website import create_app
app = create_app()
if __name__ == '__main__':
app.run(debug=True)
the error keeps on occurring even after I try and import from website or
I resolved it by just adding
app = Flask(__name__)
into my image.py file. Feel stupid

Unable to access formdata from Axios POST to Flask

I have a flask api that I am starting and I am sending a post generated by AXIOS.post:
from flask import Flask, request
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SECRET_KEY'] = "A REEALLY REALLY LONG KEY"
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://ppsadmin:#localhost/ppsportal"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
#app.route("/login")
def login():
data = request.form
print(data)
return json.dumps({"success":True})
if __name__ == '__main__':
app.run()
When I run this code Flask returns a 405 error and I am unable to access the fields.
Resolved:
I forgot to wrap the app in CORS.

How to fix 'Error: unable to open database file' in Flask app?

I'm creating a Flask server that will display information queried from an sqlite3 database. However, when I try to access the database file after running the localhost, it returns the following error.
File "C:\Users\Connor\Documents\Parking\app\routes.py", line 13, in index
con = sqlite3.connect(app.config['SQLALCHEMY_DATABASE_URI'])
sqlite3.OperationalError: unable to open database file
127.0.0.1 - - [26/Mar/2019 20:30:57] "GET / HTTP/1.1" 500 -
I'm almost positive that the problem stems from sqlite:///, but I can't figure it out. None of the solutions suggested seem to have the answer either.
routes.py
from app import app
from flask import Flask, flash, redirect, request, render_template,
session, url_for
import sqlite3
app.secret_key = app.config['SECRET_KEY']
#app.route('/')
#app.route('/index')
def index():
con = sqlite3.connect(app.config['SQLALCHEMY_DATABASE_URI'])
cur = con.cursor()
cur.execute("SELECT * FROM Lot")
data = cur.fetchall()
return render_template('index.html', data=data)
config.py
import os
PROJECT_ROOT = os.path.dirname(os.path.realpath(__file__))
class Config(object):
SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(PROJECT_ROOT, 'app.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
DEBUG = True
SECRET_KEY = 'development key'
init.py
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
Printing app.config['SQLALCHEMY_DATABASE_URI'] returns sqlite:///C:\Users\Connor\Documents\Parking\app.db. I would assume the forward slashes are the root of my problem. I've tried several variants of os.path but to no avail.
Oddly enough, when I manually type in my path, the database displays just fine AND its data can be manipulated in the admin portal. When I use os.path.join(PROJECT_ROOT, 'app.db'), the database displays, but I can't manipulate its data in the admin portal. When I use "sqlite:///" + os.path.join(PROJECT_ROOT, 'app.db'), I can't access the database at all.
I believe I'm using sqlite:/// correctly as per this document, so maybe I'm just missing something?
The issue here is that you are using the sqlalchemy connection url, but trying to connect directly through the sqlite3 api.
This line of code from within your index() route:
con = sqlite3.connect(app.config['SQLALCHEMY_DATABASE_URI'])
...calls the sqllite3.connect() function, and you are passing that your sqlalchemy connection url: SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(PROJECT_ROOT, 'app.db').
Here is the function signature of sqlite3.connect():
sqlite3.connect(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri])
And here is an excerpt form the documentation about what can be passed as the database parameter:
database is a path-like object giving the pathname (absolute or
relative to the current working directory) of the database file to be
opened.
sqllite:///some/path/to/app.db is not a valid pathname and that's why the error is raised.
You've gone to all the trouble of configuring flask_sqlalchemy, so you may as well use it!
from app import app, db # <== notice import of db here
from flask import (Flask, flash, redirect, request, render_template,
session, url_for)
app.secret_key = app.config['SECRET_KEY']
#app.route('/')
#app.route('/index')
def index():
data = db.session.execute("SELECT * FROM Lot").fetchall()
return render_template('index.html', data=data)
This has the added bonus of keys included session management that comes with Flask-SQLAlchemy.

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)

Categories