Table not migrating - Flask-SQLAlchemy - python

I have the following line of code in my models.py file:
referalls = db.table('referrals',
db.Column('referrer', db.String(64), db.ForeignKey('User.email')),
db.Column('referral', db.String(64), db.ForeignKey('User.email'))
)
This is to create a many-to-many relationship table for a referral system I'm trying to implement.
However, when I run my migrate/upgrade command, Alembic is not creating the table.
I'm following the official Flask-SQLAlchemy tutorial: http://flask-sqlalchemy.pocoo.org/2.1/models/
For clarity's sake, here's the User class:
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))
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)
...
I believe my problem might be the following line (pulled from the official Flask-SQLAlchemy documentation):
tags = db.relationship('Tag', secondary=tags,
backref=db.backref('pages', lazy='dynamic'))
I tried:
referalls = db.relationship('User', secondary=referalls,
backref=db.backref('users', lazy='dynamic'))
But same thing: Alembic's not identifying the referrals table.
Any input on this is greatly appreciated.

I had the same problem and solved by using a class inheriting db.Model instead of declaring a table the way the flask tutorial suggests. When I defined everything as a class it just worked.
Possibly its a problem with alembic.
Try:
class Referalls(db.Model):
__tablename__ = 'referalls'
referrer = db.Column(db.String(64), db.ForeignKey('User.email'))
referral = db.Column(db.String(64), db.ForeignKey('User.email'))

Related

Setting up One-to-Many relationship in sqlalchemy, but keep getting AmbiguousForeignKeysError

I'm trying to set up a one-to-many relation between two tables (User and BlogPost, respectively).
I tried copying what the course(?) solution for this and still get foreign-key errors. What do I have wrong? Or, is this actually an issue with sqlalchemy (v. 1.3.19)?
I've even tried upgrading to the current version (1.4.31) with no success. I was getting run-time errors (flask page error reports) usually around the posts = BlogPost.query.all() line in home(). Now that I've upgraded the package, I'm getting a build-time error (AttributeError: can't set attribute) stemming from the db.create_all() line.
I've also tried deleting the db, again with no success.
Please leave a comment if this was answered somewhere else or if more info is needed.
Here's a snippet from Main.py:
db = SQLAlchemy(app)
class User(db.Model, UserMixin):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(250), nullable=False)
password = db.Column(db.String(250), nullable=False)
name = db.Column(db.String(100), nullable=False)
posts = relationship("BlogPost", back_populates="author")
class BlogPost(db.Model):
__tablename__ = "blog_posts"
id = db.Column(db.Integer, primary_key=True)
author_id = db.Column(db.Integer, db.ForeignKey("users.id"))
title = db.Column(db.String(250), unique=True, nullable=False)
subtitle = db.Column(db.String(250), nullable=False)
date = db.Column(db.String(250), nullable=False)
body = db.Column(db.Text, nullable=False)
img_url = db.Column(db.String(250), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
author = relationship("User", back_populates="posts")
db.create_all()
#app.route('/')
def home():
posts = BlogPost.query.all()
user = current_user
return render_template("index.html", all_posts=posts, user=user)
I still don't know what's wrong, but the following code works in a newer project. Like I said in one of the comments: I suspect that there's an issue with my current PyCharm project.
db = SQLAlchemy(app)
class User(UserMixin, db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(100), unique=True)
password = db.Column(db.String(100))
name = db.Column(db.String(100))
posts = relationship("BlogPost", back_populates="author")
class BlogPost(db.Model):
__tablename__ = "blog_posts"
id = db.Column(db.Integer, primary_key=True)
author_id = db.Column(db.Integer, db.ForeignKey("users.id"))
author = relationship("User", back_populates="posts")
title = db.Column(db.String(250), unique=True, nullable=False)
subtitle = db.Column(db.String(250), nullable=False)
date = db.Column(db.String(250), nullable=False)
body = db.Column(db.Text, nullable=False)
img_url = db.Column(db.String(250), nullable=False)
db.create_all()
#app.route('/')
def home():
posts = BlogPost.query.all()
return render_template("index.html", all_posts=posts)

how to filter associated data in flask and Flask-SQLAlchemy?

I have just started learning flask and Flask-SQLAlchemy and created following models:-
User:-
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, db.Sequence('users_id_seq'), primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
created_at = db.Column(db.TIMESTAMP(timezone=True), default=helpers.get_utc_now, nullable=False)
updated_at = db.Column(db.TIMESTAMP(timezone=True), default=helpers.get_utc_now, nullable=False, onupdate=helpers.get_utc_now)
def __repr__(self):
return '<User %r>' % self.username
Teacher:-
class Teacher(db.Model):
__tablename__ = "teachers"
id = db.Column(db.Integer, db.Sequence("teachers_id_seq"), primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
created_at = db.Column(db.TIMESTAMP(timezone=True), default=helpers.get_utc_now, nullable=False)
updated_at = db.Column(
db.TIMESTAMP(timezone=True), default=helpers.get_utc_now, nullable=False, onupdate=helpers.get_utc_now
)
def __repr__(self):
return "<Teacher %r>" % self.id
Students:-
class Student(db.Model):
__tablename__ = 'students'
id = db.Column(db.Integer, db.Sequence('students_id_seq'), primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
created_at = db.Column(db.TIMESTAMP(timezone=True), default=helpers.get_utc_now, nullable=False)
updated_at = db.Column(db.TIMESTAMP(timezone=True), default=helpers.get_utc_now, nullable=False, onupdate=helpers.get_utc_now)
def __repr__(self):
return '<Student %r>' % self.id
Assignment:-
class Assignment(db.Model):
__tablename__ = "assignments"
id = db.Column(db.Integer, db.Sequence("assignments_id_seq"), primary_key=True)
student_id = db.Column(db.Integer, db.ForeignKey(Student.id), nullable=False)
teacher_id = db.Column(db.Integer, db.ForeignKey(Teacher.id), nullable=True)
content = db.Column(db.Text)
grade = db.Column(BaseEnum(GradeEnum))
state = db.Column(BaseEnum(AssignmentStateEnum), default=AssignmentStateEnum.DRAFT, nullable=False)
created_at = db.Column(db.TIMESTAMP(timezone=True), default=helpers.get_utc_now, nullable=False)
updated_at = db.Column(
db.TIMESTAMP(timezone=True), default=helpers.get_utc_now, nullable=False, onupdate=helpers.get_utc_now
)
def __repr__(self):
return "<Assignment %r>" % self.id
Now in my application an student can create, edit and submit an assignment.
And when student submit an assignment, it will submitted to the particular teacher.
When student creates an assignment status field in assignment set to DRAFT, and when he submitted the assignment it will changes to SUBMITTED.
I am totally new to flask and Flask-SQLAlchemy and back-end stuff,and unable to figure out how to fetch assignments submitted to particular teacher.
I have written the following query as well but got wrong result**:-**
got empty data but there are data available in db.
#classmethod # is written is assignment class
def get_assignments_by_teacher(cls, teacher_id):
return cls.filter(cls.teacher_id == teacher_id).all()
from where i am calling this method:-
teacher_assignments = Assignment.get_assignments_by_teacher(p.teacher_id)
Thanks in advance.
Hope to here from you soon.
NOTE:- you can also suggest me better title for this post as well.
If you are trying to query all assignments for a certain teacher, you can achieve this by using sqlalchemy's query function with a filter.
Docs
teacher_assignments = Assignment.query.filter(Assignment.teacher_id == teacher_id).all()
You can also add something called a backref on your teacher model definition like this:
assignments = relationship("Assignment", backref="teacher")
Then, if you have your teacher object, you can access their assignments like this without writing any queries:
teacher.assignments
See here for more info on Backref

Sqlite3 relational database

I am trying to connect the id in the user class to the user_id in task class. I read the documentation from sqlalchemy and I have a hard time understanding the db.relationship part. I have also encountered a problem when updating the tables, when I ran db.create_all() in the terminal, these classes wasn't updated (it previously worked). Is this because the relational database I set up was wrong?
Here is my classes
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), nullable=False, unique=True)
password = db.Column(db.String(80), nullable=False)
class Task(db.Model):
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text)
complete =db.Column(db.Boolean, default=False)
And here is the documentation example
class Category(db.Model, CRUDMixin):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
# Post table (in app/models/post.py)
class Post(db.Model, CRUDMixin):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80))
body = db.Column(db.Text)
pub_date = db.Column(db.DateTime, default=datetime.utcnow)
# One to many relationship
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
category = db.relationship('Category', backref=db.backref('posts'))
Any answers or opinions will be greatly appreciated, thankyou.

Use Flask-SqlAlchemy to query relationship database

I'm trying to use Flask-SQLAlchemy to query out database for the user profile page
So far I don't have a solution for this problem, only able to query all the User data by using users.query.all()
Each user has their own role_id, department_id, researchfield_id.
How can i query out all the Role, Department, ResearchField data that has relationship with User through ID?
class User(UserMixin, db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
password_hash = db.Column(db.String(128))
is_admin = db.Column(db.Boolean, default=False)
department_id = db.Column(db.Integer, db.ForeignKey('departments.id'))
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
research_id = db.Column(db.Integer, db.ForeignKey('researchfields.id'))
class Department(db.Model):
__tablename__ = "departments"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(sqlalchemy.types.NVARCHAR(100), unique=True)
user = db.relationship('User', backref='department',
lazy='dynamic')
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(sqlalchemy.types.NVARCHAR(100), unique=True)
users = db.relationship('User', backref='role',
lazy='dynamic')
class ResearchField(db.Model):
__tablename__ = "researchfields"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(60), index=True)
parent_id = db.Column(db.Integer, db.ForeignKey("researchfields.id") , nullable=True)
users = db.relationship('User', backref='researchfield', lazy='dynamic')
If I understand correctly, what you're seeking for is a way to filter out users based on a specific model. Because in your example, the other way around is redundant - every user has only one department, so no need to filter out departments for that user. In order to achieve that, I would use the backref method provided by SQLAlchemy from the User model.
Here's an example consisting of two of the models:
from sqlalchemy.orm import backref
class User(UserMixin, db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
password_hash = db.Column(db.String(128))
is_admin = db.Column(db.Boolean, default=False)
department_id = db.Column(db.Integer, db.ForeignKey('departments.id'))
department = db.relationship("Department", backref=backref("users", lazy="dynamic"))
class Department(db.Model):
__tablename__ = "departments"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(sqlalchemy.types.NVARCHAR(100), unique=True)
Now you can use:
department = Department.query.filter_by(id=1).first()
print(department.users.filter_by(is_admin=True).all()) # get all admins with that department
Every user has only one department, so you could just get the user's department by:
user = User.query.filter_by(id=1).first()
print(user.department) # prints Department object

many to many relationship with three tables (sql-alchemy)

I am trying to get a many to many relationship working. I have three tables
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
class Groups(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(1000))
class Members(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
group_id = db.Column(db.Integer, db.ForeignKey('groups.id'))
I would like to have the option group.members, which should give me all User objects which are member of that group. I implemented it the following way
members = db.relationship('User', secondary="join(Members, User, Members.user_id == User.id)", primaryjoin="and_(Groups.id == Members.group_id)")
this seems to work, but when I delete a group it gives me (sometimes) the error
AttributeError: 'Join' object has no attribute 'delete'
so I guess this is not the right way to implement such a relation.
Any ideas how to do this correctly?
thanks
carl
Perhaps a simpler way to implement this is as follows (adapted from the documentation on Flask-SQLAlchemy
members = db.Table('members',
db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
db.Column('group_id', db.Integer, db.ForeignKey('groups.id'))
)
class Groups(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(1000))
members = db.relationship('User', secondary=members, backref=db.backref('group', lazy='dynamic'))
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
Instead of using a Model for the joining table (members), let's just use a simple table.
With this configuation, you can easily add/remove members and groups:
u = User(username='matt')
g = Groups(name='test')
db.session.add(u)
db.session.add(g)
db.session.commit()
g.members.append(u)
db.session.commit()
db.session.delete(g)
db.session.commit()

Categories