MongoDB ReferenceField到JSON

时间:2018-01-17 08:05:47

标签: python flask mongoengine flask-mongoengine

我正在使用Flask编写API。我为撰写帖子的用户使用了ReferenceField。 API应返回一个JSON对象,其中包含有关帖子的数据和有关用户的数据。

Flask端点:

@app.route("/api/posts")
def posts_index():
    posts = Post.objects()
    return jsonify({
        "posts": json.loads(posts.to_json())
    })

数据库模型:

class User(Document):
    email = EmailField(required=True, unique=True)
    username = StringField(max_length=50, required=True, unique=True)
    password = StringField(required=True)
    created = DateTimeField(required=True, default=datetime.datetime.now())


class Comment(EmbeddedDocument):
    content = StringField(max_length=5000)
    user = ReferenceField(User)
    created = DateTimeField(required=True, default=datetime.datetime.now())


class Post(Document):
    title = StringField(max_length=120, required=True)
    user = ReferenceField(User, reverse_delete_rule=CASCADE)
    content = StringField(max_length=5000)
    comments = ListField(EmbeddedDocumentField(Comment))
    created = DateTimeField(required=True, default=datetime.datetime.now())

JSON回复:

{
  "posts": [
    {
      "_id": {
        "$oid": "5a5efd1f9ef3161fc64cb95a"
      }, 
      "comments": [], 
      "content": "Lorem Ipsum", 
      "created": {
        "$date": 1516178223018
      }, 
      "title": "Hello", 
      "user": {
        "$oid": "5a5d0b9b9ef316220b6d9881"
      }
    }, 
    {
      "_id": {
        "$oid": "5a5efd1f9ef3161fc64cb95b"
      }, 
      "comments": [], 
      "content": "Lorem Ipsum Dolor", 
      "created": {
        "$date": 1516178223018
      }, 
      "title": "Hello Again", 
      "user": {
        "$oid": "5a5d0b9b9ef316220b6d9881"
      }
    }
  ]
}

我想获得json响应,但ReferenceField应该包含有关用户的信息。

2 个答案:

答案 0 :(得分:0)

首先,您应该递归遍历所有字段,最后尝试获取其值。我写了一个小函数来做到这一点。

from mongoengine import Document, EmbeddedDocument
from mongoengine.queryset import QuerySet


def to_dict(obj):
    if isinstance(obj, (QuerySet, list)):
        return map(to_dict, obj)
    elif isinstance(obj, (Document, EmbeddedDocument)):
        doc = {}
        for field_name, field_type in obj._fields.iteritems():
            field_value = getattr(obj, field_name)
            doc[field_name] = to_dict(field_value)
        return doc
    else:
        return obj

将此功能称为to_dict(Posts.objects)to_dict(Post.objects.first()),您应该会收到深层词典。

接下来,使用自定义json编码器创建json响应。

import json, bson


def json_response(obj, cls=None):
    response = make_response(json.dumps(obj, cls=cls))
    response.content_type = 'application/json'

    return response

class MongoJsonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, bson.ObjectId):
            return str(obj)

        if isinstance(obj, bson.DBRef):
            return str(obj.id)

        return json.JSONEncoder.default(self, obj)

@app.route('/')
def index():
    posts_json = to_dict(Post.objects)
    return json_response(dict(data=posts_json), cls=MongoJsonEncoder)

答案 1 :(得分:0)

hasattr不适用于属性名称$ oid 例如:

value = {'$oid': '5e8764ed70f190b802bdc008'}
if hasattr(value, '$oid'):
    print('this never prints')

我必须以这种方式访问​​它:

try:
    oid = value['$oid']
    print('this works')
except:
    print('no oid')