How to recreate database in SQLAlchemy from Flask? - python

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.

Related

(Python) Connecting mssql database using SQLalchemy and using it

I have a Python webapp that is connected to SQL Server database using SQLalchemy migration.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
import urllib
SQLALCHEMY_TRACK_MODIFICATIONS = False
app = Flask(__name__)
app.config['SECRET_KEY'] = '*******************'
params = urllib.parse.quote_plus('DRIVER={SQL Server};SERVER=SOMESERVER;DATABASE=PD;Trusted_Connection=yes;')
app.config['SQLALCHEMY_DATABASE_URI'] = "mssql+pyodbc:///?odbc_connect=%s" % params
db = SQLAlchemy(app)
now the database has a few tables with some values and I have a registration page and a login page that should use that.
but I only know that I can use a model.py file that models the table so that I can use them like this :
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
password = db.Column(db.String(60), nullable=False)
posts = db.relationship('Post', backref='author', lazy=True)
def __repr__(self):
return f"User('{self.username}', '{self.email}', '{self.image_file}')"
When I ran the files, the webapp launched normally, but when I entered a form (login or register) I got this error which, I presume, indicates that the table "User" was not found in the database.
sqlalchemy.exc.InterfaceError: (pyodbc.InterfaceError) ('IM002', '[IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified (0) (SQLDriverConnect)')
(Background on this error at: https://sqlalche.me/e/14/rvf5)
So should I just change the class name from User to the table name I have in the database, and then name all the fields using the names I have in DB as well? Or is there some other way to just call the table I have in DB and let it fill the "User" class (metaphorically) so that when User is imported, its my DB table that is used?
class User(db.Model, UserMixin):
__table__ = Table('table_name_here')
# rest of your definition
Should sort you.
EDIT: the URL should be something like:
app.config['SQLALCHEMY_DATABASE_URI'] = "mssql+pyodbc://daneil#server/database?driver=ODBC+Driver+17+for+SQL+Serve"

Having an issue with Flask, SQLlite3, SQLAcedemy, and SQL and unique column constraints and Python

I am having a problem with SQLite3 and unique column constraints here are my python model for a user.
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(120), unique=True, nullable=False)
image_file = db.Column(db.String(20), nullable=False, default="default.jpg")
password = db.Column(db.String(60), nullable=False)
posts = db.relationship("Post", backref="author", lazy=True)
When I create a new user:
user=User(username="ginger", email="ginger#gmail.com", password="ginger")
db.session.add(user)
db.session.commit()
I receive a the following error:
`enter code here`sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: user.username
However the database is completely empty. I'm really confused as to how to resolve this issue. Any help would be greatly appreciated.
Thanks
Dawson
I am so new to python that I feel like an idiot. I recently restructured my code and was using a relative path to the database. So I actually had two databases in two separate folders. The one I had open in the SQLite browser was empty however my application was inserting into the other database and yes the data I was inserting was a duplicate of what was already there.
Thanks
Dawson

How to ignore some models to migrate? [duplicate]

I am using Flask-SQLAlchemy to define my models, and then using Flask-Migrate to auto-generate migration scripts for deployment onto a PostgreSQL database. I have defined a number of SQL Views on the database that I use in my application like below.
However, Flask-Migrate now generates a migration file for the view as it thinks it's a table. How do I correctly get Flask-Migrate / Alembic to ignore the view during autogenerate?
SQL View name: vw_SampleView with two columns: id and rowcount.
class ViewSampleView(db.Model):
__tablename__ = 'vw_report_high_level_count'
info = dict(is_view=True)
id = db.Column(db.String(), primary_key=True)
rowcount = db.Column(db.Integer(), nullable=False)
Which means I can now do queries like so:
ViewSampleView.query.all()
I tried following instructions on http://alembic.zzzcomputing.com/en/latest/cookbook.html and added the info = dict(is_view=True) portion to my model and the following bits to my env.py file, but don't know where to go from here.
def include_object(object, name, type_, reflected, compare_to):
"""
Exclude views from Alembic's consideration.
"""
return not object.info.get('is_view', False)
...
context.configure(url=url,include_object = include_object)
I think (though haven't tested) that you can mark your Table as a view with the __table_args__ attribute:
class ViewSampleView(db.Model):
__tablename__ = 'vw_report_high_level_count'
__table_args__ = {'info': dict(is_view=True)}
id = db.Column(db.String(), primary_key=True)
rowcount = db.Column(db.Integer(), nullable=False)

Flask-Migrate Alter Table Error

i've been scratching my head for a bit of time now with this error and I can't seem to figure out what's wrong. Maybe you can help?
Using Flask-Migrate i've modified my models and am attempting to migrate the database accordingly.
The error i'm running into seems to be between two specific models User and Transaction.
After running
$ python run.py db init
$ python run.py db migrate
$ python run.py db upgrade
I recieve this error:
sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (1825, "Failed to add the foreign key constraint on table 'transaction_table'. Incorrect options in FOREIGN KEY constraint 'my_database/transaction_table_ibfk_1'") [SQL: 'ALTER TABLE transaction_table ADD FOREIGN KEY(user_id) REFERENCES users (id)']
Here is how i've set up my models note the tablename override:
class User(db.Model):
__tablename__ = 'users'
id = db.Column('id', db.Integer, primary_key=True)
email = db.Column(db.String(120), unique=True, index=True)
password = db.Column('password', db.String(10))
role = db.Column('role', db.String(3))
registered_on = db.Column('registered_on', db.DateTime)
transactions = db.relationship('transaction_table', backref=db.backref('user', lazy='joined'), lazy='dynamic')
class Transaction(db.Model):
__tablename__ = 'transaction_table'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
transaction_date = db.Column('transaction_date', db.DateTime)
requested_donor_id = db.Column(db.Integer, db.ForeignKey('donor_db.id'))
I've used this guide for setting up my models with Foreign Keys and relationships.
I've used this Blog Post to help diagnose my problems to no avail. Might you know what i'm missing?
Thanks in advance.

Error adding columns to SQLITE

I am working on Flask and sqlite as database. The requirements keep increasing for the project, so I have to add columns but I am not able to do it. I have searched on google but no answer found.
The part of code from model.py
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
default = db.Column(db.Boolean, default=False, index=True)
permissions = db.Column(db.Integer)
users = db.relationship('User', backref='role', lazy='dynamic')
#staticmethod
def insert_roles():
roles = {
'User': (Permission.FOLLOW |
Permission.COMMENT |
Permission.WRITE_ARTICLES, True),
'Moderator': (Permission.FOLLOW |
Permission.COMMENT |
Permission.WRITE_ARTICLES |
Permission.MODERATE_COMMENTS, False),
'Administrator': (0xff, False)
}
for r in roles:
role = Role.query.filter_by(name=r).first()
if role is None:
role = Role(name=r)
role.permissions = roles[r][0]
role.default = roles[r][1]
db.session.add(role)
db.session.commit()
def __repr__(self):
return '<Role %r>' % self.name
class User(UserMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(64), unique=True, index=True)
username = db.Column(db.String(64), unique=True, index=True)
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
password_hash = db.Column(db.String(128))
confirmed = db.Column(db.Boolean, default=False)
name = db.Column(db.String(64))
age = db.Column(db.Integer)
location = db.Column(db.String(64))
about_me = db.Column(db.Text())
member_since = db.Column(db.DateTime(), default=datetime.utcnow)
last_seen = db.Column(db.DateTime(), default=datetime.utcnow)
avatar_hash = db.Column(db.String(32))
posts = db.relationship('Post', backref='author', lazy='dynamic')
Whenever I try to add an column by running command
python manage.py db upgrade to it; it throws the following error:
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) table
roles already exists [SQL: u'\nCREATE TABLE roles (\n\tid INTEGER NOT
NULL, \n\tname VARCHAR(64), \n\tPRIMARY KEY (id), \n\tUNIQUE
(name)\n)\n\n']
How can I add column to my database?
After db migrate
run python manage.py db upgrade.
The error message is "table roles already exists". Therefore, you need to drop your db first and try to run python manage.py db upgrade again.
You must have created the database by running db.create_all();
I meet the same problem and you may try my solution as follow:
delete the database file (.sqlite);
delete the migrations folder;
run ... db init to create a new migrations;
run ... db migrate and ... db upgrade;
There may be some repeated operations between db.create_all() and the init migration. So just skip creating the tables manually.
Run the following three commands:
flask db stamp head
flask db migrate
flask db upgrade

Categories

Resources