跳转到主要内容

Plone JSON API

项目描述

plone.jsonapi.core

作者:

Ramon Bartl

版本:

0.7.0

最新构建状态

Build Status

摘要

可扩展的Plone JSON API框架

介绍

此包允许用户通过JSON公开内容信息。

动机

此项目始于2012年,源于构建基于网络的iOS应用程序的数据源需求。或者更准确地说,我想学习iOS编程,并想自己构建JSON API:)

我知道,为Plone提供自己的路由机制有点尴尬,因为该机制在ZPublisher执行其工作后分发请求,但它是有效的,所以我这样做了。

限制

由于API在ZPublisher之后,因此它只能使用HTTP GETHTTP POST方法。其他方法永远不会到达API视图。

请注意,API视图具有权限zope2.View,因此您需要在自定义路由上以编程方式检查正确的权限。

参见:http://developer.plone.org/security/permission_lists.html

兼容性

plone.jsonapi.core 应该与 Python 3 上的 Plone 3、4 和 5 兼容。

示例

[buildout]
...
versions = versions

[versions]
...
simplejson = 2.0.9
werkzeug = 0.7.2

安装

官方发布版位于 pypi,因此您只需将 plone.jsonapi.core 包含到您的 buildout 配置中即可。

示例

[buildout]
...

[instance]
...
eggs =
    ...
    plone.jsonapi.core

API URL

安装后,API 视图将以名为 @@API 的浏览器视图的形式在您的 Plone 网站上可用,例如 http://localhost:8080/Plone/@@API

API框架

主要工作在 plone.jsonapi.core.browser.api 模块中完成。该模块负责转发传入的请求并将其发送到端点函数。

API路由器

路由器 负责管理和维护 API 路由到端点。

路由由所谓的“路由提供者”定义。

路由提供者可以是实现 IRouteProvider 接口的命名实用程序类,也可以是一个通过 add_route 装饰器注册的简单函数。

基本示例

最简单的路由提供者只是一个装饰过的函数

from plone.jsonapi.core import router

@router.add_route("/hello/<string:name>", "hello", methods=["GET"])
def hello(context, request, name="world"):
    return {"hello": name}

传入的上下文和请求会被转发到 @@API 视图。它可以用来查询 Plone 工具或其他实用程序或适配器。

更复杂的示例

在这个示例中,我们将添加一个名为 my_routes 的路由提供者。这个路由提供者被注册为一个命名的 实用程序

为此,我们在我们的包中添加一个名为 routes.py 的模块,并添加以下代码

from zope import interface
from plone.jsonapi.core.interfaces import IRouteProvider

class ExampleRoutes(object):
    interface.implements(IRouteProvider)


    def initialize(self, context, request):
        """ called by the json api framework"""
        pass

    @property
    def routes(self):
        return (
            ("/hello/<string:name>", "hello", self.json_hello, dict(methods=['GET'])),
        )

    def json_hello(self, context, request, name="world"):
        return {"hello": name}

要注册这个 实用程序,我们在 configure.zcml 文件中添加以下指令

<!-- Extension point for custom routes -->
<utility
    name="my_routes"
    provides="plone.jsonapi.core.interfaces.IRouteProvider"
    factory=".routes.ExampleRoutes" />

或者使用 grok

from five import grok

...

grok.global_utility(ExampleRoutes, name="my_routes", direct=False)

每个路由提供者都会在一个名为 initialize 的方法中初始化上下文和请求。该方法由 API 框架调用。

我们的路由提供者必须包含一个 routes 属性或方法。它应该返回一个路由定义的元组。每个路由定义包含 URL 规则(/hello)、端点名称(hello)、当 URL 匹配时要调用的方法(self.json_hello)以及一个包含路由 options 的附加字典

options 字典会直接传递给 Werkzeug 的路由机制。有关详细信息,请参阅: http://werkzeug.pocoo.org/docs/routing/#rule-format

要测试此路由,请浏览到 /hello API URL

http://localhost:8080/Plone/@@API/hello/JSON%20Plone%20API

结果

{
    _runtime: 0.00025200843811035156,
    hello: "JSON Plone API"
}

API URL

如果您设计自定义的 RESTful JSON API,您可能希望插入指定资源的 URL,例如

http://localhost:8080/Plone/@@API/news/news_items_1

plone.jsonapi.core.router 模块包含一个 url_for 方法。

因此,当您要插入定义的 hello 端点的 URL 时,您可以像这样添加它

from plone.jsonapi.core import router

@router.add_route("/hello/<string:name>", "hello", methods=["GET"])
def hello(context, request, name="world"):
    return {
        "url": router.url_for("hello", values={"name": name}, force_external=True),
        "hello": name,
    }

它使用Werkzeug的Werkzeug库中的MapAdapter的build方法来构建URL。详细信息,请参阅http://werkzeug.pocoo.org/docs/routing/#werkzeug.routing.MapAdapter.build

生成的JSON将如下所示

http://localhost:8080/Plone/@@API/hello/world

结果

{
    url: "http://localhost:8080/Plone/@@API/hello/world",
    runtime: 0.002997875213623047,
    hello: "world"
}

权限

您必须手动处理路由的权限。因此,如果您想限制hello路由的权限,您必须执行如下操作

from AccessControl import getSecurityManager
from AccessControl import Unauthorized

from plone.jsonapi.core import router

@router.add_route("/hello/<string:name>", "hello", methods=["GET"])
def hello(context, request, name="world"):

    if not getSecurityManager().checkPermission("ViewHelloAPI", context):
        raise Unauthorized("You don't have the 'ViewHelloAPI' permission")

    return {
        "url": router.url_for("hello", values={"name": name}, force_external=True),
        "hello": name,
    }

输出

{
    runtime: 0.0021250247955322266,
    success: false,
    error: "You don't have the 'ViewHelloAPI' permission"
}

Plone JSONAPI集成测试

启用plone.jsonapi.core后,在Plone中公开函数变得很简单。您只需将函数包装在@router.add_route装饰器中。

以下doctest将展示框架的工作原理以及如何注册新路由。

一些必要的导入

>>> import json
>>> from plone.jsonapi.core import router
>>> from plone.jsonapi.core.version import version

准备浏览器

>>> browser = self.getBrowser()

记住一些URL

>>> portal = self.getPortal()
>>> portal_url = portal.absolute_url()
>>> api_url = portal_url + "/@@API"
>>> version_url = api_url + "/version"

检查版本URL是否返回正确的版本

>>> browser.open(version_url)
>>> dct = json.loads(browser.contents)
>>> dct["url"] == version_url
True
>>> dct["version"] == version()
True

测试框架 - 添加新的GET路由

>>> @router.add_route("/hello/<string:name>", "hello", methods=["GET"])
... def hello(context, request, name="world"):
...     return dict(hello=name)

>>> browser.open(api_url + "/hello/world")
>>> json.loads(browser.contents).get("hello")
'world'

测试框架 - 添加新的POST路由

>>> @router.add_route("/hello", "hello_post", methods=["POST"])
... def hello_post(context, request):
...     return {"hello": "post"}

>>> browser.post(api_url + "/hello", "")
>>> json.loads(browser.contents).get("hello")
'post'

检查当路由抛出错误时会发生什么

>>> @router.add_route("/fail", "fail", methods=["GET"])
... def fail(context, request):
...     raise RuntimeError("This failed badly")

>>> browser.open(api_url + "/fail")
Traceback ...
>>> json.loads(browser.contents).get("message")
'This failed badly'

测试XML

>>> @router.add_route("/xml", "xml", methods=["GET"])
... def xml(context, request):
...     return {"type": "xml"}
>>> browser.open(api_url + "/xml?asxml=1")
>>> browser.contents
b'<?xml version="1.0" encoding="UTF-8" ?><root><type type="str">xml</type></root>'

测试二进制流

>>> @router.add_route("/data", "data", methods=["GET"])
... def data(context, request):
...     return self.get_testfile_path()
>>> browser.open(api_url + "/data?asbinary=1")
>>> browser.contents
b'%PDF-...'

变更日志

0.7.0 - 2020-03-29

0.6 - 2017-01-10

0.5 - 2015-07-09

0.4 - 2014-03-04

0.3 - 2014-01-23

  • 由于与plone.jsonapi.routes的命名空间冲突,将包重命名为plone.jsonapi.core

  • 删除了默认的plone路由配置。

  • 添加了version路由

  • 将路由器的url_for方法更改为提供虚拟主机正确的URL。

0.2 - 2013-08-11

  • 路由器实现更新以支持装饰函数作为路由提供者。

  • 实现了url_for功能

  • 更新了文档

0.1 - 未发布

  • 初始开发开始

项目详情


下载文件

为您的平台下载文件。如果您不确定选择哪个,请了解安装包的更多信息。

源分发

plone.jsonapi.core-0.7.0.tar.gz (45.5 kB 查看哈希)

上传于 来源

由以下支持