从多对多SQL-Alchemy和Postgresql中删除 [英] Deleting from many-to-many SQL-Alchemy and Postgresql

查看:396
本文介绍了从多对多SQL-Alchemy和Postgresql中删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从sql-alchemy中的多对多关系中删除一个子对象。



我不断收到以下错误:

  StaleDataError:表'headings_locations'上的DELETE语句预计删除1行;只有两个匹配。 

我查看了一些现有的stackexchange问​​题
SQLAlchemy DELETE由于有一个懒惰负载和动态版本的相同的关系, ORM-exc> SQLAlchemy StaleDataError删除通过ORM插入的项目sqlalchemy.orm.exc.StaleDataError , SQLAlchemy试图两次删除多对多次关系关于这个以及阅读文档我不知道为什么它不工作。

定义关系的代码如下所示:

  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.Model):
__tablename__ =标题
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.ut c)(),onupdate = datetime.datetime.utcnow())

def __init __(self,name):
self.name = name



类位置(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,默认值= 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,删除孤儿)
headings = db.relationship('Headings',secondary = headings_locations,
backref = db.backref('locations',lazy ='dynamic',cascade =all))


def __init __(self,na我):
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(标题)
db.session.commit()
flash('Data Updated,thank-you')
return redirect(url_for('content.add_heading',location_id = location_id) )

无论如何,我尝试删除子对象(db.session.delete(标题)或位置



我的数据库Postgresql。

编辑:
我的代码增加了关系:

  new_heading =标题(form.new_heading.data)
db.session.add(new_heading)
location.headings.append(new_heading)
db.session.commit()


解决方案

我会假定错误信息是正确的:在你的数据库中有两行链接 Location Heading 实例。在这种情况下,您应该首先了解在哪里以及为什么会发生这种情况,并防止再次发生这种情况。


  1. ,为了确认这个假设,你可以对你的数据库运行以下查询:

    $ $ $ $ $ c $ q $ session.query

    ).group_by(
    headings_locations。)。 c.location_id,
    headings_locations.c.heading_id,
    ).having(
    sa.func.count()> 1

  2. 然后,添加
    headings_locations 表格中添加:constraints.html#sqlalchemy.schema.UniqueConstraintrel =nofollow> UniqueConstraint

      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'),


请注意,您需要将其添加到数据库中,将它添加到<$ c

现在错误地插入重复项的代码会失败并产生唯一的约束违例异常,你可以修复问题的根源。


I'm trying to delete a child object from a many-to-many relationship in sql-alchemy.

I keep getting the following error:

StaleDataError: DELETE statement on table 'headings_locations' expected to delete 1 row(s); Only 2 were matched.

I have looked at a number of the existing stackexchange questions (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) regarding this as well as read the documentation and can't figure out why it isn't working.

My code defining the relationships is as follows:

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

And my delete code is as follows:

@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))

Whichever way i try and remove the child object (db.session.delete(heading) or location.headings.remove(heading) I still get the same error.

Any help is much appreciated.

My database is postgresql.

Edit: My code which adds the relationship:

        new_heading = Headings(form.new_heading.data)
        db.session.add(new_heading)
        location.headings.append(new_heading)
        db.session.commit()

解决方案

I would assume that the error message is correct: indeed in your database you have 2 rows which link Location and Heading instances. In this case you should find out where and why did this happen in the first place, and prevent this from happening again

  1. First, to confirm this assumption, you could run the following query against your database:

    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
    )
    

  2. Assuming, the assumption is confirmed, fix it by manually deleting all the duplicates in your database (leaving just one for each).

  3. After that, add a UniqueConstraint to your 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'),
    )
    

Note that you need to need to add it to the database, it is not enough to add it to the sqlalchemy model.

Now the code where the duplicates are inserted by mistake will fail with the unique constraint violation exception, and you can fix the root of the problem.

这篇关于从多对多SQL-Alchemy和Postgresql中删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆