Reputation: 1639
I am using the declarative style for Sql Alchemy mappings. I have a column on my table that will be storing portions of the object as JSON. I have a nice method responsible for creating the JSON and that's what I want stored in my DB.
I have mapped the field in my class as a column and tried to provided a synonym for it, but discovered that those only get called by consuming code. The ORM never accesses the getter.
My question is, how can I tell SA to grab the value for a column from a method?
Here's what my code looks like:
class JsonProperty(object):
_value = None
def __get__(self, instance, owner):
if instance is None:
return self
return self._value
def __set__(self, instance, value):
self._value = value
class TableTestParent(Base,object):
__tablename__ = 'Test'
id = Column(Integer, primary_key=True)
age = Column(Integer)
name = Column(String)
_model = Column('model',String)
@synonym_for('_model')
@property
def model(self):
return self._modelToJson()
def _modelToJson(self):
dict = {}
for item in self.__class__.__dict__.iteritems():
if type(item[1]) is JsonProperty:
attName = item[0]
attValue = getattr(self,attName,'')
dict[attName] = attValue
return json.dumps(dict)
class TableTest(TableTestParent):
email = JsonProperty()
phone = JsonProperty()
bestTimes = JsonProperty()
obj = TableTest()
obj.email = '[email protected]'
obj.name = 'Yeroc'
#save to db
Upvotes: 0
Views: 1178
Reputation: 80031
It's actually quite easy to create a custom type like this when using the TypeDecorator
:
http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/types.html#sqlalchemy.types.TypeDecorator
However... if you don't have anything that specifically depends on json, I would recommend using the PickleType
instead of your custom json type: http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/types.html#sqlalchemy.types.PickleType
Here's an example on how to make a json column work anyway:
class JsonType(types.TypeDecorator):
impl = types.Unicode
def process_bind_param(self, value, dialect):
return json.dumps(value)
def process_result_value(self, value, dialect):
return json.loads(value)
Upvotes: 2