bottle直接返回pymongo查询结果
以前提到过bottle,也写过在django里使用pymongo,这次是在bottle里用pymongo。
bottle有类似ROR的一些特性,比如处理请求的时候直接return一个字典,框架会自动把它parse成json(autojson)。
我是想偷个懒来着,把代码写成了下面这样。
@get('/api/today')
def api_today():
    udid = request.GET.get('udid')
    return self.coll.find_one({'udid':udid, 'date':today})
这会有问题,因为find_one返回的bson没办法直接parse。伟大的发明都是在偷懒的时候诞生的,看起来我要做的事情也很简单,只要能让我改一改parser就行了。
- 写一个dump方法替换原来JSONPlugin里的
 - 设置Bottle app的autojson为False。
Bottle(autojson=False) - 把有自己dump方法的JSONPlugin给install到app里
 
class MongoEncoder(JSONEncoder):
    def mongo_dumps(obj):
        # convert all iterables to lists
        if hasattr(obj, '__iter__'):
            return list(obj)
        # convert cursors to lists
        elif isinstance(obj, pymongo.cursor.Cursor):
            return list(obj)
        # convert ObjectId to string
        elif isinstance(obj, bson.objectid.ObjectId):
            return unicode(obj)
        # dereference DBRef
        elif isinstance(obj, bson.dbref.DBRef):
            return db.dereference(obj) # db is the incetance database
        # convert dates to strings
        elif isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date) or isinstance(obj, datetime.time):
            return unicode(obj)
        return json.JSONEncoder.default(self, obj)
app = app()
app.autojson = False
m_encoder = MongoEncoder()
app.install(JSONPlugin(json_dumps=lambda s: dumps(s, default=m_encoder.mongo_dumps)))
via: