Sqlalchemy上的UniqueConstraint阻止更新

时间:2015-11-19 13:31:35

标签: python orm sqlalchemy

在我的sqlalchemy模型定义中,我为列image_uid和优先级设置了UniqueConstraint,它看起来像这样:

class GalleryImage(base.Base):
     __tablename__ = 'gallery_image'

    gallery_uid = sqlalchemy.Column(sqlalchemy.Unicode(32), sqlalchemy.ForeignKey('gallery.uid'), primary_key=True)
    image_uid = sqlalchemy.Column(sqlalchemy.Unicode(32), sqlalchemy.ForeignKey('image.uid'), primary_key=True)
    priority = sqlalchemy.Column(sqlalchemy.Integer, nullable=False)

    image = sqlalchemy.orm.relationship("Image", backref='galleries')

    __table_args__ = (
        sqlalchemy.UniqueConstraint('gallery_uid', 'priority', name='image_priority_unique'),
    )

一切正常,除了Gallery没有图像的情况,我尝试重新排序。

实施例

在:

uid: 1, priority: 1
uid: 2, priority: 2
uid: 3, priority: 3

后:

uid: 1, priority: 3
uid: 2, priority: 2
uid: 3, priority: 1

代码明智的做法是这样的:

priority = len(gallery.images)

for item in gallery.images:
    item.priority = priority
    priority -= 1

    Session.add(item)

我的sql.log使用了事务,因此据我所知,这应该一次性完成并且应该优先处理:

[2015-11-19 13:25:43] BEGIN (implicit)
[2015-11-19 13:25:43] SELECT image.uid AS image_uid, image.user_uid AS image_user_uid, image.upload_session_id AS image_upload_session_id, image.title AS image_title, image.description AS image_description, image.created_at AS image_created_at, image.updated_at AS image_updated_at FROM image WHERE image.uid = %(uid_1)s
[2015-11-19 13:25:43] {'uid_1': u'5'}
[2015-11-19 13:25:43] {}
[2015-11-19 13:25:43] SAVEPOINT sa_savepoint_1
[2015-11-19 13:25:43] {}
[2015-11-19 13:25:43] SELECT gallery.uid AS gallery_uid, gallery.user_uid AS gallery_user_uid, gallery.title AS gallery_title, gallery.gallery_type AS gallery_gallery_type, gallery.description AS gallery_description, gallery.ad_tag AS gallery_ad_tag, gallery.ad_path AS gallery_ad_path, gallery.ad_zone AS gallery_ad_zone, gallery.created_at AS gallery_created_at, gallery.updated_at AS gallery_updated_at FROM gallery WHERE gallery.uid = %(uid_1)s
[2015-11-19 13:25:43] {'uid_1': u'7'}
[2015-11-19 13:25:43] SELECT image.uid AS image_uid, image.user_uid AS image_user_uid, image.upload_session_id AS image_upload_session_id, image.title AS image_title, image.description AS image_description, image.created_at AS image_created_at, image.updated_at AS image_updated_at FROM image WHERE image.uid = %(uid_1)s
[2015-11-19 13:25:43] {'uid_1': u'5'}
[2015-11-19 13:25:43] SELECT gallery_image.gallery_uid AS gallery_image_gallery_uid, gallery_image.image_uid AS gallery_image_image_uid, gallery_image.priority AS gallery_image_priority FROM gallery_image WHERE %(param_1)s = gallery_image.gallery_uid ORDER BY gallery_image.priority
[2015-11-19 13:25:43] {'param_1': u'7'}
[2015-11-19 13:26:08] UPDATE gallery_image SET priority=%(priority)s WHERE gallery_image.gallery_uid = %(gallery_image_gallery_uid)s AND gallery_image.image_uid = %(gallery_image_image_uid)s
[2015-11-19 13:26:08] {'priority': 3, 'gallery_image_gallery_uid': u'7', 'gallery_image_image_uid': u'3'}
[2015-11-19 13:26:08] ROLLBACK TO SAVEPOINT sa_savepoint_1
[2015-11-19 13:26:08] {}
[2015-11-19 13:26:08] ROLLBACK

请告知。

1 个答案:

答案 0 :(得分:1)

经过几个小时尝试不同的事情后,我了解到它实际上并不是sqlalchemy或ORM问题,而是对UniqueConstraint的定义不好。

应该是这样的(对于postgres db):

sqlalchemy.UniqueConstraint('gallery_uid', 'priority', name='image_gallery_unique', deferrable=True, initially="DEFERRED")

正如本文所述:

http://www.postgresql.org/docs/9.1/static/sql-set-constraints.html

而且:

http://docs.sqlalchemy.org/en/rel_1_0/core/constraints.html#sqlalchemy.schema.UniqueConstraint

解释事情。