炼金术中的Python格言
我想从我的sqlite数据库中加载/保存一个dict,但在找到一个简单的方法时遇到了一些问题。我真的不需要能够根据内容进行过滤等,所以对字符串进行简单的转换就可以了炼金术中的Python格言,python,sql,sqlite,sqlalchemy,Python,Sql,Sqlite,Sqlalchemy,我想从我的sqlite数据库中加载/保存一个dict,但在找到一个简单的方法时遇到了一些问题。我真的不需要能够根据内容进行过滤等,所以对字符串进行简单的转换就可以了 其次是外键。请不要发布指向大型示例的链接,如果我看到任何这些示例,我的头都会爆炸。如果您需要映射1-N关系,并将其映射为dict,而不是list,请阅读 但是如果您指的是一个字段,那么您可以做什么来获得一个string类型的DB字段,它被映射到Python对象。但是在同一个python对象上,您提供了一个属性,该属性将作为dict(
其次是外键。请不要发布指向大型示例的链接,如果我看到任何这些示例,我的头都会爆炸。如果您需要映射1-N关系,并将其映射为
dict
,而不是list
,请阅读
但是如果您指的是一个字段,那么您可以做什么来获得一个string类型的DB字段,它被映射到Python对象。但是在同一个python对象上,您提供了一个属性,该属性将作为dict()类型的映射字符串字段的代理。
代码示例(未测试):
SQLAlchemy就是为了这个
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()
方法的其他内容来更改pickler,可以更改序列化机制。通过子类化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))
您可以通过子类化
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()
这在中进行了概述,其中还显示了如何跟踪该词典的突变
这种方法应该适用于所有版本的Python,而仅仅将json
作为值传递给PickleType
的pickler
参数将无法正常工作,正如他对另一个答案的评论一样。SQLAlchemy有一个内置的json类型,您可以使用:
attributes = Column(JSON)
可爱!我周一第一件事就是试试。当我尝试自我时,我可能犯了严重的错误。_properties[k]=v?我得到“TypeError:“Column”对象不支持项分配”。我的示例是使用声明性语法一次性定义表和映射器。您出现的错误听起来好像您没有为类使用声明性基类。为此,请在类定义之前添加Base=sqlalchemy.ext.declarative.declarative_Base()。自sqlalchemy版本0.7起,PickleType上不再有mutable
参数。出于性能原因,删除了该选项,并引入了新的可变性策略。请参阅(在版本0.9文档中),这在Python3.6上不起作用,而且不应该在早期版本中起作用。Pickle的dumps()
与json的dumps()
不兼容,因为前者接受协议参数,后者不接受。在3.5及更早版本的python上,这将导致将skip_keys
的值设置为协议编号。请注意,SQLAlchemy不会看到您修改dict的内容,因此在设置dict后对其所做的任何更改都不会被持久化。您的第一个链接不再有效。您的答案不完整,因此无法接受。它还提到了“被接受的答案”,它转移了任何尝试,改变了任何答案的特定状态。请以正确的答案开始,并(如果必须)在结尾包括其他人做错了什么。@JonasByström很公平,我已经删除了对当前接受答案的引用,并将示例扩展了一点。这在我第一次设置它时是有效的。但是,在向我的模型中添加一个新字段(product\u count=db.Column(db.Integer)
)后,将更改迁移到mysql时会出现以下错误:NameError:name'TextPickleType'未定义
假设您使用alembic进行迁移,您可能必须在迁移脚本中导入该类型。很难说。也许会问一个新问题?
attributes = Column(JSON)