2011-04-04 35 views
1

我有一個在sqlalchemy-0.7中有Date列的類。我可以有一個column_property或類似的東西讓我一年,讓我輕鬆過濾它嗎?我會如何寫它?SA:對於Date列,我可以擁有'年份'column_property嗎?

IE瀏覽器,我想有(聲明語法):

class Foo(Base): 
    id = Column(Integer, primary_key=True) 
    date = Column(Date(), nullable=False) 
    year = column_property(something here) 

# later on 
q = session().query(Foo).filter_by(year=2011) 

回答

4

當然,你可以定義這樣的屬性:

year = column_property(extract('year', date)) 

但你真的需要它嗎?您可以一年不通過重寫過濾條件定義這樣的屬性過濾:

query(Foo).filter(extract('year', Foo.date)==2011) 

更新

雖然這種解決方案看起來很簡單它也有一個缺點:這樣的條件在WHERE子句將永遠不會對日使用指數領域。有很多排和高選擇性的條件,這會對性能造成很大的影響。所以,你可能要重寫的條件,這將導致RANGE索引掃描而不是全表掃描(如西蒙的意見建議):

start = datetime.date(year, 1, 1) 
end = datetime.date(year, 12, 31) 
query(Foo).filter(Foo.date.between(start, end)) 

定義的屬性有這樣的行爲也是可能的,你只需要重新定義比較:

class YearComparator(ColumnProperty.Comparator): 
    def __eq__(self, year): 
     if isinstance(year, int): 
      column = self.prop.columns[0].get_children()[0].expr 
      start = datetime.date(year, 1, 1) 
      end = datetime.date(year, 12, 31) 
      return column.between(start, end) 
     else: 
      # It can be a column or exression which we can't handle such way 
      return ColumnProperty.Comparator.__eq__(self, year) 
    # __lt__, __gt__ etc. are very similar to __eq__ 

def year_property(date_column, **kwargs): 
    kwargs.setdefault('comparator_factory', YearComparator) 
    return column_property(extract('year', date_column), **kwargs) 

class Foo(Base): 
    __tablename__ = 'Foo' 
    id = Column(Integer, primary_key=True) 
    date = Column(Date, index=True) 
    year = year_property(date) 
+0

還可以使用一個 '標準' 的條件:'查詢(美孚).filter(and_(Foo.date> =日期(2011年,1,1),Foo.date <日期(2012年,1, 1)))' – Simon 2011-04-05 12:23:54

相關問題