flask_sqlalchemy 查詢結果轉dict 終極解決方案


  之前為了學習Python,試着拿Flask作框架搞小網站,感覺還不錯,基本就拋棄了PHP。前段時間做了一個微信小程序,想着yii框架拿來寫幾十個小接口是不是浪費了,就繼續用flask寫api了,哪想到填坑無數啊。

  Python的ORM框架就屬Sqlalchemy牛逼,網上資料也多,想着和yii里面應該差不多,就拿來用了。第二天萬萬沒想到,php里面簡單的一句asArray就能解決的問題,flask_sqlalchemy居然沒有解決方案,查詢的結果對象無法直接JSON序列化。這期間從南到北地找,大部分解決方案都是做一個JSON.dumps的Encoder方法,來轉化restult對象,無意中看見https://www.cnblogs.com/wancy86/p/6421792.html 這個帖子,說queryresult對象加入了json屬性,欣喜萬分,搞了一晚上也沒找到這個方法。

  原文鏈接:https://www.cnblogs.com/eating-gourd/p/9997751.html

 


 

咳咳,正文:  

  網上的方法主要問題在於只能處理result對象或model對象之一,當查詢某個表全部字段時,如

1 db.session.query(User).filter().all()

  其返回User這個類的對象列表,而查詢某些字段或者多表連接時,如:

 1 db.session.query(User.UserID,User.UserName).filter().all() 

  其返回result對象的列表,這兩種情況下,對象的屬性不同,導致很多情況下只能適應一種返回。今天趁閑着沒事,把兩種情況的查詢結果轉dict作了一下整理,封裝為一個queryToDict函數,並同時支持all()返回的列表和first()返回的單個對象結果:

from datetime import datetime as cdatetime #有時候會返回datatime類型
from datetime import date,time
from flask_sqlalchemy import Model
from sqlalchemy.orm.query import Query
from sqlalchemy import DateTime,Numeric,Date,Time #有時又是DateTime

def queryToDict(models):
    if(isinstance(models,list)):
        if(isinstance(models[0],Model)):
            lst = []
            for model in models:
                gen = model_to_dict(model)
                dit = dict((g[0],g[1]) for g in gen)
                lst.append(dit)
            return lst
        else:
            res = result_to_dict(models)
            return res
    else:
        if (isinstance(models, Model)):
            gen = model_to_dict(models)
            dit = dict((g[0],g[1]) for g in gen)
            return dit
        else:
            res = dict(zip(models.keys(), models))
            find_datetime(res)
            return res
#當結果為result對象列表時,result有key()方法
def result_to_dict(results):
    res = [dict(zip(r.keys(), r)) for r in results]
    #這里r為一個字典,對象傳遞直接改變字典屬性
    for r in res:
        find_datetime(r)
    return res
def model_to_dict(model):      #這段來自於參考資源
    for col in model.__table__.columns:
        if isinstance(col.type, DateTime):
            value = convert_datetime(getattr(model, col.name))
        elif isinstance(col.type, Numeric):
            value = float(getattr(model, col.name))
        else:
            value = getattr(model, col.name)
        yield (col.name, value)
def find_datetime(value):
    for v in value:
        if (isinstance(value[v], cdatetime)):
            value[v] = convert_datetime(value[v])   #這里原理類似,修改的字典對象,不用返回即可修改
def convert_datetime(value):
    if value:
        if(isinstance(value,(cdatetime,DateTime))):
            return value.strftime("%Y-%m-%d %H:%M:%S")
        elif(isinstance(value,(date,Date))):
            return value.strftime("%Y-%m-%d")
        elif(isinstance(value,(Time,time))):
            return value.strftime("%H:%M:%S")
    else:
        return ""
dit = dict((g[0],g[1]) for g in gen)相關代碼也是之前查找資料獲得,現在找不到出處了,作者可以聯系我。
 滾去學雅思了,代碼寫得較快,歡迎指出bug

參考資源:

[1] https://stackoverflow.com/questions/5022066/how-to-serialize-sqlalchemy-result-to-json

[2] https://segmentfault.com/q/1010000007459402/a-1020000007460322


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM