从 many-to-many SQL-Alchemy 和 Postgresql 中删除
Deleting from many-to-many SQL-Alchemy and Postgresql
我正在尝试从 sql-alchemy 中的 many-to-many 关系中删除 child object。
我不断收到以下错误:
StaleDataError: DELETE statement on table 'headings_locations' expected to delete 1 row(s); Only 2 were matched.
我查看了一些现有的 stackexchange 问题
(SQLAlchemy DELETE Error caused by having a both lazy-load AND a dynamic version of the same relationship, SQLAlchemy StaleDataError on deleting items inserted via ORM sqlalchemy.orm.exc.StaleDataError, , Delete from Many to Many Relationship in MySQL)
关于这个以及阅读文档,但无法弄清楚为什么它不起作用。
我定义关系的代码如下:
headings_locations = db.Table('headings_locations',
db.Column('id', db.Integer, primary_key=True),
db.Column('location_id', db.Integer(), db.ForeignKey('location.id')),
db.Column('headings_id', db.Integer(), db.ForeignKey('headings.id')))
class Headings(db.Model):
__tablename__ = "headings"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
version = db.Column(db.Integer, default=1)
special = db.Column(db.Boolean(), default=False)
content = db.relationship('Content', backref=db.backref('heading'), cascade="all, delete-orphan")
created_date = db.Column(db.Date, default=datetime.datetime.utcnow())
modified_date = db.Column(db.Date, default=datetime.datetime.utcnow(), onupdate=datetime.datetime.utcnow())
def __init__(self, name):
self.name = name
class Location(db.Model):
__tablename__ = "location"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True)
account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
version = db.Column(db.Integer, default=1)
created_date = db.Column(db.Date, default=datetime.datetime.utcnow())
modified_date = db.Column(db.Date, default=datetime.datetime.utcnow())
location_prefix = db.Column(db.Integer)
numbers = db.relationship('Numbers', backref=db.backref('location'), cascade="all, delete-orphan")
headings = db.relationship('Headings', secondary=headings_locations,
backref=db.backref('locations', lazy='dynamic', cascade="all"))
def __init__(self, name):
self.name = name
而我的删除代码如下:
@content_blueprint.route('/delete_content/<int:location_id>/<int:heading_id>')
@login_required
def delete_content(location_id, heading_id):
import pdb
pdb.set_trace()
location = db.session.query(Location).filter_by(id = location_id).first()
heading = db.session.query(Headings).filter_by(id = heading_id).first()
location.headings.remove(heading)
#db.session.delete(heading)
db.session.commit()
flash('Data Updated, thank-you')
return redirect(url_for('content.add_heading', location_id=location_id))
无论我尝试删除 child object(db.session.delete(标题)或 location.headings.remove(标题),我仍然遇到相同的错误。
非常感谢任何帮助。
我的数据库是postgresql。
编辑:
我添加关系的代码:
new_heading = Headings(form.new_heading.data)
db.session.add(new_heading)
location.headings.append(new_heading)
db.session.commit()
我认为错误消息是正确的:确实在您的数据库中有 2 行 link Location
和 Heading
实例。在这种情况下,您应该首先找出发生这种情况的地点和原因,并防止再次发生这种情况
首先,为了证实这个假设,您可以运行对您的数据库进行以下查询:
q = session.query(
headings_locations.c.location_id,
headings_locations.c.heading_id,
sa.func.count().label("# connections"),
).group_by(
headings_locations.c.location_id,
headings_locations.c.heading_id,
).having(
sa.func.count() > 1
)
假设,假设得到证实,通过手动删除数据库中的所有重复项(每个只保留一个)来修复它。
之后,添加一个UniqueConstraint到你的headings_locations
table:
headings_locations = db.Table('headings_locations',
db.Column('id', db.Integer, primary_key=True),
db.Column('location_id', db.Integer(), db.ForeignKey('location.id')),
db.Column('headings_id', db.Integer(), db.ForeignKey('headings.id')),
db.UniqueConstraint('location_id', 'headings_id', name='UC_location_id_headings_id'),
)
注意需要添加到数据库中,添加到sqlalchemy
模型中是不够的
现在错误插入重复项的代码将因违反唯一约束异常而失败,您可以解决问题的根源。
我正在尝试从 sql-alchemy 中的 many-to-many 关系中删除 child object。
我不断收到以下错误:
StaleDataError: DELETE statement on table 'headings_locations' expected to delete 1 row(s); Only 2 were matched.
我查看了一些现有的 stackexchange 问题
(SQLAlchemy DELETE Error caused by having a both lazy-load AND a dynamic version of the same relationship, SQLAlchemy StaleDataError on deleting items inserted via ORM sqlalchemy.orm.exc.StaleDataError,
我定义关系的代码如下:
headings_locations = db.Table('headings_locations',
db.Column('id', db.Integer, primary_key=True),
db.Column('location_id', db.Integer(), db.ForeignKey('location.id')),
db.Column('headings_id', db.Integer(), db.ForeignKey('headings.id')))
class Headings(db.Model):
__tablename__ = "headings"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
version = db.Column(db.Integer, default=1)
special = db.Column(db.Boolean(), default=False)
content = db.relationship('Content', backref=db.backref('heading'), cascade="all, delete-orphan")
created_date = db.Column(db.Date, default=datetime.datetime.utcnow())
modified_date = db.Column(db.Date, default=datetime.datetime.utcnow(), onupdate=datetime.datetime.utcnow())
def __init__(self, name):
self.name = name
class Location(db.Model):
__tablename__ = "location"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True)
account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
version = db.Column(db.Integer, default=1)
created_date = db.Column(db.Date, default=datetime.datetime.utcnow())
modified_date = db.Column(db.Date, default=datetime.datetime.utcnow())
location_prefix = db.Column(db.Integer)
numbers = db.relationship('Numbers', backref=db.backref('location'), cascade="all, delete-orphan")
headings = db.relationship('Headings', secondary=headings_locations,
backref=db.backref('locations', lazy='dynamic', cascade="all"))
def __init__(self, name):
self.name = name
而我的删除代码如下:
@content_blueprint.route('/delete_content/<int:location_id>/<int:heading_id>')
@login_required
def delete_content(location_id, heading_id):
import pdb
pdb.set_trace()
location = db.session.query(Location).filter_by(id = location_id).first()
heading = db.session.query(Headings).filter_by(id = heading_id).first()
location.headings.remove(heading)
#db.session.delete(heading)
db.session.commit()
flash('Data Updated, thank-you')
return redirect(url_for('content.add_heading', location_id=location_id))
无论我尝试删除 child object(db.session.delete(标题)或 location.headings.remove(标题),我仍然遇到相同的错误。
非常感谢任何帮助。
我的数据库是postgresql。
编辑: 我添加关系的代码:
new_heading = Headings(form.new_heading.data)
db.session.add(new_heading)
location.headings.append(new_heading)
db.session.commit()
我认为错误消息是正确的:确实在您的数据库中有 2 行 link Location
和 Heading
实例。在这种情况下,您应该首先找出发生这种情况的地点和原因,并防止再次发生这种情况
首先,为了证实这个假设,您可以运行对您的数据库进行以下查询:
q = session.query( headings_locations.c.location_id, headings_locations.c.heading_id, sa.func.count().label("# connections"), ).group_by( headings_locations.c.location_id, headings_locations.c.heading_id, ).having( sa.func.count() > 1 )
假设,假设得到证实,通过手动删除数据库中的所有重复项(每个只保留一个)来修复它。
之后,添加一个UniqueConstraint到你的
headings_locations
table:headings_locations = db.Table('headings_locations', db.Column('id', db.Integer, primary_key=True), db.Column('location_id', db.Integer(), db.ForeignKey('location.id')), db.Column('headings_id', db.Integer(), db.ForeignKey('headings.id')), db.UniqueConstraint('location_id', 'headings_id', name='UC_location_id_headings_id'), )
注意需要添加到数据库中,添加到sqlalchemy
模型中是不够的
现在错误插入重复项的代码将因违反唯一约束异常而失败,您可以解决问题的根源。