2015-02-04 43 views
3

我用的烧瓶SQLAlchemy的和具有以下列模型:为什么SQLAlchemy将hstore字段初始化为空?

class Item(Model): 
    misc = Column(MutableDict.as_mutable(postgresql.HSTORE), nullable=False, 
        server_default='', 
        default=MutableDict.as_mutable(postgresql.HSTORE)) 

当我尝试域分配给模型对象,似乎misc列是无,而不是一个空的字典:

my_item = Item() 
my_item.misc["foo"] = "bar" 
# TypeError: 'NoneType' object does not support item assignment 

如何配置模型以便新对象使用空字典进行初始化?

回答

3

这里有两个问题。首先,default应该是Python字典,而不是列类型的重复。其次,在初始化新实例时不使用default,只有在提交没有为该列设置值的实例时才使用default。所以你需要在初始化期间专门添加一个默认值。

from sqlalchemy.dialects.postgresql import HSTORE 
from sqlalchemy.ext.mutable import MutableDict 

class Item(db.Model): 
    misc = db.Column(MutableDict.as_mutable(HSTORE), nullable=False, default={}, server_default='') 

    def __init__(self, **kwargs): 
     kwargs.setdefault('misc', {}) 
     super(Item, self).__init__(**kwargs) 
item = Item() 
item.misc['foo'] = 'bar' 

关于这一点,有一个在设置这两个defaultserver_default如果你永远只能将使用这个从Python中没有点。不过,也没有害处。


我假设你知道你在这种特殊情况下需要一个HSTORE,但我还会指出,PostgreSQL有更普遍的JSON和JSONB类型了。

+0

这是我工作的:'misc = db.Column(MutableDict.as_mutable(HSTORE),nullable = False,server_default = db.text(“''”))''。通过这种方式,我在postgres的'misc'列中获得了一个'DEFAULT'':: hstore',这导致在python中缺省为空的'dict'。 – robkorv

0

有可能是一个更简单的方法来做到这一点,但一种方法是创建一个自定义列类型转换数据库中的值,并返回。

下面是一个VARCHAR字段从序列化的文档/反序列化JSON的例子:

http://docs.sqlalchemy.org/en/latest/orm/extensions/mutable.html#establishing-mutability-on-scalar-column-values

from sqlalchemy.types import TypeDecorator, VARCHAR 
import json 

class JSONEncodedDict(TypeDecorator): 
    "Represents an immutable structure as a json-encoded string." 

    impl = VARCHAR 

    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 

在你的情况,你可以检查是否value为None并返回一个空dict()相反,当写入分贝时,你会检查value是否是一个空字典,而不是写None

如果你走这条路,再看看可变性的东西,所以JSONEncodedDict的变化会被注意到并被刷新。它看起来像你已经知道它,但只是为了读其他人。

希望有所帮助。

+0

但这不是HSTORE。由于这是PostgreSQL,因此如果需要的话,可以使用JSON和JSONB类型。 – davidism