使用端点更新DataStore JSON值(Python)

0 投票
1 回答
924 浏览
提问于 2025-04-18 03:25

我正在尝试使用端点来更新我的数据存储中的一些JSON值。我在GAE上有以下的数据存储...

class UsersList(ndb.Model):
    UserID = ndb.StringProperty(required=True)
    ArticlesRead = ndb.JsonProperty()
    ArticlesPush = ndb.JsonProperty()

总的来说,我想通过这个API做的事情是,让一个方法接收一个用户ID和一份阅读过的文章列表(每篇文章用一个字典表示,字典里有一个ID和一个布尔值,表示用户是否喜欢这篇文章)。我的消息(围绕这个逻辑)如下...

class UserID(messages.Message):
    id = messages.StringField(1, required=True)


class Articles(messages.Message):
    id = messages.StringField(1, required=True)
    userLiked = messages.BooleanField(2, required=True)


class UserIDAndArticles(messages.Message):
    id = messages.StringField(1, required=True)
    items = messages.MessageField(Articles, 2, repeated=True)


class ArticleList(messages.Message):
    items = messages.MessageField(Articles, 1, repeated=True)

而我用来尝试更新的API/端点方法如下...

@endpoints.method(UserIDAndArticles, ArticleList,
                  name='user.update',
                  path='update',
                  http_method='GET')
def get_update(self, request):
    userID = request.id
    articleList = request.items
    queryResult = UsersList.query(UsersList.UserID == userID)

    currentList = []

    #This query always returns only one result back, and this for loop is the only way
    # I could figure out how to access the query results.
    for thing in queryResult:
        currentList = json.loads(thing.ArticlesRead)

    for item in articleList:
        currentList.append(item)

    for blah in queryResult:
        blah.ArticlesRead = json.dumps(currentList)
        blah.put()

    for thisThing in queryResult:
        pushList = json.loads(thisThing.ArticlesPush)

    return ArticleList(items = pushList)

我在这段代码中遇到了两个问题。第一个是,我似乎无法弄清楚(使用本地的Google APIs Explorer)如何通过我的UserIDAndArticles类将一份文章列表发送到端点方法。端点方法的输入可以是messages.MessageField()吗?

另一个问题是,我在'blah.ArticlesRead = json.dumps(currentList)'这一行出现了错误。当我尝试用一些随机输入运行这个方法时,得到了以下错误...

TypeError: <Articles
 id: u'hi'
 userLiked: False> is not JSON serializable

我知道我需要自己写一个JSON编码器来解决这个问题,但我不确定传入的request.items的格式是什么样的,以及我应该如何编码它。

我对GAE和端点(还有这种服务器端编程)都很陌生,所以请多多包涵。非常感谢你们的帮助。

1 个回答

0

有几点需要注意:

  • http_method 这个应该用 POST,或者更好的是用 PATCH,因为你不是要覆盖所有的值,而只是修改一个列表,也就是在做“补丁”。
  • 你不需要使用 json.loadsjson.dumps,NDB会自动帮你处理这些。
  • 你把 Endpoints 的消息和 NDB 模型的属性搞混了。

这是我想到的方法内容:

# get UsersList entity and raise an exception if none found.
uid = request.id
userlist = UsersList.query(UsersList.UserID == uid).get()
if userlist is None:
    raise endpoints.NotFoundException('List for user ID %s not found' % uid)

# update user's read articles list, which is actually a dict.
for item in request.items:
    userslist.ArticlesRead[item.id] = item.userLiked
userslist.put()

# assuming userlist.ArticlesPush is actually a list of article IDs.
pushItems = [Article(id=id) for id in userlist.ArticlesPush]
return ArticleList(items=pushItems)

另外,你可能还需要把这个方法放在一个事务中。

撰写回答