2015-08-09 51 views
2

我正在使用MongoDB構建SPA(Angular)的python後端。

下面是我用:Python 3.4MongoDB 3Flaskflask-mongoengineflask-restful

現在,我從我的後端收到以下JSON:

[ 
    { 
     "_id": { 
      "$oid": "55c737029380f82fbf52eec3" 
     }, 
     "created_at": { 
      "$date": 1439129906376 
     }, 
     "desc": "Description.....", 
     "title": "This is title" 
    }, 
    etc... 
] 

而且我希望收到類似的東西

[ 
    { 
     "_id": "55c737029380f82fbf52eec3", 
     "created_at": 1439129906376, 
     "desc": "Description.....", 
     "title": "This is title" 
    }, 
    etc... 
] 

My co德現在:

from flask import json 
from vinnie import app 
from flask_restful import Resource, Api 
from vinnie.models.movie import Movie 

api = Api(app) 

class Movies(Resource): 
    def get(self): 
     movies = json.loads(Movie.objects().all().to_json()) 
     return movies 

api.add_resource(Movies, '/movies') 

型號:

import datetime 
from vinnie import db 

class Movie(db.Document): 
    created_at = db.DateTimeField(default=datetime.datetime.now, required=True) 
    title = db.StringField(max_length=255, required=True) 
    desc = db.StringField(required=True) 

    def __unicode__(self): 
     return self.title 

什麼是格式化方便JSON用於前端的最佳方式?

+0

那麼,爲什麼?實際上,這些標識符*「服務用途」*標識了您的最終應用*真正應該知道的「對象類型」。還有其他一些方法,並且已經可用的替代JSON序列化器將僅執行此操作,因爲對象上的一般「字符串化」方法將忽略導出時的這個「類型」信息。這裏的基本是使用標準的JSON庫lib' puts或'loads'而不是BSON變體。但是你會失去這樣做的有效信息。 –

+0

在python中,大多數對象的toString方法將以$爲前綴返回對象屬性的值,即對於objectId,它將僅返回十六進制字符串,而不是具有包含十六進制字符串的$ id屬性的對象。做你想做的最簡單的方法是迭代檢測對象的字典,然後對它們進行必要的操作 – Sammaye

+0

@Blakes Seven那麼,我如何獲得JSON而不是BSON? – bivo

回答

1

如果你確信你想擺脫所有類似的情況,那麼你當然可以編寫符合該模式的代碼。例如:很顯然

[{'title': 'This is title', 'created_at': 1439129906376, 'desc': 'Description.....', '_id': '55c737029380f82fbf52eec3'}] 

,重新格式化使用JSON很簡單:

info = [ 
    { 
     "_id": { 
      "$oid": "55c737029380f82fbf52eec3" 
     }, 
     "created_at": { 
      "$date": 1439129906376 
     }, 
     "desc": "Description.....", 
     "title": "This is title" 
    }, 
    #etc... 
] 

def fix_array(info): 
    ''' Change out dict items in the following case: 
      - dict value is another dict 
      - the sub-dictionary only has one entry 
      - the key in the subdictionary starts with '$' 
     In this specific case, one level of indirection 
     is removed, and the dict value is replaced with 
     the sub-dict value. 
    ''' 
    for item in info: 
     for key, value in item.items(): 
      if not isinstance(value, dict) or len(value) != 1: 
       continue 
      (subkey, subvalue), = value.items() 
      if not subkey.startswith('$'): 
       continue 
      item[key] = subvalue 

fix_array(info) 
print(info) 

這將返回這一點。

+0

謝謝你的回答。現在我使用你的方法,但是我發現了一個更好的方法,我在自己的問題答案中描述了這個方法。 – bivo

1

我在flask-restful擴展中發現了我的問題的一個整潔的解決方案,我使用。

它提供了fields模塊。

Flask-RESTful提供了一種簡單的方法來控制您實際在響應中呈現的數據。通過fields模塊,您可以在資源中使用任何對象(ORM模型/自定義類/等)。字段還允許您格式化和過濾響應,因此您不必擔心公開內部數據結構。

在查看代碼時,顯示什麼數據以及如何格式化也很明顯。

例子:

from flask_restful import Resource, fields, marshal_with 

resource_fields = { 
    'name': fields.String, 
    'address': fields.String, 
    'date_updated': fields.DateTime(dt_format='rfc822'), 
} 

class Todo(Resource): 
    @marshal_with(resource_fields, envelope='resource') 
    def get(self, **kwargs): 
     return db_get_todo() # Some function that queries the db 

Flask-RESTful Output Fields Documentation

+0

這也適用於我。 – CraigH