2013-05-06 50 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

相關問題