[英]using list on postgresql JSON type with sqlalchemy
我使用sqlalchemy金字塔,pyramid_tm和postgresql来测试这个。
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()
class MyList(Base):
id = Column(Integer, primary_key=True)
lst = Column(JSON)
我正在使用postgresql 9.3+并使用JSON类型。 当我这样做
mylst = MyList(lst=[])
我可以看到在数据库上也创建了空[]列表,并且
def view(request):
mylst = DBSession.query(MyList).get(1)
mylst.lst.append('45')
print(DBSession.is_active, DBSession.is_modified(mylst))
我可以在数据库中看到['45'],并打印返回
True, True
在下一个请求上继续[编辑](上面已经提交)
def view(request):
mylst = DBSession.query(MyList).get(1)
mylst.lst.append('65')
print(DBSession.is_active, DBSession.is_modified(mylst))
db不会更新,它仍然是['45']并且打印返回
True, False
我做错了什么或这是一个错误?
默认情况下,SQLAlchemy仅跟踪值本身的更改,这对于简单值(如int和字符串)“按预期”工作:
alice.name = "Alice"
alice.age = 8
当您为“复杂类型”的列(例如dict或list)分配新值时,它也有效:
alice.toys = ['doll', 'teddy bear']
但是,如果修改列表中的某个元素,或者追加/删除值,SQLAlchemy不会注意到更改:
alice.toys[0] = 'teapot'
alice.toys.append('lego bricks')
要使这项工作,您可以确保每次都分配一个新列表:
toys = alice.toys[:] # makes a "clone" of the existing list
toys[0] = 'teapot'
toys.append('lego bricks')
alice.toys = toys
或者阅读SQLAlchemy文档中的Mutation Tracking章节,了解如何对列表或dict进行子类化,以便跟踪元素的修改。
另外,既然你提到你正在使用Postgres - 在Postgres中有一个专用的ARRAY
类型,你可以使用它而不是JSON
如果你需要的只是存储列表。 然而,上面关于突变跟踪的内容也适用于ARRAY
类型的列。
您可以将实例标记为手动修改
from sqlalchemy.orm.attributes import flag_modified
def view(session):
mylst = Session.query(MyList).get(1)
mylst.lst.append('45')
flag_modified(mylst, 'lst') # flag its `lst' attribute is modified
print(Session.is_active, Session.is_modified(mylst))
# (True, True)
在mylst.lst.append('45')
之后尝试DBSession.flush()
mylst.lst.append('45')
。 这允许您在pyramid_tm执行提交之前更新数据库。
更多信息可以在这里找到: http : //docs.sqlalchemy.org/en/latest/orm/session.html#flushing
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.