1

我必须对Club具有memberstype的 a 进行建模User。显然,一个俱乐部可以有大量的成员。

我已经做到了

class User(EndpointsModel):
    username = ndb.StringProperty(required=True)


class Club(EndpointsModel):
    ....
    members_key = ndb.KeyProperty(kind="User", repeated=True)

    @EndpointsAliasProperty(repeated=True,property_type=User.ProtoModel())
    def members(self):
        return ndb.get_multi(self.members_key)

在响应中这样做我得到了整个用户列表,如果我有 5000 名成员可能需要一段时间。

是否有可能将此列表分页?也许使用ProtoCollection()而不是ProtoModel()?(我试过没有成功)。

或者,我如何创建一个类型的端点/club/{id}/members,让我返回成员列表(分页)?

4

2 回答 2

1

还有许多其他方法可以实现多用户对一个俱乐部的关系 - 我想在 User 中存储一个“俱乐部”重复属性,该属性引用他们所属的俱乐部(存储俱乐部的密钥)。您查询满足 clubs 属性的用户,并将结果限制为页面大小。使用类似的模式

next_page_results = User.all().filter('club =', club_key).filter('__key__ >', last_seen_key).order('key').run(limit=page_size)

确保页面被正确检索,在正确的位置开始和停止

last_seen_key = next_page_results[-1]下一个电话在哪里)

你这样做的方式是每次都获取所有结果并在内存中过滤。这很糟糕,而且会花钱。

于 2014-12-13T23:35:32.497 回答
1

我来了 我做了一些测试,我找到了这个解决方案(在club/{id}/members

我为标准端点创建了一个资源容器。消息复制了query_method作为输入的内容。

ID_RESOURCE_PAGE = endpoints.ResourceContainer(
    message_types.VoidMessage,
    id=messages.IntegerField(1, variant=messages.Variant.INT64),
    cursor=messages.StringField(2, variant=messages.Variant.STRING, required=False, default="1"),
    limit=messages.IntegerField(3, variant=messages.Variant.INT32, required=False, default=10)
)

然后我创建了一个@endopint.method这样的标准

@endpoints.method(ID_RESOURCE_PAGE, User.ProtoCollection(),
                      path='club/{id}/members',
                      http_method='GET',
                      name='club.members')
    def club_memebers(self, request):
        # check if user has ownership
        club = Club.get_by_id(request.id)
        page_size = request.limit
        # convert the cursors, usually it's a token, here is page number.
        page = int(request.cursor)
        # internal check, just in case.
        if (page is None or page < 0):
            raise endpoints.BadRequestException(message="Page field must be a positive integer")
        if (page_size is None or page_size < 0 or page > 100):
            raise endpoints.BadRequestException(
                message="Page_size field must be a positive integer and cannot be greater than 100")
        # compute start and end users to retrive
        start = (page - 1) * page_size
        end = page * page_size
        # crop the list
        res_list = club.membersUser[start:end]
        # create the object
        ret = User.ToMessageCollection(res_list)
        # it's probably another page
        if (len(res_list) == page_size):
            # add next page as nextPageToken, not the best but the easy way
            ret.nextPageToken = str(page + 1)
        return ret

需要注意的是,我曾经User.ProtoCollection()让集合自动序列化,并且我将页码伪造为ret.nextPageToken. 最后一次编辑看起来不太干净(实际上不是),但查询有效。

不过,我对这个解决方案并不满意。

于 2014-10-27T07:38:55.693 回答