Problem with storing data in sqlite with Python/Flask-SQLAlchemy code - python

I'm trying to store a user and password in a table I created with sqlite db. It seems that pwd column doesn't exist, while if I check the table in sqlite it does contain the column.
The error returns the following:
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', '$2b$12$j5NPKCgv8DsFnOJtHE2xjOyXMoGSFCz89Gf/Oy2Hs.FfEx/0BuOY2')]
(Background on this error at: http://sqlalche.me/e/e3q8)
ERROR DETAILS:
File "/home/itad/DICP_evo_dev/venv/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 552, in do_execute
def do_executemany(self, cursor, statement, parameters, context=None):
cursor.executemany(statement, parameters)
def do_execute(self, cursor, statement, parameters, context=None):
cursor.execute(statement, parameters)
def do_execute_no_params(self, cursor, statement, context=None):
cursor.execute(statement)
def is_disconnect(self, e, connection, cursor):
this is the User class I created:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data-users.sqlite'
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.String(128))
def __init__(self,id,username,pwd):
self.id=id
self.username = username
self.pwd = bcrypt.generate_password_hash(pwd)
This is the code where I manually insert the password with a python GUI in my app:
from store_user_db import User, db
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()
Here I check the user table if exist and the schema, I also tried to run sqlite>SELECT * FROM user but it doesn't return any result
itad#itad-virtual-machine:~/DICP_evo_dev$ sqlite3 data-users.sqlite
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
sqlite> .schema user
CREATE TABLE user (
id INTEGER NOT NULL,
username VARCHAR,
pwd VARCHAR,
PRIMARY KEY (id),
UNIQUE (username)
);
Maybe it's easier if I show you the screenshots, the commented part is the one I used to create the table, then I commented it because you only need to create it once.
PYTHON CODE
SQLITE FROM COMMAND PROMPT
I didn't put that in the code but I previously did create the db and the table with the function table() then create_all() etc.. Then I comment that out. indeed if I type sqlite> .schema user, it shows the table, should be there in the db no?

i think issue is with the declaration of user variable 2 times in models
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.String(128))
def __init__(self,id,username,pwd):
db.Model.__init__(self, id=id, username=username, pwd=pwd)
this will solve the problem.

Seems like your table is not being created, try running 'python' (to run REPL), import the class that has the db object and run 'db.create_all()' (This will create tables in DB according to your models)

Looking at the code where I create the table and then I create the User class, there might be some issue because in the User class I'm using User(db.Model) while when I create the table just before I'm using engine and Metadata() function? Indeed when I create the table there's no reference to db.
Screenshot below, code on the left:
https://i.stack.imgur.com/LMwhO.jpg

Related

exclude password column in query sqlalchemy

I need to know how to query by excluding password column.
is it possible?
query = await db.execute(
select(User)
.filter(User.id.in_(users.user_ids)).where(User.is_deleted== False))
list_user = query.scalars().unique().all()
You can use the "Deferred Column Loading" feature. For example, if you want the password column to be loaded only upon direct access, instead of when the entity is queried, you can define it using the deferred function in your model:
from sqlalchemy.orm import deferred
from sqlalchemy import String, Column, ...
class User(Base):
__tablename__ = "user"
username = Column(String(200), nullable=False)
...
password = deferred(Column(String(2000)))
...

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)

How to recreate database in SQLAlchemy from Flask?

I'm using SQLAlchemy ORM framework from a Flask project. I wanted to add another column to one of my models. After I did, I used db.session.drop_all() to drop all current entries in the database, and then I tried recreating a new instance with the new field.
Whenever I tried I get this error
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no
such table: user
[SQL: SELECT user.id AS user_id, user.username AS user_username, user.email AS user_email, user.password AS user_password, user.image_file AS user_image_file
FROM user]
I think I might need to reconstruct the database in some way, but I'm not sure how. I looked into the documentation, but could not find anything useful.
__init__.py
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
models.py
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(40), unique=True, nullable=False) #newly added field
password = db.Column(db.String(60), nullable=False)
image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
messages = db.relationship('Message', backref='user', lazy=True)
When you used db.drop_all() you dropped all tables so now you can't insert data because there is no table. You need create the table again with db.create_all() as #SuperShoot mentioned.
You should use something for migrations like alembic or flask-sqlalchemy.
This way you could add new column to your ORM. Run flask db migrate -m 'new column', this will detect changes. Then run flask db upgrade head to apply those changes to your database.

how to manage session django_session with login table sqlalchemy?

I need to manage session in django to check whether user is active or non active. I use sqlalchemy ORM for login where django_session creates table with python manage.py syncdb of one django ORM,
how to check session user logged in with two table (Login Tabel of SQLAlchemy and Django_session Django ORM)
class Student(Base):
__tablename__ = 'login'
id = Column(Integer, primary_key=True)
username = Column(String(50))
password = Column(String(50))
session = Column(String,ForeignKey(Session))
Write a function that checks if a user is logged in with SqlAlchemy:
def is_login_sql_alchemy(id):
logged = ... check in sql alchemy, True or False
return logged
Then in your view (assume a CBV):
if self.request.user.is_authenticated:
logged_in_both = is_login_sql_alchemy(self.request.user.id)
In a function view just use request.user

Flask/SQLAlchemy - error creating models with relationships

I created a table users with this mysql statement in the shell:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(40) NOT NULL,
`email` varchar(120) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB;
and a table posts with this statement:
CREATE TABLE `posts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`text` varchar(140) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_user_id` (`user_id`),
CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
I want to use these tables in my Flask app. I created a foreign key connecting posts to users. It's supposed to be a one-to-many relationship with the user having many posts.
In my python code I have the following models:
class Users(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(40), unique=True)
email = db.Column(db.String(120), unique=True)
posts = db.relationship('Posts', backref='user', lazy='dynamic')
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<User {}>'.format(self.username)
class Posts(db.Model):
id = db.Column(db.Integer, primary_key=True)
text = db.Column(db.String(140))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
When I try running my Flask app however, I keep getting the error:
sqlalchemy.exc.InvalidRequestError: One or more mappers failed to
initialize - can't proceed with initialization of other mappers.
Original exception was: Could not determine join condition between
parent/child tables on relationship Users.posts - there are no foreign
keys linking these tables.
But I created the foreign key connecting posts to users in the mysql statement. When I take out the line posts = db.relationship('Posts', backref='user', lazy='dynamic'), everything works just fine, so the issue lies in that piece of code. What part of my setup is wrong?
Not sure what's wrong with the initial creation of the tables, but i would use sqlalchemy's create_all. See here and in the docs. This way you know any issue is not a matter of different definitions of the initial SQL creation query vs the models' definitions. Stick with SQLAlchemy all the way.
Your model definitions seem OK, except for the backref. I compared it with my models definitions, and my backrefs are always the table names. You have 'user' as a backref, which doesn't really appear anywhere else in the code, so i'm assuming that's where things go wrong.
To forcibly define table names add tablename to the class definition; e.g.
class User(db.model):
__tablename__ = 'Users'
id = db.Column(..
.. more fields ..
posts = db.relationship('Post', backref='Users', lazy='dynamic')
I use the convention of the classes in singular, and table names in plural, which makes it easier to see how things are defined, what a backref points to, etc. For example, note that the above relationship points to the class Post, while the backref to the table Users. Now there's no ambivalence in the definitions.

Categories

Resources