我正在尝试从 sql-alchemy 中的多对多关系中删除一个子对象。
我不断收到以下错误:
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 , SQLAlchemy Attempting to Twice Delete Many to Many Secondary Relationship , 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))
无论我尝试删除子对象(db.session.delete(heading) 或 location.headings.remove(heading))的哪种方式,我仍然会遇到同样的错误。
非常感谢任何帮助。
我的数据库是postgresql。
编辑: 我添加关系的代码:
new_heading = Headings(form.new_heading.data)
db.session.add(new_heading)
location.headings.append(new_heading)
db.session.commit()
最佳答案
我假设错误消息是正确的:确实在您的数据库中有 2 行链接 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
表: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
模型中是不够的。
现在,错误插入重复项的代码将因违反唯一约束异常而失败,您可以解决问题的根源。
关于postgresql - 从多对多 SQLAlchemy 和 Postgresql 中删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31768652/