2016-02-04 682 views
2

我有存儲在以下格式的日期時間值的表:(EG)20160213145512.不幸的是,SQLAlchemy的讓我沒有機會指定用於存儲日期時間值的格式與SQLAlchemy的數據庫的DateTime類型。SQLAlchemy的ORM的DateTime具有特定格式

因此,我創建了以下dataype:

class Timestamp(TypeDecorator): 
    impl = String(14) 

    def process_bind_param(self, value, dialect): 
     if isinstance(value, datetime): 
      value = '%04d%02d%02d%02d%02d%02d' % (value.year, 
                value.month, 
                value.day, 
                value.hour, 
                value.minute, 
                value.second) 
     return value 


    def process_result_value(self, value, dialect): 
     if value: 
      return datetime(year=int(value[0:4]), 
          month=int(value[4:6]), 
          day=int(value[6:8]), 
          hour=int(value[8:10]), 
          minute=int(value[10:12]), 
          second=int(value[12:14]) 
          ) 

我不使用的strftime和strptime性能方面的原因。 我現在能夠做的是以下幾點:

class TestTable(Base): 
    __tablename__ = "TESTTABLE" 

    id = Column(Integer, primary_key=True) 
    timestamp = Column(Timestamp) 

插入行通過經DateTime對象定義的日期時間:

session.add(TestTable(timestamp=datetime(year=2016, month=2, day=3, hour=2))) 

或者定義日期時間爲一個字符串中插入一行:

session.add(TestTable(timestamp="20160203031422")) 

到目前爲止,一切都很好。 但是下面沒有按預期工作:

session.query(TestTable).filter(TestTable.timestamp.year == 2016).all() 

如果我捉迷藏此代碼段我得到這個錯誤:

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with ORDERS.dz_statakt has an attribute 'year' 

但是這個工程:

session.query(TestTable).filter(TestTable.timestamp.startswith("2016")).all() 

直到現在我無法解決這個問題。我想我在我自己的Timestamp類中缺少一些東西。

這可能嗎?

非常感謝您的幫助!

回答

1

這是可能的,但有點複雜。

首先,你的代碼不工作的原因。 TestTable.timestampColumn。沒有任何地方定義的year屬性。 year屬性位於從process_result_value返回的datetime對象上。原因TestTable.timestamp.startswith的作品是因爲.startswithconsidered an operator by SQLAlchemy

因此,要使其工作,你需要在TestTable.timestamp定義的屬性,讓你正確的SQL表達式,當你對值對它們進行比較:

class Timestamp(TypeDecorator): 
    impl = String(14) 

    class comparator_factory(TypeDecorator.Comparator, impl.comparator_factory): 
     @property 
     def year(self): 
      return cast(func.substr(self.expr, 1, 4), Integer) 

     ... 

    def process_bind_param(self, value, dialect): 
     ... 

    def process_result_value(self, value, dialect): 
     ... 
+0

謝謝!按預期工作! – Rollmops

+0

注意:最好從String.Comparator派生comparator_factory。否則像startswith這樣的字符串函數有一個奇怪的行爲。 – Rollmops

+0

@Rollmops謝謝。最初的'TypeDecorator.comparator_factory'實際上來自'(TypeDecorator.Comparator,impl.comparator_factory)'。我已經更新了我的答案。 – univerio