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
Related
I am having trouble making a One-To-Many relationship between 'User' and 'GymObj' using a Foreign Key. In my code, a user can have only one gym objective however a gym objective can have many users. The code which I attempted seems to be correct as I followed a tutorial for it however a 'NoForeignKeysError' appears.
python code
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(200), nullable=False, unique=True)
birth_year = db.Column(db.Integer, nullable=False)
weight = db.Column(db.Integer, nullable = False)
date_added = db.Column(db.DateTime, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('gymobj.id'))
#Create a String
def __repr__(self):
return '<Username %r>' % self.username
class GymObj(db.Model):
id = db.Column(db.Integer, primary_key=True)
gym_obj = db.Column(db.String)
users = db.relationship('User', backref='user')
console
sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between parent/child tables on relationship GymObj.users - there are no foreign keys linking these tables. Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression.
I attempted to make a migration and push the migration in the Shell as well however the same error appeared. Any help would be much appreciated.
I have two model classes in separate files, created a One-To-Many relationship between them.
user.py:
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(100), index=True, unique=True, nullable=False)
password = db.Column(db.String(128), nullable=False)
projects = db.relationship('Project', backref='owner', lazy='dynamic')
project.py:
class Project(db.Model):
__tablename__ = 'projects'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), index=True, unique=True, nullable=False)
owner_id = db.Column(db.Integer, db.ForeignKey('User.id'))
This is how I create my app:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URL
db = SQLAlchemy(app)
#app.before_first_request
def create_tables():
db.create_all()
app.run(debug=True)
However when I create a request I get the following error:
sqlalchemy.exc.NoReferencedTableError:
Foreign key associated with column 'projects.owner_id' could not find
table 'User' with which to generate a foreign key to target column 'id'
I understand this is a duplicate of this question asked before, however I tried that and did not work:
#app.before_first_request
def create_tables():
from projectx.models.auth.user import User
from projectx.models.private_data.project import Project
db.create_all()
I also tried giving the same __table_args__ = {"schema": "testdb"} args to both models (I manually created the db with this name) and refer to db.ForeignKey('testdb.User.id) to no avail, the error is the same.
What am I missing here?
It seems I misunderstood some concepts about how this relationship abstraction works.
The foreign key reference is to the tablename and not the class name naturally.
I should have written db.ForeignKey('users.id').
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.
Okay, so I have the following. In user/models.py:
class User(UserMixin, SurrogatePK, Model):
__tablename__ = 'users'
id = Column(db.Integer, primary_key=True, index=True)
username = Column(db.String(80), unique=True, nullable=False)
email = Column(db.String(80), unique=False, nullable=False)
password = Column(db.String(128), nullable=True)
departments = relationship("Department",secondary="user_department_relationship_table", back_populates="users")
and in department/models.py:
user_department_relationship_table=db.Table('user_department_relationship_table',
db.Column('department_id', db.Integer,db.ForeignKey('departments.id'), nullable=False),
db.Column('user_id',db.Integer,db.ForeignKey('users.id'),nullable=False),
db.PrimaryKeyConstraint('department_id', 'user_id') )
class Department(SurrogatePK, Model):
__tablename__ = 'departments'
id = Column(db.Integer, primary_key=True, index=True)
name = Column(db.String(80), unique=True, nullable=False)
short_name = Column(db.String(80), unique=True, nullable=False)
users = relationship("User", secondary=user_department_relationship_table,back_populates="departments")
Using the flask development server locally this works totally fine. However, once I deploy to the standard python buildpack on heroku, the cpt/app.py loads both modules to register their blueprints:
from cpt import (
public, user, department
)
...
def register_blueprints(app):
app.register_blueprint(public.views.blueprint)
app.register_blueprint(user.views.blueprint)
app.register_blueprint(department.views.blueprint)
return None
and eventually errors out with the following:
sqlalchemy.exc.InvalidRequestError: When initializing mapper
Mapper|User|users, expression 'user_department_relationship_table'
failed to locate a name ("name 'user_department_relationship_table' is
not defined"). If this is a class name, consider adding this
relationship() to the class after
both dependent classes have been defined.
I'd like to know if there's a better way to organize these parts to avoid this error obviously, but I'm more curious why this organization works fine on the development server but blows up something fierce on gunicorn/heroku.
Well I can't explain the discrepancy between heroku and the dev server, but I got the error to go away by changing the Department mode from
users = relationship("Department",secondary="user_department_relationship_table", back_populates="users")
to
users = relationship("User", secondary=user_department_relationship_table, backref="departments")
which sets up the User model automatically which in turn means I can delete any mention of Department and the relationship table on that end.
¯\_(ツ)_/¯
I have the next models.py file:
from app import db, bcrypt
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
class BlogPost(db.Model):
__tablename__ = "posts"
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String, nullable=False)
desc = db.Column(db.String, nullable=False)
author_id = db.Column(db.Integer, ForeignKey('users.id'))
def __init__(self, title, desc):
self.title = title
self.desc = desc
def __repr__(self):
return "Titulo >> " + self.title
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
email = db.Column(db.String, nullable=False)
password = db.Column(db.String, nullable=False)
posts = relationship("BlogPost", backref="author")
def __init__(self, name, email, password):
self.name = name
self.email = email
self.password = password
def __repr__(self):
return "Usuario >> ", self.name
Then I ran:
python manage.py db init
and everything was fine, the thing is when I tried to modify my models file to make a migration.. I just change the line:
self.password = password
to:
self.password = bcrypt.generate_password_hash(password)
and when I ran:
python manage.py db migrate
it works, but when I tried to upgrade with:
python manage.py db upgrade
I get the next error:
"No support for ALTER of constraints in SQLite dialect")
NotImplementedError: No support for ALTER of constraints in SQLite dialect
Note: the database just has a few records for testing.. thank you!
Alembic has changed how SQLite migrations are done since most tutorials for Alembic were written. ALTER commands now need to use batch mode. This mode is still compatible with other databases, if you decide to switch from SQLite later.
For each table being altered, place all operations inside a with op.batch_alter_table('table_name'): block.
def upgrade():
with op.batch_alter_table('table_name'):
op.alter_column(...)