在带有sqlalchemy的PostgreSQL JSON类型上使用列表 [英] 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(整数,primary_key = True)
lst =列(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'],并且打印返回
真实的,真实的
在下一个请求(上面已经提交)上从[edit]继续
def视图( request):
mylst = DBSession.query(MyList).get(1)
mylst.lst.append('65')
print(DBSession.is_active,DBSession.is_modified(mylst) )
数据库不会更新,它仍然是['45']并且打印返回
正确,错误
我做错了还是这是一个错误?
默认情况下,SQLAlchemy仅跟踪值本身的更改,该值对简单值(如整数和字符串)按预期运行:
alice.name =爱丽丝
alice.age = 8
当您为复杂类型的列(例如dict或list)分配新值时,它也起作用:
alice.toys = ['doll','泰迪熊']
但是,如果您修改列表中的元素之一或追加/删除值,SQLAlchemy不会注意到更改:
alice.toys [0] ='茶壶'
alice.toys.append('乐高积木')
要执行此操作,您可以确保每次都分配一个新列表:
toys = alice.toys [:]#在现有列表中制作一个克隆
toys [0] ='茶壶'
toys.append('lego bricks')
alice.toys =玩具
或者读t他在SQLAlchemy文档中的突变跟踪 一章中了解了如何
此外,由于您提到您正在使用Postgres,因此有一个专用的 ARRAY
键入Postgres,如果您只需要存储列表,则可以使用它代替 JSON
。但是,上面所说的有关突变跟踪的内容也适用于 ARRAY
类型的列。
I am using pyramid with sqlalchemy, pyramid_tm and postgresql to test this.
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()
class MyList(Base):
id = Column(Integer, primary_key=True)
lst = Column(JSON)
I am using postgresql 9.3+ and using JSON type. When i do this
mylst = MyList(lst=[])
i can see empty [] list being created on database as well, and
def view(request):
mylst = DBSession.query(MyList).get(1)
mylst.lst.append('45')
print(DBSession.is_active, DBSession.is_modified(mylst))
i can see ['45'] in database, and print returns
True, True
continuing from above [edit] on next request (above is already committed)
def view(request):
mylst = DBSession.query(MyList).get(1)
mylst.lst.append('65')
print(DBSession.is_active, DBSession.is_modified(mylst))
The db wont get updated, it is still ['45'] and print returns
True, False
Am i doing something wrong or is this a bug?
By default, SQLAlchemy only tracks changes of the value itself, which works "as expected" for simple values, such as ints and strings:
alice.name = "Alice"
alice.age = 8
It also works when you assign a new value to a column of a "complex type", such as dict or list:
alice.toys = ['doll', 'teddy bear']
However, SQLAlchemy does not notice a change if you modify one of the elements in the list, or append/remove a value:
alice.toys[0] = 'teapot'
alice.toys.append('lego bricks')
To make this work you can either make sure you assign a new list each time:
toys = alice.toys[:] # makes a "clone" of the existing list
toys[0] = 'teapot'
toys.append('lego bricks')
alice.toys = toys
Or have a read of the Mutation Tracking chapter in SQLAlchemy docs to see how you can subclass a list or a dict so they track modifications of their elements.
Also, since you mentioned you're using Postgres - there's a dedicated ARRAY
type in Postgres which you can use instead of JSON
if all you need is to store lists. However, what is said above about the mutation tracking applies to columns of ARRAY
type too.
这篇关于在带有sqlalchemy的PostgreSQL JSON类型上使用列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!