librelist archives

« back to archive

Prevent model column from being directly modified

Prevent model column from being directly modified

From:
Sudaraka Wijesinghe
Date:
2014-10-19 @ 20:21
I have the following model (using SQLAlchemy)

-- code - sart --

class MyThing(db.Model):

    attributes_json = db.Column(db.Text)

    @property
    def attributes(self):
        if self.attributes_json is None:
            return []

        return json.loads(self.attributes_json)

    @attributes.setter
    def attributes(self, value):
        if not isinstance(value, list):
            raise ValueError('value is not a list')

        self.attributes_json = json.dumps(value)

-- code - end --

My objective is to have MyThing.attributes be assigned and retrieved as
a list, and it be saved to database as a JSON string.

Property works as I need and the JSON string is being saved to DB fine.
Now I need to make it so that attributes_json can't be altered directly.
Appreciate some pointers on how I can do this, or there are better
solutions for this.

Thanks.

-- 
Sudaraka Wijesinghe.
http://sudaraka.org/

Re: [flask] Prevent model column from being directly modified

From:
Matthias Urlichs
Date:
2014-10-20 @ 05:56
Hi,

Sudaraka Wijesinghe:
> I have the following model (using SQLAlchemy)

This is a sqlalchemy, not a flask, problem.

To answer your question:
Basically, you can't. This is Python, not C++.

However, what you can (indeed should) do is to not use a property.
Instead, subclass the sqlalchemy data type.

For an example, here's a simple class which stores a date as
seconds-since-epoch, for a legacy database:

	class UnixDateTime(types.TypeDecorator):
		impl = types.Integer

		def process_bind_param(self, value, dialect):
			if value is None: return None
			return int(time.mktime(value.timetuple()))

		def process_result_value(self, value, dialect):
			if value is None: return None
			return datetime.datetime.fromtimestamp(float(value))


	[ class MyTable: ]
		datestamp = Column(UnixDateTime())

-- 
-- Matthias Urlichs

Re: [flask] Prevent model column from being directly modified

From:
Sudaraka Wijesinghe
Date:
2014-10-20 @ 13:22
On 10/20/14 11:26, Matthias Urlichs wrote:
> Hi,
> 
> Sudaraka Wijesinghe:
>> I have the following model (using SQLAlchemy)
> 
> This is a sqlalchemy, not a flask, problem.

My bad.

> 
> To answer your question:
> Basically, you can't. This is Python, not C++.
> 
> However, what you can (indeed should) do is to not use a property.
> Instead, subclass the sqlalchemy data type.
> 
> For an example, here's a simple class which stores a date as
> seconds-since-epoch, for a legacy database:
> 
> 	class UnixDateTime(types.TypeDecorator):
> 		impl = types.Integer
> 
> 		def process_bind_param(self, value, dialect):
> 			if value is None: return None
> 			return int(time.mktime(value.timetuple()))
> 
> 		def process_result_value(self, value, dialect):
> 			if value is None: return None
> 			return datetime.datetime.fromtimestamp(float(value))
> 
> 
> 	[ class MyTable: ]
> 		datestamp = Column(UnixDateTime())
> 

I followed this and what SQLAlchemy document said and got the exact
result I wanted. Thanks for pointing me in the right direction.