Skip to content

Instantly share code, notes, and snippets.

@luhn
Created November 29, 2012 18:35
Show Gist options
  • Star 46 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save luhn/4170996 to your computer and use it in GitHub Desktop.
Save luhn/4170996 to your computer and use it in GitHub Desktop.
Using getters and setters with SQLAlchemy
class Table(Base):
id = Column(Integer, primary_key=True)
_name = Column('name', String(24))
@property
def name(self):
return self._name;
@name.setter
def name(self, value):
self._name = value.title()
#A query you might perform on the table.
#It won't work anymore :'(
query = db_session.query(Table)\
.filter(Table.name == 'Theron')
#You could do this, but it doesn't look as nice, is inconsistent with the "id"
#column, and you'd have to update all your existing code.
query = db_session.query(Table)\
.filter(Table._name == 'Theron')
from sqlalchemy.orm import synonym
class Table(Base):
id = Column(Integer, primary_key=True)
_name = Column('name', String(24))
@property
def name(self):
return self._name;
@name.setter
def name(self, value):
self._name = value.title()
name = synonym('_name', descriptor=name)
#A query you might perform on the table.
#Now it works again! :)
query = db_session.query(Table)\
.filter(Table.name == 'Theron')
class Table(Base):
id = Column(Integer, primary_key=True)
name = Column(String(24))
#A query you might perform on the table.
query = db_session.query(Table)\
.filter(Table.name == 'Theron')
@jmaicher
Copy link

Thanks for the examples.
One remark: Instead of using @property you can use @hybrid_property and therewith avoid having to create the synonym.

from sqlalchemy.ext.hybrid import hybrid_property

class Table(Base):
    id = Column(Integer, primary_key=True)
    _name = Column('name', String(24))

    @hybrid_property
    def name(self):
        return self._name;

    @name.setter
    def name(self, value):
        self._name = value.title()

@period331
Copy link

@jmaicher
tks
👍

@lunemec
Copy link

lunemec commented Feb 23, 2016

@jmaicher yes, but hybrid_properties aren't supposed to have the same name as the column itself. The example you posted does not work. Please use the version with synonym it works flawlessly.

Thx for all the examples, I wish the official documentation would have these!

@arturoribes
Copy link

Why not use event.listen instead of this? (I just used this guide to generate a slug upon setting an entity name).
Any ideas on the performance impact of using event?

@igorsobreira
Copy link

synonym also works with flask_admin form generation seamlessly. Thanks for posting this!

@josegonzalez
Copy link

Confirming that the synonym method works great!

@valhuber
Copy link

Let me add my thanks for doing this.

I wanted to define a computed attribute that is not in db, with a setter to override the value. I introduced an instance variable _paid as shown below. (Did not need to use synonym, not clear on that)

# coding: utf-8

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property

Base = declarative_base()
metadata = Base.metadata


class Customer(Base):
    __tablename__ = 'Customer'

    Id = Column(String(8000), primary_key=True)
    OrderCount = Column(Integer)
    UnpaidOrderCount = Column(Integer)

    @hybrid_property
    def paid(self):
        if not hasattr(self, "_paid"):
            self._paid = self.OrderCount - self.UnpaidOrderCount
        return self._paid

    @paid.setter
    def paid(self, value):
        self._paid = value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment