指定したdatetime値でのfilter(修正2010-03-02)


ユーザー一覧の表示でページ遷移などする時に fetch() を使おうとすると1000件の壁にぶち当たる。
そこで datetime 値での filter を使用した。

  • こんなモデルがあったとする
from google.appengine.ext import db

class Member(db.Model):
    insert_datetime = db.DateTimeProperty(auto_add = True)
    name = db.StringProperty()
    age = db.IntegerProperty()

しかし microsec での絞りこみはできないので、以下のようにした。

def get(delimiter_id=None):
    """
    Member から指定した件数の情報を取得する。
        引数 delimiter_id が存在する場合:
            insert_datetime を昇順ソートし
            delimiter_id で指定した Member までを除外する。
    """
    from google.appengine.ext import db
    from member.models import Member
    import datetime

    # 取得件数 100件
    limit = 100

    # 絞り込む日時
    if delimiter_id is None:
        delimiter_dt = str(datetime.datetime.now())
    else:
        m = Member.get(delimiter_id)
        delimiter_dt = str(m.insert_datetime)

    # クエリ
    gql = "SELECT * FROM member_member"
    gql += " WHERE insert_datetime <= DATETIME('%s')"
    gql += " ORDER BY insert_datetime DESC"
    m = db.GqlQuery(gql % datetime_dt)

    # 取得実行
    start_num = 0
    if delimiter_id is not None:
        i = 0
        for val in m:
            i += 1
            if val.pk == delimiter_id:
                start_num = i
                break
    return m[start_num:(start_num+limit):]

microsecond があれば、そこまで比較してくれる。ドキュメントを見ると一番細かいのは「DATETIME(year, month, day, hour, minute, second)」または「DATETIME('YYYY-MM-DD HH:MM:SS')」と記載されていて microsecond まで対応してるとは書いてない。
試したら期待通りに動いてくれたとはいえ、いずれ無視されるようになるかもしれないなーと思った。期待通りに動いたように見えただけだった。自分の環境では microsec 部分は無視されたのか、エラーが帰ってこなかったので使えると勘違いしただけだった。