Many To Many Relation - delete item - flask

Models:
class Cecha(db.Model):
__tablename__='cechy'
id = db.Column(db.Integer, primary_key = True)
nazwa = db.Column(db.String)
cechy_asort = db.Table('cechy_asort',
db.Column('id_cechy', db.Integer, db.ForeignKey('cechy.id')),
db.Column('id_asortymentu', db.Integer, db.ForeignKey('asortymenty.id')))
class Asortyment(db.Model):
__tablename__ = 'asortymenty'
id = db.Column(db.Integer, primary_key=True)
nazwa = db.Column(db.String(64), unique = True, index = True, nullable = False)
zamowienia = db.relationship('Zamowienie', backref='asortyment', lazy='dynamic', cascade='all,delete')
cecha = db.relationship('Cecha', secondary=cechy_asort, backref=db.backref('asortymenty', lazy='dynamic'), lazy='joined')
def ma_ceche(self, id_cechy):
cecha = Cecha.query.filter_by(id=id_cechy).first()
if cecha is None:
return False
if not cecha in self.cecha:
return False
return cecha
def dodaj_ceche(self,id_cechy):
if not self.ma_ceche(id_cechy):
cecha = Cecha.query.filter_by(id=id_cechy).first()
self.cecha.append(cecha)
db.session.commit()
def usun_ceche(self,id_cechy):
if self.ma_ceche(id_cechy):
cecha = Cecha.query.filter_by(id=id_cechy).first()
self.cecha.remove(cecha)
db.session.commit()
class Grupa_asort(db.Model):
__tablename__ = 'grupy_asort'
id = db.Column(db.Integer, primary_key=True)
nazwa = db.Column(db.String(64), unique = True, index = True)
asortymenty = db.relationship('Asortyment', backref = 'grupa_asort', lazy='dynamic', cascade='all,delete')
The problem is with deleting item from table Asortyment if there is relation:
Asortyment.query.filter_by(id_grupy=id_grupy).delete()
The error is:
cursor.execute(statement, parameters)
psycopg2.errors.ForeignKeyViolation: update or delete on table "asortymenty" violates foreign key constraint "cechy_asort_id_asortymentu_fkey" on table "cechy_asort"
DETAIL: Key (id)=(1446) is still referenced from table "cechy_asort".

cechy_asort = db.Table('cechy_asort',
db.Column('id_cechy', db.Integer, db.ForeignKey('cechy.id')),
db.Column('id_asortymentu', db.Integer, db.ForeignKey('asortymenty.id', ondelete="CASCADE")))

Related

sqlite3.IntegrityError: FOREIGN KEY constraint failed

I have an sqlite database in my flask server with three tables as seen below:
from database import db
class ChordNode(db.Model):
__tablename__ = 'chordnode'
id = db.Column(db.Integer, primary_key=True)
hashed_id = db.Column(db.String)
successor = db.Column(db.String)
predecessor = db.Column(db.String)
is_bootstrap = db.Column(db.Boolean, default=False)
storage = db.relationship("KeyValuePair")
node_map = db.relationship("NodeRecord", cascade="delete")
def __repr__(self):
return 'Chord node {}, with successor: {}, predecessor: {}, ' \
'bootstrap: {}'.format(self.hashed_id, self.successor,
self.predecessor, self.is_bootstrap)
class KeyValuePair(db.Model):
__tablename__ = 'keyvaluepair'
id = db.Column(db.Integer, primary_key=True)
chordnode_id = db.Column(db.String, db.ForeignKey('chordnode.hashed_id'), nullable=True)
hashed_id = db.Column(db.String)
value = db.Column(db.String)
def __repr__(self):
return '<key-value pair: {}:{}, responsible Chord node: {}'.format(self.hashed_id,
self.value, self.chordnode_id)
class NodeRecord(db.Model):
__tablename__ = 'noderecord'
id = db.Column(db.Integer, primary_key=True)
bootstrap_id = db.Column(db.Integer, db.ForeignKey('chordnode.id'), nullable=False)
ip_port = db.Column(db.String)
def __repr__(self):
return 'Node record {} on boo
tstrap node with id {}'.format(self.ip_port,
self.bootstrap_id)
When i insert into ChordNode class or Noderecord everything works fine but inserting a record into KeyValuePair produces this error:
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) FOREIGN KEY constraint failed
However KeyValuePair's foreign key is exactly the same as ChordNode's corresponding.
Any ideas about what else could be wrong with this and why this error occurs?

How to resolve this flask sqlalchemy error "sqlalchemy.exc.InvalidRequestError"?

from datetime import datetime
from pack import db,login_manager
from flask_login import UserMixin
# SQLALCHEMY_TRACK_MODIFICATIONS = False
#login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
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(150), unique = True, nullable = False)
password = db.Column(db.String(60), nullable = False)
profile_pic = db.Column(db.String(20), nullable = False, default = "default_profile_pic.jpg")
posts = db.relationship('Post', backref = 'author', lazy = True)
comments = db.relationship('Comment', backref = 'commentor', lazy = True)
def __repr__(self):
return f"User('{self.username}','{self.email}','{self.profile_pic}')"
class Post(db.Model,UserMixin):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable = False)
date_posted = db.Column(db.DateTime, nullable = False, default = datetime.utcnow)
content = db.Column(db.Text, nullable = False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable = False)
post_comments = db.relationship('Comment', backref = 'commentor', lazy = 'dynamic')
def __repr__(self):
return f"Post('{self.title}','{self.content}','{self.date_posted}','{self.comments}')"
class Comment(db.Model):
id = db.Column(db.Integer, primary_key=True)
comment = db.Column(db.String(100000), nullable = False)
timestamp = db.Column(db.DateTime, nullable = False, default = datetime.utcnow, index = True)
user_comment_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable = False)
post_comment_id = db.Column(db.Integer, db.ForeignKey('post.id'))
def __repr__(self):
return f"Post('{self.comment}','{self.user_comment_id}','{self.post_comment_id}')"
This give this error:
sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'mapped class Post->post'. Original exception was: Error creating backref 'commentor' on relationship 'Post.post_comments': property of that name exists on mapper 'mapped class Comment->comment'
Please help me resolve this error. I want to add a feature to comment on a post and for that i am trying to connect the Comment model with Post and User models.
In your error you have: Post.post_comments': property of that name exists on mapper 'mapped class Comment->comment.
It seems that in User you have comments which creates a backref 'commentor' in Comment and in Post you have post_comments which also creates a backref 'commentor' in Comment.
For example in Post, you can change post_comment to :
post_comments = db.relationship('Comment', backref = 'post_commented', lazy = 'dynamic')
Edit:
When defining a One to Many relationship with backref parameter, there is no need of user_id (in Post), user_comment_id (in Comment), post_comment_id (in Comment): Simply remove them.
You should have another look at https://docs.sqlalchemy.org/en/13/orm/basic_relationships.html#one-to-many (the backref part)

Flask SQLAlchemy join query returning [<Service 2>]

Why is the code
res = Service.query.join(Counter,(Counter.service_id == Service.id)).filter(Service.dept_id == deptId).all()
print(res)
is always returning []. I want the data in array format.
My Models are as below. Please excuse me if the question is very primitive. I am very new to SQL Alchemy.
class Service(FlaskSerializeMixin,db.Model):
id = db.Column(db.Integer, primary_key=True)
ser_name = db.Column(db.String(100),unique=True,nullable=False)
ser_prefix = db.Column(db.String(1),unique=True,nullable=False)
cnt_num = db.Column(db.Integer,nullable=False)
pri_q_flg = db.Column(db.Boolean,nullable=False)
dept_id = db.Column(db.Integer, db.ForeignKey('department.id'),nullable=False)
cre_time =db.Column(db.DateTime)
chg_time =db.Column(db.DateTime)
__table_args__ = (
db.UniqueConstraint('ser_name', 'dept_id', name='unique_service_dept'),
)
pqueues = db.relationship('PQueue',backref='service',lazy=True)
counters = db.relationship('Counter',backref='service',lazy=True)
class Counter(FlaskSerializeMixin,db.Model):
id = db.Column(db.Integer, primary_key=True)
cnt_num = db.Column(db.Integer,nullable=False)
service_id = db.Column(db.Integer, db.ForeignKey('service.id'),nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
cre_time =db.Column(db.DateTime)
chg_time =db.Column(db.DateTime)
__table_args__ = (
db.UniqueConstraint('cnt_num', 'service_id', name='unique_cnt_service'),
)

Selecting Rows based on multiple related tables

I have the following models:
modifiers = db.Table('modifiers',
db.Column('modifier', db.Integer, db.ForeignKey('modifier.id')),
db.Column('modified_ingredient', db.Integer, db.ForeignKey('modified_ingredient.id')),
)
modified_ingredients = db.Table('modified_ingredients',
db.Column('recipe', db.Integer, db.ForeignKey('recipe.id')),
db.Column('modified_ingredient', db.Integer, db.ForeignKey('modified_ingredient.id'))
)
class Recipe(db.Model):
__tablename__ = 'recipe'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(256))
description = db.Column(db.Text)
directions = db.Column(db.Text)
prep_time = db.Column(db.Integer)
cook_time = db.Column(db.Integer)
image = db.Column(db.LargeBinary())
ingredients = db.relationship('ModifiedIngredient', secondary=modified_ingredients)
class Ingredient(db.Model):
__tablename__ = 'ingredient'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30), index=True, unique=True)
mod_ing = db.relationship("ModifiedIngredient")
class Modifier(db.Model):
__tablename__ = 'modifier'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30), index=True, unique=True)
class ModifiedIngredient(db.Model):
__tablename__ = 'modified_ingredient'
id = db.Column(db.Integer, primary_key=True)
amount = db.Column(db.Integer)
unit = db.Column(db.String(20))
ingredient = db.Column(db.Integer, db.ForeignKey('ingredient.id'))
modifiers = db.relationship('Modifier', secondary=modifiers,
backref=db.backref('modifiers', lazy='dynamic'), lazy='dynamic')
I'm trying to retrieve recipes based on having two or more ingredients.
I'm able to retreive recipes that have single ingredients with the following:
db.session.query(models.Recipe).join(models.ModifiedIngredient, models.Recipe.ingredients).join(models.Ingredient).filter(models.Ingredient.name == 'garlic')
However, adding multiple filters return 0 results. This makes sense, it's matching a single ingredient to a recipe, and an ingredient can't be both garlic and onion. So, how would I accomplish this?
The solution I have found is to use an intersect.
Issue multiple queries with each of your filter options:
q1 = db.session.query(models.Recipe).join(models.ModifiedIngredient, models.Recipe.ingredients).join(models.Ingredient).filter(models.Ingredient.name == 'garlic')
q2 = db.session.query(models.Recipe).join(models.ModifiedIngredient, models.Recipe.ingredients).join(models.Ingredient).filter(models.Ingredient.name == 'onion')
q3 = q1.intersect(q2)
And q3 will have all items that have both 'onion' and 'garlic'

Flask-appbuilder many-to-may relationship sqlalchemy.exc.NoReferencedTableError Error

I've read through all of these (https://stackoverflow.com/search?q=sqlalchemy.exc.NoReferencedTableError%3A), the Flask-appbuilder docs, the sqlalchemy docs, and the Flask-sqlalchemy docs and more. Unfortunately, I can't find any full examples of a many-to-many sqlalchemy relationship.
I have a python Flask app using flask-appbuilder (which relies on flask-sqlalchemy). My app/model.py file has this:
field_feature_association = Table('field_feature_association',Base.metadata,
Column('field_id', Integer, ForeignKey('field.id')),
Column('feature_id',Integer, ForeignKey('feature.id')),
schema="main"
)
class field(Model):
__tablename__ = 'field'
id = Column(Integer, primary_key=True)
name = Column(String(70), nullable=False)
database_type = Column(String(70)) #varchar(255), text, int
joinable_to = Column(Text())
notes = Column(Text()) #don't use this for X
table_id = Column(Integer, ForeignKey('table.id'))
table = relationship("table")
features = relationship("feature",
secondary = field_feature_association,
backref = backref('fields'),
)
def __repr__(self):
return self.name
class feature(Model):
__tablename__ = 'feature'
id = Column(Integer, primary_key=True)
name = Column(String(70), unique = True, nullable=False)
field_id = Column(Integer, ForeignKey('field.id'))
#field = relationship("field")
def __repr__(self):
return self.name
It's generating this error:
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'field_feature_association.feature_id' could not find table 'feature' with which to generate a foreign key to target column 'id'
Thoughts on how to fix this error?
Here is a working sample of many-to-many in SQLAlchemy. Moreover I modified your model and it works fine:
field_feature_association = db.Table('field_feature_association', db.Model.metadata,
db.Column('field_id', db.Integer, db.ForeignKey('field.id')),
db.Column('feature_id', db.Integer, db.ForeignKey('feature.id')),
schema="main"
)
class Field(db.Model):
__tablename__ = 'field'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(70), nullable=False)
database_type = db.Column(db.String(70)) # varchar(255), text, int
joinable_to = db.Column(db.Text())
notes = db.Column(db.Text()) # don't use this for X
features = db.relationship("Feature",
secondary=field_feature_association,
backref=db.backref('fields'),
)
def __repr__(self):
return self.name
class Feature(db.Model):
__tablename__ = 'feature'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(70), unique=True, nullable=False)
field_id = db.Column(db.Integer, db.ForeignKey('field.id'))
# field = relationship("field")
def __repr__(self):
return self.name
and this is how to use it:
field = Field()
field.name="filed1"
feature = Feature()
feature.name = "feature1"
field.features.append(feature)
db.session.add(field)
db.session.commit()
My database object is imported as ’db’ and I have used it explicitely to refer to other types.