OperationalError no such table in Flask with SQLAlchemy - flask-sqlalchemy

run.py
if __name__ == '__main__':
config()
app.run()
main.py
import database
app = Flask(__name__)
def config():
app.config.from_object('config.DevConfig')
# Run SQLAlchemy _that uses app.config_ and add entities if in DEBUG mode
database.init_db(app)
import blueprints.auth
app.register_blueprint(blueprints.auth.auth)
database.py
db = None
def init_db(app):
global db
db = SQLAlchemy(app)
from models import User, Interest, Event
if app.config['DEBUG']:
print 'Recreating all db'
db.create_all() # I DO create everything
print 'Loading test data'
... (here I add some Users and etc. and everything works fine - tests pass)
models.py
from database import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
...
blueprints/auth.py
from models import User
auth = Blueprint('auth', __name__)
#auth.route('/')
def index():
return str(User.query.get(1).interests)
And so I get
OperationalError: (OperationalError) no such table: user u'SELECT user.id AS user_id, user.username AS user_username, user.email AS user_email, user.passhash AS user_passhash, user.vk_page AS user_vk_page \nFROM user \nWHERE user.id = ?' (1,)
What am I doing wrong?

For anyone trying to use an in memory database:
from sqlalchemy import create_engine
from sqlalchemy.pool import StaticPool
engine = create_engine(
"sqlite://",
connect_args={"check_same_thread": False},
poolclass=StaticPool
)

There were few things I had to change to make everything work.
replace DATABASE_URI with SQLALCHEMY_DATABASE_URI parametr in config
replace :memory: sqlite address with /tmp/test.db
Now it works fine.

Related

Authentication with sub routes in SQLAlchemy in flask

Hi I was implementing a login verification to restrict certain routes on a website. Users are created successfully and if a user does not exist, they cannot log in. However, when attempting to access a route that requires a login, changing the username still allows access to the route. Do you know why this might be happening?
This is the code:
from flask import Flask, redirect, flash, request, render_template, url_for, make_response
import secrets
from flask_login import login_required, LoginManager, login_user, UserMixin
from flask_sqlalchemy import SQLAlchemy
app = Flask("test")
secret_key = secrets.token_hex(16)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SECRET_KEY'] = secret_key
db = SQLAlchemy(app)
login_manager = LoginManager(app)
login_manager.init_app(app)
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(120), nullable=False)
email = db.Column(db.String(100), unique=True, nullable=False)
games = db.relationship('Game', backref='user', lazy=True)
class Game(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
moves= db.Column(db.String(500), nullable=False)
status = db.Column(db.String(5), nullable=False)#Si o no
color = db.Column(db.String(20), nullable=False)
#login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
#login_manager.unauthorized_handler
def unauthorized():
return redirect(url_for("login"))
#app.route('/')
def home():
return render_template('begin.html')
#app.route('/login',methods=['GET','POST'])
def login():
if request.method == 'POST':
name= request.form['user']
psw = request.form['psw']
user = User.query.filter_by(name=name).first()
if user and user.password==psw:
login_user(user)
route = '/'+str(user.name)+'/home'
return redirect(route)
else:
return render_template('login.html',resultado='user not found')
else:
return render_template('login.html')
#app.route('/registrar',methods=['GET','POST'])
def registrar():
if request.method == 'POST':
user = request.form['user']
email = request.form['email']
psw = request.form['psw']
confirm_psw = request.form['confirm_psw']
if psw != confirm_psw:
return render_template('registrar.html',validacion="Passwords do not match")
new_user = User(name=name, email=email, password=psw)
db.session.add(new_user)
db.session.commit()
return redirect('/login')
else:
return render_template('registrar.html')
#app.route('/<user>/home',methods=['GET','POST'])
#login_required
def main_page(user):
return render_template('home.html',user=user)
UPDATE
After some research I know the problem is with the url in the main_page. When I change the user in the url the current_user doesn't change so the current_user is the user that make login and the login_required doesn't look for the new user. I don't know if I am correct because I tried to fixed it but it doesn't work
The first thing to underestand is that your logged in user is being loaded every time they go to a route, and we define this behaviour in this seccion of code:
#login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
Whats happening here is that we are loading the user using it's user_id which is stored in flask's session object, as you can see in this line of code User.query.get(int(user_id))
So the reazon it doesn't prompt the user to login again is because the user_id hasn't changed even when the username was changed.
What you could do if you want that to happen is to clear the session when you change the username, like this:
from flask import session
# Your code where you change the username
session.clear()

Flask not storing data to database

Database not storing flask data models. Even though the database gets created.
Using postrges, the tables get created in bash view but not in pgAdmin. I have a simple app that needs to store data. Would appreciate help.'
Code uses SQLAlchemy. DO i need to use different library. I am using psycopg2 and sessions but havent imported sessions.
#!flask/bin/python
#!flask/bin/python
from os import linesep
from typing import Mapping, Type from flask
import Flask, jsonify
from flask import request
from slotscal import results
from flask_sqlalchemy
import SQLAlchemy
import time
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']= 'postgresql+psycopg2://postgres:test123#localhost:5432/hqw' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db=SQLAlchemy(app)
db.metadata.clear()
#add parenrts
class Contracts(db.Model):
name=db.Column(db.String(100))
address=db.Column(db.String(42), unique=True, primary_key=True)
fileName=db.Column(db.Integer)
Functions= db.relationship('Function')
Variables= db.relationship('Variable')
StateVariables=db.relationship('StateVariable')
def __init__(self,address,fileName,id,StateVariables,name):
self.address=address
self.fileName=fileName
self.id=id
self.StateVariables=StateVariables
self.name=name
class Function(db.Model):
id=db.Column(db.String(42), db.ForeignKey('contracts.address'), primary_key=True)
name=db.Column(db.String)
lines=db.Column(db.Integer)
ReachingTime=db.Column(db.DateTime)
TrackingTime=db.Column(db.DateTime)
Arguments= db.relationship('Arguments')
def __init__(self,address,ReachingTime,id,TrackingTime,name,lines):
self.address=address
self.ReachingTime=ReachingTime
self.TrackingTime=TrackingTime
self.id=id
self.lines=lines
self.name=name
class Argument(db.Model):
id=db.Column(db.String(42), db.ForeignKey('function.id'), primary_key=True)
Type=db.Column(db.String)
Value=db.Column(db.String)
Name=db.Column(db.String)
def __init__(self,Name, id,Type,Value):
self.Name=Name
self.id=id
self.Type=Type
self.Value=Value
class Variable(db.Model):
VariableName=db.Column(db.String)
id=db.Column(db.String(42),db.ForeignKey('contracts.address'),primary_key=True)
Type=db.Column(db.String)
Value=db.Column(db.String)
StateVaruiable=db.Column(db.Boolean)
Mapping=db.Column(db.Boolean)
def __init__(self,address,Value,Type,id,StateVariables,name):
self.address=address
self.Type=Type
self.Value=Value
self.id=id
self.StateVariables=StateVariables
self.name=name
class m(db.Model):
id=db.Column(db.String(42),db.ForeignKey('variable.id'), primary_key=True)
Type=db.Column(db.String)
Source=db.Column(db.String)
def __init__(self,Type,Source,id):
self.Type=Type
self.id=id
self.Source=Source
class StateVariable(db.Model):
id=StateVariableType=db.Column(db.String)
StateVariableValue=db.Column(db.String)
id=db.Column(db.String(42),db.ForeignKey('contracts.address'),primary_key=True)
def __init__(self,id,StateVariableType,StateVariableValue):
self.StateVariableType=StateVariableType
self.StateVariableValue=StateVariableValue
self.id=id
class Key(db.Model):
id=db.Column(db.String(42),db.ForeignKey('m.id'), primary_key=True)
Value=db.Column(db.String)
Type=db.Column(db.String)
def __init__(self,Value,id,Type):
self.id=id
self.Value=Value
self.Type=Type
class Analysis(db.Model):
id=db.Column(db.String(42),db.ForeignKey('contracts.address'),primary_key=True)
FullTime=db.Column(db.DateTime)
StateVariables=db.Column(db.Integer)
def __init__(self,id,FullTime):
self.id=id
self.FullTime=FullTime
#app.route('/') def index():
return "Hello, World!" #app.route('/process', methods=['POST']) def process():
#print ('h')
header=request.json
#print ('g')
code=header['code']
f=open('code.sol','w')
f.write(code)
f.close()
path='./code.sol' #filename
subcon=header['name'] #name
add=header['address'] #address
contract=Contracts(subcon,add,path)
db.session.add(contract)
db.session.commit()
lst=results(path,subcon,add)
return jsonify({'task': lst})
if __name__ == '__main__':
app.run(debug=True)**
I'm not certain what you use the db.metadata.clear() for in your context.
Most likely, you don't see data in your DB, because there's nothing in your code to create the database relations. Standard solutions would include Alembic (Flask-Migrate package) or adding
with app.app_context():
db.create_all()
to your code.
The particulars are really up to you. Flask-Migrate is quite easy:
Install: pip install flask-migrate
Add to model:
from flask-migrate import Migrate
...
app = Flask(...)
...
#db init code
...
migrate = Migrate(app, db)
Run:
initialize: flask db init
migrate: flask db migrate -m "[YOUR MESSAGE]"
upgrade: flask db upgrade
Here's a good source in addition to the official docs: https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iv-database

How to use `from_orm` if the pydantic model defines aliases?

Though the pydantic's ORM mode is documented here, unfortunately there is no documentation for usage with aliases.
How to use from_orm if the pydantic model defines aliases?
It seems that the from_orm factory forgets about all non-aliased names if aliases exist. - See error message and the corresponding code below. Is that a bug or a feature?
The code snippet below fails unexpectedly with a validation error:
pydantic.error_wrappers.ValidationError: 1 validation error for SimpleModel
threeWordsId
field required (type=value_error.missing)
from sqlalchemy import Column, String
from sqlalchemy.ext.declarative import declarative_base
from pydantic import BaseModel, Field
Base = declarative_base()
class SimpleOrm(Base):
__tablename__ = 'simples'
three_words_id = Column(String, primary_key=True)
class SimpleModel(BaseModel):
three_words_id: str = Field(..., alias="threeWordsId")
class Config:
orm_mode=True
simple_orm = SimpleOrm(three_words_id='abc')
simple_oops = SimpleModel.from_orm(simple_orm)
Use allow_population_by_field_name = True in config.
Like
from sqlalchemy import Column, String
from sqlalchemy.ext.declarative import declarative_base
from pydantic import BaseModel, Field
Base = declarative_base()
class SimpleOrm(Base):
__tablename__ = 'simples'
three_words_id = Column(String, primary_key=True)
class SimpleModel(BaseModel):
three_words_id: str = Field(..., alias="threeWordsId")
class Config:
orm_mode = True
allow_population_by_field_name = True
# allow_population_by_alias = True # in case pydantic.version.VERSION < 1.0
simple_orm = SimpleOrm(three_words_id='abc')
simple_oops = SimpleModel.from_orm(simple_orm)
print(simple_oops.json()) # {"three_words_id": "abc"}
print(simple_oops.json(by_alias=True)) # {"threeWordsId": "abc"}
from fastapi import FastAPI
app = FastAPI()
#app.get("/model", response_model=SimpleModel)
def get_model():
# results in {"threeWordsId":"abc"}
return SimpleOrm(three_words_id='abc')

How do I structure this medium sized flask application?

Using the FLASK framework in Python, my application needs to:
register and log in users (with either a sqlite or postgres database)
access a specific google spreadsheet that the logged in user owns and output that data in a json format.
I am required to have my own authorization & authentication system
I am having a lot of trouble figuring out how to even structure the application - what directories and sub-directories should I have?
I have done A LOT of playing around (about 1 months worth). I am using a virtual environment but don't know how to test my code well either. In general, my code runs but I have no idea how they work together really.** I am completely new to flask.**
Structuring the app:
|app
|----run.py
|----config.py
|----database
|---------database.db
|----app
|---------views.py
|---------models.py
|---------forms.py
|---------extensions.py
|----templates
|---------....
|----static
|--------....
Authorization / Authentication:
I have looked at Flask-Login, Flask-Auth, Flask-Security. I understand the general idea but do not know how to securely implement a complete authorization & authentication system.
app = Flask(__name__)
app.config.from_object(config)
login_manager = LoginManager()
login_manager.init_app(app)
def create_app():
db.init_app()
db.app = app
db.create_all()
return app
#app.route('/')
def index():
#needs to render the homepage template
#app.route('/signup', methods = ['GET', 'POST'])
def register():
form = SignupForm()
if request.method == 'GET':
return render_template('signup.html', form=form)
elif request.method == 'POST':
if form.validate_on_submit():
if User.query.filter_by(email=form.email.data).first():
return "email exists"
else:
newuser = User(form.email.data, form.password.data)
db.session.add(newuser)
db.session.commit()
login_user(newuser)
return "New User created"
else:
return "form didn't validate"
return "Signup"
#app.route('/login', methods = ['GET', 'POST'])
def login():
form = SignupForm()
if request.method == 'GET':
return render_template('login.html', form=form)
elif request.method == 'POST':
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user:
if user.password == form.password.data:
login_user(user)
return "you are logged in"
else:
return "wrong password"
else:
return "user doesnt exist"
else:
return "form did not validate"
#login_manager.user_loader
def load_user(email):
return User.query.filter_by(email = email).first()
#app.route('/protected')
#login_required
def protected():
return "protected area for logged in users only"
if __name__ == '__main__':
#app.create_app()
app.run(port=5000, host='localhost')`
from flask_security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin, login_required
import os
# Create app
app = Flask(__name__)
#app.config['DEBUG'] = True
app.config['SECRET_KEY'] = ''
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////'
app.config['SECURITY_PASSWORD_HASH'] = 'sha512_crypt'
app.config['SECURITY_PASSWORD_SALT'] = str(os.urandom(24))
# Create database connection object
db = SQLAlchemy(app)
# Define models
roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
description = db.Column(db.String(255))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
active = db.Column(db.Boolean())
confirmed_at = db.Column(db.DateTime())
roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic'))
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
# Create a user to test with
#app.before_first_request
def create_user():
db.create_all()
user_datastore.create_user(email='', password='')
db.session.commit()
#app.route('/')
#login_required
def home():
#password = encrypt_password('mypass')
#print verify_and_update_password('mypass', password)
return "hello"
if __name__ == '__main__':
app.run(debug=True, use_reloader=False)
** I would really appreciate any guidance!**
Project structure:
If you're planning to build a larger Flask application, you should consider decomposing the functionality into Blueprints.
The official Flask documentation has a tutorial on how to structure larger applications:
http://flask.pocoo.org/docs/0.12/patterns/packages/
Also, take a look at the Hitchhiker's guide to organizing your project. It has some very good points: http://python-guide-pt-br.readthedocs.io/en/latest/writing/structure/
If you're designing an REST API consider using Flask-RESTful (which also works nicely with Blueprints)
ya'll, i figured it out & my app is LOOKING GOOD :)I am using blueprints & an application factory pattern.
APP
|_runserver.py
|_/app
|---__init__.py
|---config.py
|---extensions.py
|---forms.py
|---models.py
|---/login_dashboard #blueprint
|------__init__.py
|------views.py
|------/templates
|---------base.html
.
.
|------/static
|-----------/css
.
.
|-----------/js
.
.
|-----------/img
.
.

Problems when connecting to Appfog's SQL service from Flask

I'm currently trying to get my Flask app working with Appfog. I'm having 500 error every time I'm trying to do something with my DB. My connection code looks like:
services = json.loads(os.environ.get("VCAP_SERVICES"))
pg = services["postgresql-9.1"][0]["credentials"]
app.config.update({
'SQLALCHEMY_DATABASE_URI': "postgresql://%s:%s#%s:%i/%s" % \
(pg["username"], pg["password"], pg["host"], pg["port"], pg["name"])
})
# I've tried MySQL too
Model:
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(40), unique=True)
passhash = db.Column(db.String(140))
def __init__(self, username, password):
self.username = username
self.passhash = pwd_context.encrypt(password)
def check_password(self, password):
return pwd_context.verify(password, self.passhash) # from passlib
# Flask-Login properties
def is_authenticated(self): return True
def is_active(self): return True
def is_anonymous(self): return False
def get_id(self): return unicode(self.id)
And some example route that utilizes DB:
#app.route("/login", methods=['GET', 'POST'])
def login():
if current_user.is_authenticated():
logout_user()
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
user = User.query.filter_by(username=username).first()
if not user or not user.check_password(password):
flash('Wrong username or password.')
return render_template('login.html')
else:
login_user(user)
return redirect(request.args.get("next") or "/")
else:
return render_template('login.html')
This works with sqlite database on localhost. So, am I doing something wrong?