SQLAlchemy中的Python字典
我想把一个字典(dict)存到我的sqlite数据库里,或者从数据库里读取出来,但我在找简单的方法时遇到了一些问题。其实我并不需要根据内容进行筛选,所以把字典简单地转换成字符串就可以了。
其次,如果能用外键那也不错。请不要发那些超级复杂的例子链接,我看了会头疼的。
5 个回答
8
SQLAlchemy 有一个内置的 JSON 类型,你可以使用它:
attributes = Column(JSON)
66
SQLAlchemy中的PickleType正是为了这个目的而设计的。
class SomeEntity(Base):
__tablename__ = 'some_entity'
id = Column(Integer, primary_key=True)
attributes = Column(PickleType)
# Just set the attribute to save it
s = SomeEntity(attributes={'baked': 'beans', 'spam': 'ham'})
session.add(s)
session.commit()
# If mutable=True on PickleType (the default) SQLAlchemy automatically
# notices modifications.
s.attributes['parrot'] = 'dead'
session.commit()
你可以通过更换不同的序列化工具来改变序列化的方式,只要这个工具有dumps()
和loads()
这两个方法。你还可以通过继承PickleType并重写impl属性来改变底层的存储机制:
class TextPickleType(PickleType):
impl = Text
import json
class SomeOtherEntity(Base):
__tablename__ = 'some_other_entity'
id = Column(Integer, primary_key=True)
attributes = Column(TextPickleType(pickler=json))
21
你可以通过继承 sqlalchemy.types.TypeDecorator
来创建一个自定义类型,这样就能处理文本的序列化和反序列化。
一个实现的例子可能是这样的:
import json
import sqlalchemy
from sqlalchemy.types import TypeDecorator
SIZE = 256
class TextPickleType(TypeDecorator):
impl = sqlalchemy.Text(SIZE)
def process_bind_param(self, value, dialect):
if value is not None:
value = json.dumps(value)
return value
def process_result_value(self, value, dialect):
if value is not None:
value = json.loads(value)
return value
使用示例:
class SomeModel(Base):
__tablename__ = 'the_table'
id = Column(Integer, primary_key=True)
json_field = Column(TextPickleType())
s = SomeModel(json_field={'baked': 'beans', 'spam': 'ham'})
session.add(s)
session.commit()
这个方法在 SQLAlchemy文档中的一个例子 中有详细说明,它还展示了如何跟踪字典的变化。
这种方法适用于所有版本的Python,而直接将 json
作为 PickleType
的 pickler
参数的值则无法正确工作,正如 AlexGrönholm在他对另一个答案的评论中指出。