how to use primary and foreign keys in SQL ALchemy - python

I have the following two tables. User and Project.
I need User_ID and name to be projected in Project table columns user_ID and User respectively but i couldn't achieve it.
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
User_ID = db.Column(db.Integer, unique=True)
name = db.Column(db.String(20))
project = db.relationship('Project', backref='proj')
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
user = db.Column(db.String(50), db.ForeignKey("user.name"))
UserID = db.Column(db.Integer, db.ForeignKey("user.User_ID"))
customer = db.Column(db.String(50))
lead_office = db.Column(db.String(50))
phase = db.Column(db.String(50))

Try this ( it worked for me in similar project):
class User(db.Model):
User_ID = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(20))
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
id_user = db.Column(db.String(50), db.ForeignKey("User.User_ID"))
customer = db.Column(db.String(50))
lead_office = db.Column(db.String(50))
phase = db.Column(db.String(50))

Related

Querying user specific data in flask

I'm building an app that shows a database of different plant species. Each user sees the same table of plant species except for the "notes" column, which each user can edit to their own liking. This is the database structure I have created:
class Note(db.Model):
__tablename__ = 'plantdatabasenote'
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.Text(), nullable=False)
plant_id = db.Column(db.Integer, db.ForeignKey("plant.id"))
user_id = db.Column(db.Integer, db.ForeignKey("profile.id"))
class Plant(db.Model):
__tablename__ = 'plant'
id = db.Column(db.Integer, primary_key=True)
common_name = db.Column(db.String(200), nullable=False)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
notes = db.relationship("Note", backref="user_notes")
class Profile(db.Model):
__tablename__ = 'profile'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(200), unique=True, nullable=False)
I tried to retrieve the notes of user 1 with the following:
Plant.query.filter(Plant.notes.any(user_id=1)).all()
Unfortunately, this does not give me all the plants with the notes of user 1. Any idea how to fix this?

How to Perform filtering and sorting or filtering different column in Flask_SQLACLHEMY

I am creating a site where you can log in and then add your favorite animes and movies to your favorite list, for that I created a database and 3 tables User, Anime and Movie.
My database code:
from . import db
from flask_login import UserMixin
from sqlalchemy.sql import func
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150), unique=True)
password = db.Column(db.String(150))
first_name = db.Column(db.String(150))
anime = db.relationship('Anime')
movie = db.relationship('Movie')
class Movie(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(50), nullable=False)
date = db.Column(db.DateTime(timezone=True), default=func.now())
year = db.Column(db.Integer, nullable=False)
description = db.Column(db.String(400), nullable=False)
rating = db.Column(db.Float, nullable=True)
ranking = db.Column(db.Integer, nullable=True)
review = db.Column(db.String(50), nullable=True)
img_url = db.Column(db.String(250), nullable=False)
movie_link = db.Column(db.String(250), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
class Anime(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(50), nullable=False)
year = db.Column(db.Integer, nullable=False)
date = db.Column(db.DateTime(timezone=True), default=func.now())
description = db.Column(db.String(400), nullable=False)
rating = db.Column(db.Float, nullable=True)
ranking = db.Column(db.Integer, nullable=True)
review = db.Column(db.String(50), nullable=True)
img_url = db.Column(db.String(250), nullable=False)
anime_link = db.Column(db.String(250), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
I want to first filter all the data with the current user id
(all_anime = Anime.query.filter_by(id=current_user.id.).all())
then sort them according to the ratings given by the user
(all_anime = Anime.query.order_by(Anime.rating).all())
all_anime = User.anime.query.order_by(Anime.rating).all()
all_anime = db.session.query(Anime).filter_by(id=current_user.id).all()
print(all_anime)
for i in range(len(all_anime)):
all_anime[i].ranking = len(all_anime) - i
db.session.commit()
I know this snippet of code is wrong but I want to perform two different functions in two different columns how can I do it.
I also wanted to not accept the anime titles which are already present in the list of that user.
for that purpose, I have to filter the data with that user id
(anime_name = Anime.query.filter_by(id=current_user.id).all())
and then filter the data with the anime title
(anime_name = Anime.query.filter_by(title=data['canonicalTitle']).first()))
#views.route("/anime/find")
def find_anime():
anime_api_id = request.args.get("id")
if anime_api_id:
movie_api_url = f"https://kitsu.io/api/edge/anime//{anime_api_id}"
response = requests.get(movie_api_url)
data = response.json()['data']['attributes']
name = data["canonicalTitle"].replace(' ', '%20')
description = data['description'].rsplit('.', 1)[0]
# anime_name = User.anime.query.filter_by(title=data['canonicalTitle']).first()
# if anime_name:
# flash("Anime Already exists In The List.", category="error")
# else:
new_anime = Anime(
title=data['canonicalTitle'],
year=data['startDate'].split("-")[0],
img_url=data['posterImage']['medium'],
description=description,
anime_link=ANIME_SEARCH + name,
user_id=current_user.id
)
db.session.add(new_anime)
db.session.commit()
flash("Successfully Added.", category="success")
return redirect(url_for("views.edit_anime", id=new_anime.id))

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

Multiple relationships to the same SQLAlchemy model

I have a User table that has role column. role can be student, professor or admin. User table have relation with Course table.
If relationship is between Course and student it should be many to many relation but if relationship is between Course and professor it should be one to many.
How to define multi relationship between two table with different roles?
User Model
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
firstname = db.Column(db.String(40))
lastname = db.Column(db.String(40))
username = db.Column(db.String(40), nullable=False, unique=True)
password_hash = db.Column(db.String(100), nullable=False)
role = db.Column(db.SmallInteger, nullable=False, default=0)
create_at = db.Column(db.DateTime, default=datetime.datetime.utcnow)
update_at = db.Column(db.DateTime, default=datetime.datetime.utcnow)
# what should i write instead of bellow lines?
# courses = db.relationship('Course', secondary=student_course, backref='students', lazy='dynamic')
# OR
# courses = db.relationship('Course', backref='teacher', lazy='dynamic')
ROLE_STUDENT = 0
ROLE_PROFESSOR = 1
ROLE_ADMIN = 2
Course Model
class Course(db.Model):
id = db.Column(db.Integer, primary_key=True)
teacher_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
title = db.Column(db.String(120))

Categories