API star - Python3用 Web API framework

最近何度か名前を目にした Webアプリケーションフレームワーク API Star を試してみた

github.com

まだ開発中のフレームワークだが、Pythonの型アノテーションをうまく利用して、Web APIを簡単に開発できるようになっている。

インストール

githugからソースをダウンロードして実行してみた

$ git clone https://github.com/encode/apistar.git
$ pip install -e .

アプリケーションの作成

apistar コマンドでひな形を作成する。

$ apistar new test
test/app.py
test/tests.py

アプリケーションの実行

作成した app.py を実行する。

$ python app.py start
 * Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)
 * Restarting with fsevents reloader
 * Debugger is active!
 * Debugger PIN: 233-378-852

APIの追加

app.py を次のように修正する

from apistar import Include, Route
from apistar.frameworks.wsgi import WSGIApp as App
from apistar.handlers import docs_urls, static_urls
from apistar import typesystem

def welcome(name=None):
    if name is None:
        return {'message': 'Welcome to API Star!'}
    return {'message': 'Welcome to API Star, %s!' % name}


# ここから追加
class IntProp(typesystem.Integer):
    minimum = 1
    maximum = 5

class EnumProp(typesystem.Enum):
    enum = ['one', 'two', 'three']

class RetType(typesystem.Object):
    properties = {
        'strprop': typesystem.string(max_length=100),
        'intprop': IntProp,
        'enumprop': EnumProp,
    }

def api1(intprop: IntProp, enumprop: EnumProp) -> RetType:
    return RetType(strprop='abc', intprop=intprop, enumprop=enumprop)

# ここまで追加


routes = [
    Route('/', 'GET', welcome),
    Route('/api1', 'GET', api1),   # この行を追加
    Include('/docs', docs_urls),
    Include('/static', static_urls)
]

app = App(routes=routes)


if __name__ == '__main__':
    app.main()

この例では、2つのデータ型を定義して、関数 api1() の引数として指定している。一つは 1 から 5 までの整数値を表す型で、もう一つは文字列のone, two, three のいずれかの文字列の列挙型だ。

app.py を再起動し、ブラウザで http://127.0.0.1:8080/docs/# を開く。

f:id:atsuoishimoto:20170912083047p:plain

作成した APIが表示され、INTERACT をクリックするとAPIを実行できる。

f:id:atsuoishimoto:20170912083326p:plain

Webページの作成

APIだけではなく、Jinjaテンプレートを使って通常のHTMLも作成できる。

def generate_htmlpage(name, templates: Templates):
    templ = templates.get_template('hello.html')    # templates/hello.htmlを使用
    return templ.render(username=name)

RDBの利用

RDBへのアクセス手段として、SQLAlchemyとDjango-ORMを使用できる。

from apistar import Include, Route
from apistar.frameworks.wsgi import WSGIApp as App
from apistar.handlers import docs_urls, static_urls

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String

from apistar.backends import sqlalchemy_backend

Base = declarative_base()

# Testテーブルの定義
class Test(Base):
    __tablename__ = "Test"
    id = Column(Integer, primary_key=True)
    name = Column(String)


def create_test(session: sqlalchemy_backend.Session, name: str):
    # Testテーブルにデータを登録し、idを返す
    test = Test(name=name)
    session.add(test)
    session.flush()
    return {'id': test.id}

routes = [
    Route('/create_test', 'GET', create_test),
    Include('/docs', docs_urls),
    Include('/static', static_urls)
]

# Configure database settings.
settings = {
    "DATABASE": {
        "URL": "sqlite:///test.sqlite",
        "METADATA": Base.metadata
    }
}

app = App(
    routes=routes,
    settings=settings,
    commands=sqlalchemy_backend.commands,  # Install custom commands.
    components=sqlalchemy_backend.components  # Install custom components.
)


if __name__ == '__main__':
    app.main()

この例では、SQLAlchemyとSQLiteを使ってデータを登録している。app.pycreate_tables コマンドでテーブルを作成できる。

$ python app.py create_tables