2015-05-28 210 views
0

我用flask-sqlalchemy定義了一個表。如下所示。Flask-sqlalchemy查詢日期時間間隔

class Notes(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    notes = db.Column(db.Text, nullable=False) 
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) 
    added_at = db.Column(db.DateTime, default=db.func.now()) 

@staticmethod 
def newest(num): 
    return Notes.query.order_by(desc(Notes.added_at)).limit(num) 

我試圖編寫一個查詢來替換和現有的直接查詢,看起來像這樣。

select notes,user,added_at from notes where added_at >= now() - INTERVAL 8 HOUR; 

但是基於我能找到的文檔,我找不到一種方法來做同樣的事情。我能夠做出更簡單的查詢,但我努力重新創建sql本身非常簡單。

我非常樂意閱讀一些圍繞它的文檔,也無法精確地指出這一點。你可以提供的任何方向都很棒。

+0

可能重複的[SQLAlchemy:如何過濾日期字段?](http://stackoverflow.com/questions/8895208/sqla lchemy-how-to-filter-date-field) – nathancahill

+0

我看到了這個,但是它沒有足夠的信息來重新創建我試圖完成的區間函數。謝謝你。 – Harry

回答

2

你可以嘗試像

Notes.query.order_by(desc(Notes.added_at)).filter(
    Notes.added_at >= text('NOW() - INTERVAL 8 HOURS').limit(num) 

正如我只能用我這個語法測試了這一點純粹的SQLAlchemy:

>>> from sqlalchemy import text 
>>> # s is a standard sqlalchemy session created from elsewhere. 
>>> print s.query(Notes).order_by(desc(Notes.added_at)).filter(
...  Notes.added_at >= text('NOW() - INTERVAL 8 HOURS')) 
SELECT notes.id AS notes_id, notes.notes AS notes_notes, notes.added_at AS notes_added_at 
FROM notes 
WHERE notes.added_at >= NOW() - INTERVAL 8 HOURS ORDER BY notes.added_at DESC 

之所以使用text該節僅僅是因爲NOW()INTERVAL在所有SQL實現中使用不一致(某些實現需要使用DATEADD來執行日期時間算術,而sqlalchemy確實支持Interval類型它沒有真正有效的文檔記錄,並且在我的簡短測試中它並沒有真正做你需要的東西(使用來自this answer的示例,對於sqlite和MySQL)。如果您打算使用SQL後端爲有序(但愚蠢的)數據存儲你可以構建實際的查詢從內部的Python,也許像這樣:

q = s.query(Notes).order_by(desc(Notes.added_at)).filter(
    Notes.added_at >= (datetime.utcnow() - timedelta(3600 * 8)) 
) 

有些人不喜歡這個像一些數據庫(如PostgreSQL)可以比Python更好地處理日期時間(比如timedelta對閏年是無知的)。

0

也可以嘗試

from sqlalchemy import func, text 

@staticmethod 
def newest(num): 
    return Notes.query.filter(Notes.added_at >= (func.date_sub(func.now(), text('INTERVAL 8 HOUR')).order_by(desc(Notes.added_at)).limit(num) 

OR

from datetime import datetime, timedelta 
from dateutil import tz 

@staticmethod 
def newest(num): 
    recent = datetime.now(tz=tz.tzlocal()) - timedelta(hours=8) 

    return Notes.query.filter(Notes.added_at >= recent).order_by(desc(Notes.added_at)).limit(num) 
0

我總是有Python的datetime圖書館讓我的 「現在」 和 「8小時前」,然後使用日期時間只是做一個過濾器:

from datetime import datetime, timedelta 

now = datetime.now() 
eight_hours_ago = now - timedelta(hours=8) 

Notes.query.filter(Notes.added_at > eight_hours_ago).filter(Notes.added_at < now).all()