I'm having trouble creating a modular application using Flask using blueprints. I'm not sure how to migrate models defined in blueprints.
My app looks as follows:
- app
- __init__.py
- user
__init__.py
models.py
app.__init__.py looks as follows:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import Config
from flask_migrate import Migrate
from app.auth import bp as user_bp
db = SQLAlchemy()
app = Flask(__name__)
app.config.from_object(Config)
app.register_blueprint(user_bp, url_prefix='/user')
migrate = Migrate(app, db)
from app.auth.models import User
user/.__init__.py:
from flask import Blueprint
bp = Blueprint('user', __name__)
user/models.py:
from app import db
class User(db.Model):
user_id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(128))
last_name = db.Column(db.String(128))
user_name = db.Column(db.String(120))
password_hash = db.Column(db.String(220))
def __repr__(self):
return '<User {}>'.format(self.email)
When trying to run flask db migrate... no models are being detected and I think I have some sort of circular dependency.
Can someone please explain how to do this properly?
The User model (user/models.py) should be imported somewhere in the application, try to import into the blueprint file (user/__init__.py)
from flask import Blueprint
from app.user.models import User
bp = Blueprint('user', __name__)
app.py
from flask import Flask
from flask_restful import Resource, Api
from user import user_blueprint
from flask_cors import CORS
app = Flask(__name__)
api = Api(app)
app.register_blueprint(user_blueprint)
cors = CORS(app, resources={r"/*": {"origins": "*"}})
if __name__ == '__main__':
app.run(debug=True)
model/user.py
from sqlalchemy import Column, INTEGER, String
class User(Base):
__tablename__ = 'USER'
__table_args__ = {'schema': 'MAPPING'}
ID = Column(INTEGER(11), primary_key=True)
FIRST_NAME = Column(String(255), nullable=False, server_default=text("''"))
LAST_NAME = Column(String(255), nullable=False, server_default=text("''"))
EMAIL = Column(String(255), nullable=False, server_default=text("''"))
route/user_route
from flask import Blueprint, jsonify, request
from flask_restful import Resource, Api
user_blueprint = Blueprint('app/', __name__)
user_api = Api(user_blueprint, prefix='/')
class User(Resource):
def get(self):
db_conn = //db connection Object
results = // your query
db_conn.close()
return jsonify(results)
user_api.add_resource(User, '/user')
Related
I followed some tutorial of flask factory pattern and tried to refactor my project. The database I use is a MySql container. Everything works fine before refactoring.
Now I came into an error sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: user and I guess the problem is due to isolated db instance because I never use sqllite in my project. But I fail to debug it. I also use blutprint to orgnize the strcture.
Here is the code relating to the error:
baseClasses.py
from flask_login import UserMixin
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
db = SQLAlchemy()
login_manager = LoginManager()
login_manager.login_view = "login"
login_manager.login_message_category = 'info'
bcrypt = Bcrypt()
#login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
class User(db.Model, UserMixin):
__tablename__ = "user"
usr = db.Column(db.String(50),primary_key=True,unique=True,nullable=False)
psd = db.Column(db.String(100), nullable=False)
role = db.Column(db.String(50), default="viewer")
def __repr__(self):
return f"User('{self.usr}','{self.psd}','{self.role}')"
def get_id(self):
return (self.usr)
class DataModel(db.Model):
__abstract__ = True
own_id = db.Column(db.Integer, primary_key = True, autoincrement = True, nullable = False)
name = db.Column(db.String(255), nullable = False)
project = db.Column(db.String(100), nullable = False)
last_user = db.Column(db.String(50))
path = db.Column(db.String(255), nullable = False)
model.py, the class TO is one example of all other classes, each of them has a table in the database.
from storage_flask.baseClasses import DataModel
from storage_flask.baseClasses import db
class TO(DataModel):
__tablename__ = "to"
to_version = db.Column(db.String(100), nullable = False)
title = db.Column(db.String(100), nullable = False)
issue_date = db.Column(db.DateTime, default = datetime.now().date())
change_date = db.Column(db.DateTime, default = datetime.now().date())
def __repr__(self):
return f"TO('{self.own_id}','{self.name}','{self.to_version}','{self.project}','{self.last_user}','{self.issue_date}','{self.change_date}','{self.path}','{self.title}'"
config.py
import os
class BaseConfig:
SECRET_KEY = 'aafa4f8047ce31126011638be8530da6'
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(BaseConfig):
DEBUG = True
#Database
SQLALCHEMY_DATABASE_URL = 'mysql+pymysql://root:demo#localhost:33065/TO'
init.py
import os
from flask import Flask
from storage_flask.baseClasses import db, bcrypt, login_manager, User
from storage_flask.main.routes import main
def create_app(config):
#create app instance
app = Flask(__name__.split('.')[0],static_folder="static")
app.config.from_object(config)
db.init_app(app)
bcrypt.init_app(app)
login_manager.init_app(app)
#register blueprintes
app.register_blueprint(main)
return app
run.py
from storage_flask import create_app, config
app = create_app(config.DevelopmentConfig)
if __name__ == '__main__':
app.run(host="127.0.0.1", debug=True)
routes.py of the blueprint main
from flask import render_template, url_for, flash, redirect, request, make_response, jsonify, abort, send_from_directory, Blueprint
# import flask-login functions
from flask_login import login_user, current_user, logout_user, login_required
main = Blueprint('main',__name__)
#main.route('/', methods = ['POST', 'GET'])
#login_required
def select_function():
return render_template('functionSelect.html', title = 'Function Selection')
The structure of the project would be:
|--storage_flask/
| |--main/
| | |--routes.py
| |--__init__.py
| |--baseClasses.py
| |--config.py
| |--model.py
|--run.py
I tried many ways to debug it but I always get the error. The database exists and it works before refactoring with factory pattern.
Could someone give me a hand?
I have some difficulties with the library lask-sqlalchemy, I tried to create my database with the code bellow, i have no error but no table created.
_init.py
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
app.config.from_json("C:/Users/lquastana/PycharmProjects/flask_demo/conf/api-config.json")
app.app_context().push()
db.py
from flask_sqlalchemy import SQLAlchemy
from api_lab import app
db = SQLAlchemy(app)
member.py
from api_lab.models.db import db
class Member(db.Model):
__table_args__ = {"schema": "public"}
id = db.Column(db.BigInteger,
primary_key=True,
autoincrement=True)
id_company = db.Column(db.BigInteger,
db.ForeignKey("compagny.id"),
index=True,
nullable=False)
nom = db.Column(db.String(80), unique=True, nullable=False)
age = db.Column(db.Integer, unique=True, nullable=False)
def __repr__(self):
return '<Member %r>' % self.nom
run_api.py
from api_lab import app
from api_lab.models.db import db
def main():
host = app.config["ENV"]["HOST"]
port = app.config["ENV"]["PORT"]
debug = app.config["ENV"]["DEBUG"]
app.run(host=host, port=port, debug= debug)
if __name__ == '__main__':
db.create_all()
#main()
You should put all initialization related logic into init.py
Use SQLAlchemy to setup a db connection with your app.config
init.py
from api_lab import app
from api_lab.models.db import db
from flask_sqlalchemy import SQLAlchemy
app.config.from_json("C:/Users/lquastana/PycharmProjects/flask_demo/conf/api-config.json")
app.app_context().push()
db = SQLAlchemy(app)
# initialize the DB
db.create_all()
I have created a flask app with Flask-Sql-Alchemy, however flask in't recognising the database table User_Plans I created and trying to query.
It gives the following error:
NameError: name 'User_Plans' is not defined.
I could be wrong, but it feels like the error is a scoping issue.
I have included my code below.
Can you help? Many thanks in advance.
database.py
from flask_sqlalchemy import SQLAlchemy
from flask_user import UserManager, UserMixin, SQLAlchemyAdapter
from datetime import datetime
def create_db(app):
db = SQLAlchemy(app)
class User(db.Model, UserMixin):
id=db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(50),nullable=False,unique=True)
password = db.Column(db.String(255),nullable=False, server_default='')
active=db.Column(db.Boolean(),nullable=False,server_default='0')
email = db.Column(db.String(255),nullable=False,unique=True)
confirmed_at = db.Column(db.DateTime())
plan_id=db.Column(db.Integer, db.ForeignKey('plans.id'),default=1)
db_adapter = SQLAlchemyAdapter(db,User)
user_manager = UserManager(db_adapter,app)
class User_Plans(db.Model):
id=db.Column(db.Integer,primary_key=True)
user_id=db.Column(db.Integer, db.ForeignKey('user.id'))
plan_id=db.Column(db.Integer, db.ForeignKey('plans.id'))
start_date = db.Column(db.DateTime())
class User_APIs(db.Model):
id=db.Column(db.Integer,primary_key=True)
user_id=db.Column(db.Integer, db.ForeignKey('user.id'))
api_id=db.Column(db.Integer, db.ForeignKey('tools.id'))
api_key=db.Column(db.String(50),nullable=False,unique=True)
class Tools(db.Model):
id=db.Column(db.Integer,primary_key=True)
tool=db.Column(db.String(50),nullable=False,unique=True)
class Plans(db.Model):
id=db.Column(db.Integer,primary_key=True)
plan=db.Column(db.String(50),nullable=False,unique=True)
price=db.Column(db.Float(5),nullable=False)
credit=db.Column(db.Integer,nullable=False)
class Usage(db.Model):
id=db.Column(db.Integer,primary_key=True)
user_id=db.Column(db.Integer, db.ForeignKey('user.id'))
task_id=db.Column(db.Integer, db.ForeignKey('tasks.id'))
datetime=db.Column(db.DateTime())
class Tasks(db.Model):
id=db.Column(db.Integer,primary_key=True)
task=db.Column(db.String(50),nullable=False,unique=True)
credit=db.Column(db.Integer,nullable=False)
class Status(db.Model):
id=db.Column(db.Integer,primary_key=True)
status=db.Column(db.String(20),nullable=False,unique=True)
__init__.py
from flask import Flask
from flask import render_template
from flask_mail import Mail
from config import config
from database import create_db
from flask_user import login_required, current_user
from dateutil.relativedelta import relativedelta
from datetime import datetime
def create_app(config_name):
print(config_name)
app = Flask(__name__)
app.config.from_object(config[config_name])
create_db(app)
mail = Mail(app)
#app.route('/')
#login_required
def index():
user_id = current_user.id
start_date=User_Plans.query.with_entities(User_Plans.start_date).filter(User_Plans.user_id==user_id).first()
return '<h1>Hello {}, you started your plan on {}</h1>'.format(current_user.username,start_date.strftime('%d-%m-%Y'))
manage.py
from app import create_app
app = create_app('development')
if __name__== '__main__':
app.run()
It isn't talking about your table, it's talking about the name User_Plans, which is indeed not defined in your main code. You need to import it - and any other models you use - into that file.
from models import User_Plans
I am following this tutorial: getting started with flask-login.
However I am stuck at step 5 where I start to use SQLAlchemy. I believe the problem might be circular importing, based on what I have read but I'm still a little new to Python coding. This web app is a little project I am doing in my free time.
So I guess my overall question is, is this circular importing, and if not does anyone see what I might be doing wrong here? I am also running this using virtualenv using Python 2.7.
File Structure:
-noteapp
-noteapp
-db
-forms
-static
-templates
-views
__init__.py
app.py
models.py
This is my app.py file
from flask import Flask
from flask_login import LoginManager
from noteapp.models import db
from noteapp.views.index import bp as index_bp
from noteapp.views.createnote import bp as createnote_bp
from noteapp.views.signup import bp as signup_bp
def init_db():
db.init_app(app)
db.app = app
db.create_all()
app = Flask(__name__)
app.secret_key = 'removed for reasons'
app.config['SQLALCHEMY_DATABASE_URI'] = 'removed for reasons'
db = SQLAlchemy(app)
login_manager = LoginManager(app)
login_manager.init_app(app)
app.register_blueprint(index_bp)
app.register_blueprint(createnote_bp)
app.register_blueprint(signup_bp)
if __name__ == '__main__':
app.init_db()
app.run(debug=True)
This is my models.py file:
from noteapp.app import app
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
class User(db.Model):
email = db.Column(db.String(80), primary_key=True, unique=True)
password = db.Column(db.String(80))
def __init__(self, email, password):
self.email = email
self.password = password
def __repr__(self):
return '<User %r>' % self.email
You are correct you have a circle import issue.
At app.py you import from noteapp.models import db,
and at models.py you import from noteapp.app import app
A quick fix could be:
at models.py use db = SQLAlchemy() without the app.
At the app.py module, import db from models.py and do db.init_app(app)
also remove db = SQLAlchemy(app) from your app.py
your app.py should look like this..
from noteapp.models import db
...
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'removed for reasons'
...
def init_db():
db.init_app(app)
db.app = app
db.create_all()
...
if __name__ == '__main__':
app.init_db()
app.run(debug=True)
models.py should look like this:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
email = db.Column(db.String(80), primary_key=True, unique=True)
password = db.Column(db.String(80))
def __init__(self, email, password):
self.email = email
self.password = password
def __repr__(self):
return '<User %r>' % self.email
Basically I'm trying to make a Flask app using flask-sqlalchemy. I want to first load up a bunch of data into my database (database.py). However, I can't get this to work or even create the myapp.db file.
I'm getting no errors, however myapp.db file is not being created.
>>> db.engine
Engine(sqlite://)
The above should be myapp something, I'm pretty sure.
I have simplified my code to make it more concise to the problem.
Here I have my app:
from flask import Flask
import os
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db_path = os.path.join(os.path.dirname(__file__), 'myapp.db')
db_uri = 'sqlite:///{}'.format(db_path)
SQLALCHEMY_DATABASE_URI = db_uri
db = SQLAlchemy(app)
from views import *
if __name__ == '__main__':
app.secret_key = os.urandom(12)
app.run(debug=True)
And I want to run my database.py to load all my data - which in my mind should be creating a myapp.db file??:
from flask_sqlalchemy import SQLAlchemy
import os
import re
from myapp import app
from models import *
## Creates our database
db.create_all()
username = test
password = test
user = User(username=username, password=password)
db.session.add(user)
db.session.commit()
Here is my models.py
from flask_sqlalchemy import SQLAlchemy
from myapp import app
# create a new SQLAlchemy object
db = SQLAlchemy(app)
class User(db.Model):
""""""
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, nullable=False)
password = db.Column(db.String, nullable=False)
Changing
SQLALCHEMY_DATABASE_URI = db_uri
to
app.config['SQLALCHEMY_DATABASE_URI'] = db_uri
fixed it.