Google云端点api的干代码

2024-05-15 00:44:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我想避免为我的googleappengine应用程序的不同模型创建Google云端点api的样板代码。假设我有一个PostUser和{}模型。数据存储在数据存储中。我想用资源postsusers和{}创建一个restapi。我为posts资源编写了以下代码:

import endpoints
from protorpc import messages
from protorpc import message_types
from protorpc import remote
from blog.models import Post
from cloud_endpoints import WEB_CLIENT_ID, ANDROID_CLIENT_ID, IOS_CLIENT_ID, ANDROID_AUDIENCE


class PostMessage(messages.Message):
    id = messages.StringField(1)
    title = messages.StringField(2)
    body = messages.StringField(3)


class PostMessageCollection(messages.Message):
    post_messages = messages.MessageField(PostMessage, 1, repeated=True)


def post_to_message(post):
    return PostMessage(
        id=str(post.key()),
        title=post.title,
        body=post.body)


ID_RESOURCE = endpoints.ResourceContainer(
    message_types.VoidMessage,
    id=messages.StringField(1, variant=messages.Variant.STRING))

PUT_RESOURCE = endpoints.ResourceContainer(
    PostMessage,
    id=messages.StringField(1, variant=messages.Variant.STRING))

POST_RESOURCE = endpoints.ResourceContainer(Post)


@endpoints.api(name='posts',
               version='v1',
               allowed_client_ids=[WEB_CLIENT_ID, ANDROID_CLIENT_ID, IOS_CLIENT_ID],
               audiences=[ANDROID_AUDIENCE])
class PostsApi(remote.Service):
    """List"""
    @endpoints.method(message_types.VoidMessage,
                      PostMessageCollection,
                      path='/posts',
                      http_method='GET',
                      name='posts.listPosts')
    def list(self, unused_request):
        post_messages = []
        for post in Post.all():
            post_messages.append(post_to_message(post))

        return PostCollection(post_messages=post_messages)

    """Get"""
    @endpoints.method(ID_RESOURCE,
                      PostMessage,
                      path='/posts/{id}',
                      http_method='GET',
                      name='posts.getPost')
    def get(self, request):
        try:
            return post_to_message(Post.get(request.id))

        except (IndexError, TypeError):
            raise endpoints.NotFoundException('Post %s not found.' % (request.id,))

    """Create"""
    @endpoints.method(POST_RESOURCE,
                      message_types.VoidMessage,
                      path='/posts',
                      http_method='POST',
                      name='posts.createPost')
    def create(self, request):
        post = Post(title=request.title, body=request.body)\
        post.put()
        return message_types.VoidMessage()

    """Update"""
    @endpoints.method(PUT_RESOURCE,
                      message_types.VoidMessage,
                      path='/posts/{id}',
                      http_method='POST',
                      name='posts.updatePost')
    def update(self, request):
        try:
            post = Post.get(request.id)
            post.title = request.title
            post.body = request.body
            return message_types.VoidMessage()
        except (IndexError, TypeError):
            raise endpoints.NotFoundException('Post %s not found.' % (request.id,))

    """Delete"""
    @endpoints.method(ID_RESOURCE,
                      message_types.VoidMessage,
                      path='/posts/{id}',
                      http_method='DELETE',
                      name='posts.deletePost')
    def delete(self, request):
        try:
            post = Post.get(request.id)
            post.delete()
            return message_types.VoidMessage()

        except (IndexError, TypeError):
            raise endpoints.NotFoundException('Post %s not found.' % (request.id,))

我可以复制/粘贴这段代码,将“Post”改为“Category”,并编辑PostMessagePostMessageCollection和{},但这似乎是一种不好的做法。我不想重复我自己的话。是否可以创建一个抽象的API类并为PostAPICategoryAPI和{}创建子类?或者,有没有更好的方法来参数化PostPostMessagePostMessageCollectionpost_to_message和资源路径(“/posts”、“/categories”和“/users”),这样我就不必为每个资源复制/粘贴类了吗?类将具有相同的方法和相同的修饰符,我不想对每个资源重复这一点。我使用python2.7。在


Tags: idmessagetitlerequestbodypostmethodtypes
2条回答

这条线已经用了两年了,但无论如何我还是要提出一个想法。它有一个明显的缺陷;下面将详细介绍。在

我假设您正在通过ndbapi使用数据存储。在

其想法是引入通用消息类(EntityContainerEntityContainerList),它可以包含任何应用程序特定消息类的实例,并包含一个字典,将路由映射到protorpc和{}类:

模型.py

class Book(ndb.Model):
    title = ndb.StringProperty()
    author = ndb.StringProperty()

class Movie(ndb.Model):
    title = ndb.StringProperty()
    director = ndb.StringProperty()

主.py

^{pr2}$

当然,也可以使用DELETEPUT和{}方法。在

您拥有的消息类越有用,这种方法可以为您节省的代码越多。(我刚刚包含了两个BookMovie作为演示。)

上面提到的缺陷是,EntityContainer类中的消息字段太多,任何类实例都只使用其中两个字段。我不知道事情在幕后是如何运作的,所以我无法评估这件事的严重性。在

不幸的是,这个问题也不可能。方法装饰器需要请求描述(PostMessageCollection这里)。子类化message.Message的请求描述不允许通过继承重用,因此所有的消息类都必须在没有任何继承的情况下完整地定义。在

不过,我现在还不能达到这样的程度:

# All the message and response definitions have to be here, complete.

class PostMessage(messages.Message):
    id = messages.StringField(1)
    title = messages.StringField(2)
    body = messages.StringField(3)


class PostMessageCollection(messages.Message):
    post_messages = messages.MessageField(PostMessage, 1, repeated=True)


def post_to_message(post):
    return PostMessage(
        id=str(post.key()),
        title=post.title,
        body=post.body)


ID_RESOURCE = endpoints.ResourceContainer(
    message_types.VoidMessage,
    id=messages.StringField(1, variant=messages.Variant.STRING))

PUT_RESOURCE = endpoints.ResourceContainer(
    PostMessage,
    id=messages.StringField(1, variant=messages.Variant.STRING))

POST_RESOURCE = endpoints.ResourceContainer(Post)

# Now define all the 'Category' related messages here.


@endpoints.api(name='posts_n_categories',  # The name can be a common one.
               version='v1',
               allowed_client_ids=[WEB_CLIENT_ID, ANDROID_CLIENT_ID, IOS_CLIENT_ID],
               audiences=[ANDROID_AUDIENCE])
class BaseAPI(remote.Service):
    """List"""
    # Common defs go here.
    MessageCollection = messages.Message
    PATH = '/'
    NAME = ''

    @staticmethod
    def converter(x):
        raise NotImplemented

    iterator = []
    collection = messages.Message
    @endpoints.method(message_types.VoidMessage,
                      MessageCollection,
                      path=PATH,
                      http_method='GET',
                      name=NAME)
    def list(self, unused_request):
        # Do the common work here. You can 
        _messages = []
        for post in self.__class__.iterator.all():
            _messages.append(self.__class__.converter(post))

        return self.__class__.collection(post_messages=_messages)




@endpoints.api(name='posts',  # The name can be different.
               version='v1',
               allowed_client_ids=[WEB_CLIENT_ID, ANDROID_CLIENT_ID, IOS_CLIENT_ID],
               audiences=[ANDROID_AUDIENCE])
class PostAPI(Base):
    # Post specific defs go here.
    MessageCollection = PostMessageCollection
    PATH = '/posts'
    NAME = 'posts.listPosts'
    converter = post_to_message
    iterator = Post
    collection = PostCollection


# Define the category class here.

显然,这并不能节省多少时间。在

相关问题 更多 >

    热门问题