Corey Coogan
Corey Coogan

Reputation: 1639

SQL Alchemy ORM Getter

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

Answers (1)

Wolph
Wolph

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

Related Questions