Pecan 使用介绍

发布时间: 更新时间: 总字数:1401 阅读时间:3m 作者: 分享 复制网址
专栏文章
  1. OpenStack oslo.rootwrap 实现原理
  2. Openstack oslo.privsep 使用介绍
  3. Pecan 使用介绍(当前)
  4. Windows 安装 oslo.messaging 依赖问题
  5. OpenStack RPC 远程调用
  6. OpenStack oslo 简介

Pecan 是一个 WSGI(Web Server Gateway Interface) 对象调度 web 框架,具有架构设计精妙、响应快速,依赖较少的特点。在 OpenStack API 框架中使用较多。

安装

pip install pecan

使用

  • 创建项目
$ pecan create test_pecan
$ cd test_pecan
$ tree . | grep -v pyc
.
├── MANIFEST.in
├── config.py
├── public
│   ├── css
│   │   └── style.css
│   └── images
│       └── logo.png
├── setup.cfg
├── setup.py
└── test_pecan
    ├── __init__.py
    ├── app.py
    ├── controllers
    │   ├── __init__.py
    │   └── root.py
    ├── model
    │   ├── __init__.py
    ├── templates
    │   ├── error.html
    │   ├── index.html
    │   └── layout.html
    └── tests
        ├── __init__.py
        ├── config.py
        ├── test_functional.py
        └── test_units.py
  • config.py 中包含 API 入口:
app = {
    'root': 'test_pecan.controllers.root.RootController',
    'modules': ['test_pecan'],
  • root:RootController 所在的路径,API 的根 / 路径
  • modules:app.py 文件所在的包,即 setup_app 方法所在的包
  • debug:是否开启调试,生产环境建议配置为 False

分发式的路由

RootController 继承pecan.rest.RestController时,存在URL映射关系如下表所示:

Method Description Example Method(s) / URL(s)
get_one Display one record. GET /books/1
get_all Display all records in a resource. GET /books/
get A combo of get_one and get_all. GET /books/ 或 GET /books/1
new Display a page to create a new resource. GET /books/new
edit Display a page to edit an existing resource. GET /books/1/edit
post Create a new record. POST /books/
put Update an existing record. POST /books/1?_method=put 或 PUT /books/1
get_delete Display a delete confirmation page. GET /books/1/delete
delete Delete an existing record. POST /books/1?_method=delete 或 DELETE /books/1

示例

示例1

from pecan import expose, rest

class RootController(rest.RestController):

    _custom_actions = {
        'test': ['GET', 'POST'],
    }

    @expose()
    def get_one(self, arg):
        return 1

    @expose()
    def test(self):
        # header: pecan.request.headers.get('Content-Type')
        # querys: pecan.request.GET.items():
        if pecan.request.method == 'POST':
            return 'This is RootController POST test.'
        elif pecan.request.method == 'GET':
            return 'This is RootController GET test.'

其中:

  • _custom_actions 指定 test 方法接受的请求类型
  • @expose()指定返回值

在这个例子中,可以使用curl去测试:

$ curl -X GET http://127.0.0.1:8000/test
This is RootController GET test.

$ curl -X POST http://127.0.0.1:8000/test
This is RootController POST test.

示例2

from pecan import expose

class RootController(object):
    @expose()
    def index(self, arg):
        return arg

    @expose()
    def args(self, *args):
        return ','.join(args)

    @expose()
    def kwargs(self, **kwargs):
        return str(kwargs)
1. query string to arguments
$ curl http://127.0.0.1:8000/?arg=foo
foo
$ curl http://127.0.0.1:8000/kwargs?a=1&b=2&c=3
{u'a': u'1', u'c': u'3', u'b': u'2'}

2. remaining path to arguments
$ curl http://127.0.0.1:8000/args/one/two/three
one,two,three

3. POST body to arguments
$ curl -X POST "http://127.0.0.1:8000/" -H "Content-Type: application/x-www-form-urlencoded" -d "arg=foo"
foo
$ curl -X POST "http://127.0.0.1:8000/kwargs" -H "Content-Type: application/x-www-form-urlencoded" -d "name=foo;age=18"

WSME

WSME(Web Service Made Easy)是用于实现 REST 服务的 typing 库,一般和Pecan结合使用,如 OpenStack 的很多项目都使用了 Pecan + WSME 的组合来实现 API。

WSME 模块用来规范API的请求和响应值:

Type Json type
str String
unicode String
int Number
float Number
bool Boolean
Decimal String
date String (YYYY-MM-DD)
time String (hh:mm:ss)
datetime String (YYYY-MM-DDThh:mm:ss)
Arrays Array
None null
Complex types Object

例子如下:

from wsmeext.pecan import wsexpose
from pecan import rest

class RootController(rest.RestController):

    @wsexpose(int, int)
    def get_one(self, arg):
        return 1

其中:

  • @signature: 这个装饰器用来描述一个函数的输入和输出
  • @wsexpose(int, int)中第一个int表示返回值必须为int,第二个int表示请求参数必须为int。包@wsexpose@signature 的功能,效果就像Pecan的expose装饰器

在这个例子中,可以使用curl去测试:

$ curl -X GET http://127.0.0.1:8000/1
1

示例说明

以学生类为例:

{"students": [{"name": "foo", "age": 17}, {"name": "bar", "age": 18}]}

定义 Student 类和 Students 类型:

from wsme import types as wtypes

class Student(wtypes.Base):
    name = wtypes.text
    age = int

class Students(wtypes.Base):
    students = [Student]

Post/Put Body 约束

  • Controller
class RootController(rest.RestController):

    # 检查参数必须为 Student 对象
    @wsexpose(None, body=Student)
    def post(self, stu):
        print(f'name: {stu.name}, age: {stu.age}')
  • 调用
curl -X POST http://127.0.0.1:8000 -H "Content-Type: application/json" -d '{"name": "foo2", "age": 18}'

如果 post body 不是 Student 对象,将会报错。

返回值约束

  • Controller
from wsmeext.pecan import wsexpose
from pecan import rest


class RootController(rest.RestController):

    # 返回值为Student类对象,int 为传入的参数
    @wsexpose(Student, int)
    def get_one(self, id):
        if id == 1:
            stu_info = {
                'name': 'bar',
                'age': 18
            }
            # return Student(name='bar', age=18)
            return Student(**stu_info)
        else:
            raise wsme.exc.ClientSideError('something is wrong!', status_code=403)

    @wsexpose(Students)
    def get_all(self):
        stu_info_list = [
            {
                'name': 'foo',
                'age': 17
            },
            {
                'name': 'bar',
                'age': 18
            }
        ]
        # return Students(students=[Student(name='foo', age=17), Student(name='bar', age=18)])
        return Students(students=[Student(**stu_info) for stu_info in stu_info_list])
  • 调用
$ curl http://127.0.0.1:8081/1
{"name": "bar", "age": 18}

$ curl http://127.0.0.1:8081
{"students": [{"name": "foo", "age": 17}, {"name": "bar", "age": 18}]}

其他

如果觉得 wsexpose 约束太严格,可以使用如下通用方法

  • controller
import pecan
from pecan import rest

class TestController(rest.RestController):
    @pecan.expose('json')
    def get(self):
        return {"version": "1.0.0"}

    @pecan.expose('json', int)
    def put(self, foo):
        #return "foo"  # positive control
        return pecan.request.body

    @pecan.expose('json', int)
    def post(self, foo):
        #return "foo"  # positive control
        return pecan.request.body

    @pecan.expose('json', int)
    def patch(self, foo):
        #return "foo"  # positive control
        return pecan.request.body
  • 调用
$ curl -X POST http://127.0.0.1:8080/test/1 -d '{}'
"{}"
$ curl -X PUT http://127.0.0.1:8080/test/1 -d '{}'
"{}"
$ curl -X PATCH http://127.0.0.1:8080/test/1 -d '{}'
"{}"

status_code

以下示例返回值为 201

from wsmeext.pecan import wsexpose
from pecan import rest

class RootController(rest.RestController):

    @wsexpose(int, int, status_code=201)
    def get_one(self, arg):
        return 1

自定义 expose

如果用户没有指定返回值类型,默认为 json 格式:

  • api/expose.pys
import wsmeext.pecan as wsme_pecan


def expose(*args, **kwargs):
    if 'rest_content_types' not in kwargs:
        kwargs['rest_content_types'] = ('json',)
    return wsme_pecan.wsexpose(*args, **kwargs)

分布式路由

通常

  • 代码
from pecan import expose, rest


class v1Controller(rest.RestController):
    @expose()
    def get(self):
        return 'This is v1Controller GET.'


class RootController(rest.RestController):

    v1 = v1Controller()
  • 请求
$ curl -X GET http://127.0.0.1:8000/v1
This is v1Controller GET.

_lookup

  • 代码
from pecan import expose, abort
from somelib import get_student_by_name

class StudentController(object):
    def __init__(self, student):
        self.student = student

    @expose()
    def name(self):
        return self.student.name

class RootController(object):
    @expose()
    def _lookup(self, primary_key, *remainder):
        student = get_student_by_primary_key(primary_key)
        if student:
            return StudentController(student), remainder
        else:
            abort(404)
  • 请求
# 获取 id == 8 的名称
$ curl -X GET http://127.0.0.1:8000/8/name

Templating

pecan.expose 支持的渲染模板:

  • Mako
  • Genshi
  • Kajiki
  • Jinja2
  • JSON

参考

  1. https://github.com/pecan/pecan
专栏文章
  1. OpenStack oslo.rootwrap 实现原理
  2. Openstack oslo.privsep 使用介绍
  3. Pecan 使用介绍(当前)
  4. Windows 安装 oslo.messaging 依赖问题
  5. OpenStack RPC 远程调用
  6. OpenStack oslo 简介
最新评论
加载中...
Home Archives Categories Tags Statistics