db.create_all() is not adding specific column into the database - python

I am trying to add the Product table into the database using flask sqlalchemy. It adds all the columns except for the userBudget
Does anyone know why?
On the cmd, I do
from app import db
db.create_all()
Then I go into sqlite3 and check the .schema but only the userBudget column is missing
sqlite> .schema
CREATE TABLE user (
id INTEGER NOT NULL,
username VARCHAR(15),
email VARCHAR(50),
password VARCHAR(80),
PRIMARY KEY (id),
UNIQUE (username),
UNIQUE (email)
);
CREATE TABLE product (
"userId" INTEGER NOT NULL,
"productURL" VARCHAR NOT NULL,
"currentPrice" INTEGER,
PRIMARY KEY ("userId"),
FOREIGN KEY("userId") REFERENCES user (id)
);
import requests
from flask import Flask, render_template, redirect, url_for, request
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
# Instantiation
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db' # location of database
SQLALCHEMY_TRACK_MODIFICATIONS = False # no sqlalchemy warnings in console
bootstrap = Bootstrap(app) # allows use of flask-bootstrap
db = SQLAlchemy(app) # database
# Initialization
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
# Database Tables
class User(UserMixin, db.Model): # UserMixin provides default implementations for the methods flask-login expects users to have
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(15), unique=True)
email = db.Column(db.String(50), unique=True)
password = db.Column(db.String(80))
class Product(db.Model):
userId = db.Column(db.Integer, db.ForeignKey(User.id), primary_key=True)
productURL = db.Column(db.String(), nullable=False)
currentPrice = db.Column(db.Integer)
userBudget = db.Column(db.Integer, nullable=False)
#login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
if __name__ == '__main__':
app.run(debug=True)

If you are still in development, do a db.drop_all() followed by a db.create_all().
You should track your db changes with e.g. https://github.com/miguelgrinberg/Flask-Migrate

Related

Python Flask Authorization login_user not working

I have a flask app that acts as a login system. I am trying to use #roles_required() decorator in order to check if the user is an admin, and if they are, giving them access to specific areas.
When I try log in with the correct credentials, that have been created with the correct roles, it gives me the error below.
AttributeError: type object 'User' has no attribute 'get_user_by_token'
I have located the error, it seems to be that login_user() is not working properly. I have commented the line causing an error in login_post().
Let me know if there's anything else you need. Please help!!! No one can seem to figure it out...
app.py
from flask import Flask, Blueprint, render_template, redirect, url_for, request, flash, session
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin, login_user, logout_user, login_required, current_user, LoginManager
import json
from flask_user import UserManager, roles_required
USER_ENABLE_EMAIL = False
auth = Blueprint('auth', __name__)
db = SQLAlchemy()
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
db.init_app(app)
#login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
from app import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
app.config['USER_ENABLE_EMAIL'] = False
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy
username = db.Column(db.Text, unique=True, nullable=False)
password = db.Column(db.Text, nullable=False)
# Relationships
roles = db.relationship('Role', secondary='user_roles',
backref=db.backref('users', lazy='dynamic'))
# Define the Role data model
class Role(db.Model):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(50), unique=True)
# Define the UserRoles data model
class UserRoles(db.Model):
id = db.Column(db.Integer(), primary_key=True)
user_id = db.Column(db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE'))
role_id = db.Column(db.Integer(), db.ForeignKey('role.id', ondelete='CASCADE'))
user_manager = UserManager(app, db, User)
#auth.route('/')
def login():
return render_template('login.html')
#auth.route('/login', methods=['POST'])
def login_post():
username = request.form.get('username')
password = request.form.get('password')
remember = True if request.form.get('remember') else False
adminuser = 'adminuser'
adminpwd = 'adminpwd'
if username == adminuser:
if check_password_hash(adminpwd, password):
login_user(user, remember=remember) # this is the problem
return redirect('/admin/dashboard')
if not user or not check_password_hash(user.password, password):
flash('Please check your login details and try again.')
return redirect(url_for('auth.login'))
login_user(user, remember=remember) # this is the problem
return redirect(url_for('auth.profile'))
#auth.route('/profile')
#login_required
#roles_required('userClass')
def profile():
return render_template('profile.html')
#auth.route('/admin/dashboard')
#roles_required('Admin')
def admin_dashboard():
return render_template("admin_dashboard.html")

sqlalchemy unknown database flask with multiple databases

I created two databases using flask and sqlalchemy. My code is as follows:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager
from flask_login import UserMixin
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///C:\\Users\\dmac\\testmac.db'
app.config['SQLALCHEMY_BINDS'] = {
'User': 'sqlite:///C:\\Users\\dmac\\User.db',
'Stock': 'sqlite:///C:\\Users\\dmac\\Stock.db'
}
db = SQLAlchemy(app)
migrate = Migrate(app, db, render_as_batch = True)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
class Users(UserMixin, db.Model):
__table_name__ = 'users'
__bind_key__ = 'User'
__table_args__ = {'schema': 'User'}
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(100))
class Stock(db.Model):
__table_name__ = 'stock'
__bind_key__ = 'Stock'
__table_args__ = 'Stock'
id = db.Column(db.Integer, primary_key = True)
prices = db.Column(db.Float)
I tried to perform the flask-sqlalchemy upgrade after doing the migrate and init --multidb to fill my databases with table. However, I got the following error:
sqlalchemy.exc.OperationalError:(sqlite3.OperationalError) Unknown database "USER"[SQL:'\Create Table "User.users (id INTEGER not NULL, name VARCHAR(100))](Background on this error at: http://sqlalche.me/e/e3q8)
Any help would be appreciative. Thanks

How to create db table with SQLite / SQLAlchemy?

I'm trying to create a table in an existing db with SQLAlchemy/SQLite where I have to store a user and password, but it returns an error saying the column pwd doesn't exist!
Am I missing something? Am I messing it up?
I still didn't quite understand, I followed all steps in some online tutorial but nothing still.
Here is the class object that I developed, then from another register form I try to store the pw from the application, but the error should be here in this code:
import os
basedir = os.path.abspath(os.path.dirname(__file__))
# flask imports
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from sqlalchemy import *
# create flask app
app = Flask(__name__)
# set sqllite db connection
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')
engine= create_engine(app.config['SQLALCHEMY_DATABASE_URI'])
# bcrypt extension init to app
bcrypt = Bcrypt(app)
# sqlite init to app
db = SQLAlchemy(app)
# define meta data for table
meta=MetaData()
userstable = Table('users', meta, Column('id', Integer, primary_key = True, autoincrement=True), Column('username', String, unique=True), Column('pwd', String))
# create table to sqlite
meta.create_all(engine)
class User(db.Model):
# user columns
id = db.Column(db.Integer(), primary_key=True, autoincrement=True)
username = db.Column(db.String(64), unique=True)
pwd = db.Column(db.String(128))
def __init__(self,username,pwd):
#self.id=id
self.username=username
self.pwd=bcrypt.generate_password_hash(pwd)
# create user object
user = User('anish','23434')
# insert user object to sqlite
db.session.add(user)
# commit transaction
db.session.commit()
This is the error:
sqlalchemy.exc.OperationalError OperationalError: (sqlite3.OperationalError) table user has no column named pwd [SQL: INSERT INTO user (username, pwd) VALUES (?, ?)] [parameters: ('ita_itf', '$2b$12$VmpTsd0o4uTLj0wGypGu7ujhzYHLlV8k9ekaIP1.yh5lUMMgOM4MC')]
import os
basedir = os.path.abspath(os.path.dirname(__file__))
# flask imports
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from sqlalchemy import *
# create flask app
app = Flask(__name__)
# set sqllite db connection
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')
engine= create_engine(app.config['SQLALCHEMY_DATABASE_URI'])
# bcrypt extension init to app
bcrypt = Bcrypt(app)
# sqlite init to app
db = SQLAlchemy(app)
# define meta data for table
meta=MetaData()
userstable = Table('users', meta, Column('id', Integer, primary_key = True, autoincrement=True), Column('username', String, unique=True), Column('pwd', String))
# create table to sqlite
meta.create_all(engine)
class User(db.Model):
# table name for User model
__tablename__ = "users"
# user columns
id = db.Column(db.Integer(), primary_key=True, autoincrement=True)
username = db.Column(db.String(64), unique=True)
pwd = db.Column(db.String(128))
def __init__(self,username,pwd):
#self.id=id
self.username=username
self.pwd=bcrypt.generate_password_hash(pwd)
# create user object
user = User('anish','23434')
# insert user object to sqlite
db.session.add(user)
# commit transaction
db.session.commit()

Something is wrong with my model SQLAlchemy SQlite Flask Python

There's something wrong with my model? do you se any anomaly? Trying to store a user and password to SQLite db with SQLAlchemy but returns an error saying the column pwd in the user table doesn't exist, indeed if I check sqlite> .schema it returns the table with the correct structure and pwd column, no data inside if I query though.
I firstly create the table with Table() function, then under I define the User class, maybe is because in the class there are no references to the column names of the table? but I have imported tablename="user" so it should work no?
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from sqlalchemy import *
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data-users.sqlite'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer(), primary_key = True, autoincrement=True)
username = db.Column(db.String(64), unique = True)
pwd = db.Column(db.String())
def __repr__(self):
return '<User %r>' % self.username
Here I store the user data in the table
from store_user_db import User, db
db.create_all()
DICP_FTP_DESTINATION_PSW=self.submit_pwd()
user = User(id=001,username="ita_itf",pwd=DICP_FTP_DESTINATION_PSW)
db.session.add(user)
db.session.commit()
This is the error:
sqlalchemy.exc.OperationalError
OperationalError: (sqlite3.OperationalError) table user has no column named pwd
[SQL: INSERT INTO user (id, username, pwd) VALUES (?, ?, ?)]
[parameters: (1, 'ita_itf', <read-only buffer for 0x7efe495709f0, size -1, offset 0 at 0x7efe500c3830>)]
The db.create_all() will only create tables if they don't already exist. I suspect that your issue is that you created the table in the recent past, at a point where you didn't yet have the pwd column in your model.
So now you run db.create_all() and it essentially does nothing (as the user table already exists) but falls over when you try to access the never created pwd column.
You can db.drop_all() to destroy all the current tables, or you could manually (or using a migration tool) add the 'missing' pwd column so the database matches the model.
Also, all this code doesn't do anything in this particular example (unless you're doing something unusual in code you haven't included).
engine= create_engine(app.config['SQLALCHEMY_DATABASE_URI'])
#CREATE TABLE
meta=MetaData()
userstable = Table('user', meta, \
Column('id', Integer, primary_key = True, autoincrement=True), \
Column('username', String, unique = True), \
Column('pwd', LargeBinary,unique = True))
meta.create_all(engine)
Example Working Version
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///example.sqlite3"
bcrypt = Bcrypt(app)
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer(), primary_key=True, autoincrement=True)
username = db.Column(db.String(64), unique=True)
pwd = db.Column(db.LargeBinary(), unique=True)
def __init__(self, id, username, pwd):
self.id = id
self.username = username
self.pwd = bcrypt.generate_password_hash(pwd)
if __name__ == "__main__":
db.drop_all() # destroy all the tables.
db.create_all() # create all fresh new tables.
u = User(1, "static", "password")
db.session.add(u)
db.session.commit()
u = User.query.first() # check out data got stored.
print(u.pwd)

Flask in factory pattern cannot find user table in existing database by launching the app

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?

Categories

Resources