-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
UpdatableInsertable
zzzeek edited this page Oct 20, 2015
·
1 revision
The goal here is to annotate mapped Column objects with optional "updatable=False" and "insertable=False" directives; the effect will be that changes / values placed on these columns will be reverted when a flush occurs, allowing server-side directives to always take precedence over any ORM-level changes. Alternatively, the recipe can be altered to raise an exception when these conditions are detected.
from sqlalchemy import event
from sqlalchemy.orm import mapper
@event.listens_for(mapper, "before_insert", raw=True)
def before_insert(mapper, connection, target):
for col_attr in mapper.column_attrs:
col = col_attr.columns[0]
if not col.info.get('insertable', True):
target.dict.pop(col_attr.key, None)
@event.listens_for(mapper, "before_update", raw=True)
def before_update(mapper, connection, target):
for col_attr in mapper.column_attrs:
col = col_attr.columns[0]
if not col.info.get('updateable', True) and \
col_attr.key in target.committed_state:
target.dict[col_attr.key] = target.committed_state.pop(
col_attr.key)
if __name__ == '__main__':
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
plain = Column(Integer)
uninsertable = Column(
Integer, info={"insertable": False}, server_default="7")
unupdateable = Column(Integer, info={"updateable": False})
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
s = Session(e)
a1 = A(plain=5, unupdateable=10)
a2 = A(plain=6, uninsertable=18, unupdateable=10)
s.add_all([a1, a2])
s.flush()
assert a2.uninsertable == 7
s.commit()
assert set(a for a, in s.query(A.uninsertable)) == set([7])
a1 = s.query(A).filter_by(plain=6).one()
a1.unupdateable = 12
s.flush()
assert a1.unupdateable == 10
s.commit()
assert set(a for a, in s.query(A.unupdateable)) == set([10])