包含Blobstore密钥作为属性的NDB模型失败to_dict()

时间:2014-01-23 12:59:56

标签: python google-app-engine

class Door(ndb.Model):
    key = ndb.BlobKeyProperty(required=True)
    locked = ndb.BooleanProperty(default=True)

我需要将门转换为字典,如:door.to_dict()

但它没有说:

BlobKeyProperty Reference is not json serializable

我做错了吗?

3 个答案:

答案 0 :(得分:3)

您不应该使用key作为属性名称。 key是模型密钥的已定义访问器。

答案 1 :(得分:2)

除了蒂姆霍夫曼提到的关于钥匙的部分之外,没有你这样做是正确的(至to_dict()被认为)。这是一个错误。

如果某个属性无法转换为json,那么您需要将其转换为自己。

例如,日期不能自动转换为json,因为转换后不会知道转换它们的日期格式:

class Door(ndb.Model):
    creation_date = ndb.DateTimeProperty(auto_now_add=True)
    locked = ndb.BooleanProperty(default=True)

做的:

door.to_dict(exclude=['creation_date'])

然后找到一种方法将日期转换为您需要的格式并将其附加到创建的dict。

答案 2 :(得分:1)

您不应在您的门模型上使用钥匙作为财产。什么是关键参考?一个不同的模型?如果是这样,请使用other_model = ndb.BlobKeyProperty(required = True)。

如果你想在to_dict响应中使用门的密钥,只需覆盖to_dict()方法:

类门(ndb.Model):     other_model = ndb.BlobKeyProperty(required = True)     locked = ndb.BooleanProperty(默认= True)

def to_dict(self, *args, **kwargs):
    d = super(Door, self).to_dict(args, kwargs)
    if 'key' not in d:
        d['key'] = self.key
    return d

如果你这样做是为了返回一个json响应,我发现以下更多用处。编写自己的jsonEncoder。我这样做:

import json
import webapp2
import datetime
import calendar
from google.appengine.ext import ndb


class jsonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return calendar.timegm(obj.utctimetuple())

        if isinstance(obj, datetime.date):
            return calendar.timegm(obj.timetuple())

        # If it is a key, return it in it's urlsafe format
        elif isinstance(obj, ndb.Key):
            return obj.urlsafe()

        elif isinstance(obj, ndb.Model):
            d = obj.to_dict()
            if obj.key is not None:
                d['key'] = obj.key.urlsafe()
            return d

        elif isinstance(obj, list):
            pass

        elif isinstance(obj, datastore_types.BlobKey):
            pass

        else:
            return json.JSONEncoder.default(self, obj)

然后,我创建了一个JsonHandler:

class JsonHandler(webapp2.RequestHandler):
    def initialize(self, request, response):
        super(JsonHandler, self).initialize(request, response)
        self.response.headers['Content-Type'] = 'application/json'

    def render_response(self, **context):
        return self.response.write(json.dumps(context, cls=jsonEncoder))

最后,继承JsonHandler:

class DoorHandler(JsonHandler):
    def get(self):
        door = Door.query().get()
        return self.render_response(door=door)

然后您不必覆盖to_dict方法,并且可以处理所有类型的数据。