Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
炼金术中的Python格言_Python_Sql_Sqlite_Sqlalchemy - Fatal编程技术网

炼金术中的Python格言

炼金术中的Python格言,python,sql,sqlite,sqlalchemy,Python,Sql,Sqlite,Sqlalchemy,我想从我的sqlite数据库中加载/保存一个dict,但在找到一个简单的方法时遇到了一些问题。我真的不需要能够根据内容进行过滤等,所以对字符串进行简单的转换就可以了 其次是外键。请不要发布指向大型示例的链接,如果我看到任何这些示例,我的头都会爆炸。如果您需要映射1-N关系,并将其映射为dict,而不是list,请阅读 但是如果您指的是一个字段,那么您可以做什么来获得一个string类型的DB字段,它被映射到Python对象。但是在同一个python对象上,您提供了一个属性,该属性将作为dict(

我想从我的sqlite数据库中加载/保存一个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)