在SQLAlchemy中更新关联对象中的字段

2024-06-08 23:46:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我在SQLAlchemy中有一个association对象,它有另外两个对象的一些额外信息(实际上是一个字段)。在

第一个对象是Photo模型,第二个对象是PhotoSet,关联对象称为PhotoInSet,它拥有position属性,它告诉我们当前Photo在当前的PhotoSet中处于什么位置。在

class Photo(Base):

    __tablename__ = 'photos'
    id = Column(Integer, primary_key=True)
    filename = Column(String(128), index=True)
    title = Column(String(256))
    description = Column(Text)
    pub_date = Column(SADateTime)

class PhotoInSet(Base):

    __tablename__ = 'set_order'
    photo_id = Column(Integer, ForeignKey('photos.id'), primary_key=True)
    photoset_id = Column(Integer, ForeignKey('photo_set.id'), primary_key=True)
    position = Column(Integer)
    photo = relationship('Photo', backref='sets')

    def __repr__(self):
        return '<PhotoInSet %r>' % self.position


class PhotoSet(Base):

    __tablename__ = 'photo_set'
    id = Column(Integer, primary_key=True)
    name = Column(String(256))
    description = Column(Text)
    timestamp = Column(SADateTime)
    user_id = Column(Integer, ForeignKey('users.id'))
    user = relationship('User', backref=backref('sets', lazy='dynamic'))
    photo_id = Column(Integer, ForeignKey('photos.id'))
    photos = relationship('PhotoInSet', backref=backref('set', lazy='select'))

创建一个新的PhotoSet保存position并创建关系(大致)如下所示:

^{pr2}$

但是当顺序改变时,我在尝试如何更新position时遇到了很多麻烦。在

如果我有3个id为1、2和3、位置分别为1、2和3的3Photo对象,在创建之后会是这样的:

>>> _set = PhotoSet.get(1)
>>> _set.photos
[<PhotoInSet 1>, <PhotoInSet 2>, <PhotoInSet 3>]

如果顺序改变了,(让我们在这个例子中颠倒顺序),SQLAlchemy是否可以帮助我更新position值?到目前为止,我对我能想出的任何方法都不满意。在

最简洁的方法是什么?在


Tags: 对象keyidtruepositioncolumnintegerset
1条回答
网友
1楼 · 发布于 2024-06-08 23:46:46

看看Ordering List扩展名:

orderinglist is a helper for mutable ordered relationships. It will intercept list operations performed on a relationship()-managed collection and automatically synchronize changes in list position onto a target scalar attribute.

我相信你可以把你的计划改成:

from sqlalchemy.ext.orderinglist import ordering_list

# Photo and PhotoInSet stay the same...

class PhotoSet(Base):
    __tablename__ = 'photo_set'
    id = Column(Integer, primary_key=True)
    name = Column(String(256))
    description = Column(Text)
    photo_id = Column(Integer, ForeignKey('photos.id'))
    photos = relationship('PhotoInSet',
       order_by="PhotoInSet.position",
       collection_class=ordering_list('position'),
       backref=backref('set', lazy='select'))

# Sample usage...
session = Session()

# Create two photos, add them to the set...
p_set = PhotoSet(name=u'TestSet')

p = Photo(title=u'Test')
p2 = Photo(title='uTest2')

p_set.photos.append(PhotoInSet(photo=p))
p_set.photos.append(PhotoInSet(photo=p2))
session.add(p_set)

session.commit()
print 'Original list of titles...'
print [x.photo.title for x in p_set.photos]
print ''

# Change the order...
p_set.photos.reverse()
# Any time you change the order of the list in a way that the existing
# items are in a different place, you need to call "reorder". It will not
# automatically try change the position value for you unless you are appending
# an object with a null position value.
p_set.photos.reorder()    
session.commit()

p_set = session.query(PhotoSet).first()
print 'List after reordering...'
print [x.photo.title for x in p_set.photos]

这个脚本的结果。。。在

^{pr2}$

你在评论中说。。。在

So this would mean that if I assign a new list to _set.photos I get the positioning for free?

我怀疑这是真的。在

相关问题 更多 >