在带有sqlalchemy的PostgreSQL JSON类型上使用列表 [英] using list on postgresql JSON type with sqlalchemy

查看:264
本文介绍了在带有sqlalchemy的PostgreSQL JSON类型上使用列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将金字塔与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屋!

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