2013-05-06 22 views
3

我正在使用SQLalchemy在传统MSSQL数据库中工作,为此我有一个声明性映射。
该数据库有几个表,其中有计算列。我可以很好地阅读它们,但是(当然)写入计算列不起作用。但是,当我创建并尝试保存ORM对象时,SQLAlchemy仍会尝试在这些列中保存“无”值,从而导致错误。在sqlalchemy中包含计算列的更新表

我发现了一些联机示例,应该使用SQLAlchemy的hybrid_property装饰器将特定列设置为“只读”,但即使在执行该操作后,仍会出现相同的错误(The column "tlog_real_timehh" cannot be modified because it is either a computed column or is the result of a UNION operator.)。

的代码如下 - 映射:

class transactionlog(Base): 
    __tablename__ = 'transactionlog' 
    tlog_id = Column(VARCHAR(length=36), primary_key=True, nullable=False) 
    tlog_ppl_id = Column(VARCHAR(length=36), ForeignKey('people.ppl_id')) 
    tlog_evtt_id = Column(VARCHAR(length=5)) 
    tlog_testrun = Column(BIT()) 
    tlog_Data = Column(NVARCHAR(length=300)) 
    tlog_price = Column(DECIMAL(precision=18, scale=2)) 
    tlog_comment = Column(NVARCHAR(length=1000)) 
    _tlog_real_timehh = Column('tlog_real_timehh', INTEGER()) 
    _tlog_real_timemm = Column('tlog_real_timemm', INTEGER()) 
    _tlog_real_timess = Column('tlog_real_timess', INTEGER()) 
    _tlog_fin_booking = Column('tlog_fin_booking', BIT()) 

    @hybrid_property 
    def tlog_real_timehh(self): 
     return self._tlog_real_timehh 

    @tlog_real_timehh.setter 
    def tlog_real_timehh(self, tlog_real_timehh): 
     self._tlog_real_timehh = tlog_real_timehh 

    @hybrid_property 
    def tlog_real_timemm(self): 
     return self._tlog_real_timemm 

    @tlog_real_timemm.setter 
    def tlog_real_timemm(self, tlog_real_timemm): 
     self._tlog_real_timemm = tlog_real_timemm 

    @hybrid_property 
    def tlog_real_timess(self): 
     return self._tlog_real_timess 

    @tlog_real_timess.setter 
    def tlog_real_timess(self, tlog_real_timess): 
     self._tlog_real_timess = tlog_real_timess 

    @hybrid_property 
    def tlog_fin_booking(self): 
     return self._tlog_fin_booking 

    @tlog_fin_booking.setter 
    def tlog_fin_booking(self, tlog_fin_booking): 
     self._tlog_fin_booking = tlog_fin_booking 

和代码应该添加一个新的记录:

rem = Transactionlog() 
    rem.tlog_testrun = 0 
    rem.tlog_evtt_id = 'rem' 
    rem.tlog_Data = None 
    rem.tlog_comment = 'reminder' 
    rem.tlog_price = 0 
    db.session.add(rem) 
    db.session.flush() 

我期望hybrid_property代码,以使计算领域连读只是,但似乎SQLAlchemy仍然试图根据映射代码将它们填充到INSERT语句中。 (当我查看SQL语句时,我可以看到这一点,我不能发布SQL语句,因为我在某种程度上将对象缩写为在StackOverflow中没有任何敏感数据)。

问题是,为什么SQLAlchemy仍尝试插入tlog_real_timehh,tlog_real_timemm,tlog_real_timess和tlog_fin_booking的值,以及如何防止此问题?

谢谢你可以给我的任何指针。
埃里克

回答

3

标签server-generated columnsFetchedValue

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, autoincrement=False, primary_key=True) 
    firstname = Column(String(50)) 
    lastname = Column(String(50)) 
    fullname = Column(String(100), FetchedValue()) 

e = create_engine("mssql+pyodbc://scott:[email protected]_2005", echo=True) 
Base.metadata.drop_all(e) 

e.execute(""" 
    CREATE TABLE a (
      id INTEGER PRIMARY KEY, 
      firstname VARCHAR(50), 
      lastname VARCHAR(50) 
     ) 
""") 
e.execute("ALTER TABLE a ADD fullname AS firstname + ' ' + lastname") 

sess = Session(e) 

sess.add_all([ 
    A(id=1, firstname='ed', lastname='jones'), 
    A(id=2, firstname='wendy', lastname='smith'), 
    A(id=3, firstname='jack', lastname='bean') 
]) 
sess.commit() 

assert [ 
    fname for fname, in 
    sess.query(A.fullname).order_by(A.id) 
] == ['ed jones', 'wendy smith', 'jack bean'] 


e.execute("DROP TABLE a") 
+0

实施,测试简陋,看起来像它的工作!谢谢zzzeek! – 2013-05-10 14:51:09

相关问题