SQLAlchemy中的Python字典

38 投票
5 回答
38180 浏览
提问于 2025-04-15 14:04

我想把一个字典(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 作为 PickleTypepickler 参数的值则无法正确工作,正如 AlexGrönholm在他对另一个答案的评论中指出

撰写回答