#どうやってAPIって提供されているのか?
いつも使う側なので、提供側を経験したく。
インフラエンジニアだと、ミドルウェア設計までで終わっていて、あとはアプリに"はい、どうぞ"なので。
#前準備
例のごとく、ネット環境無いのでパッケージから導入。
python-babel-0.9.6-8.el7.noarch.rpm
python-flask-0.10.1-4.el7.noarch.rpm
python-itsdangerous-0.23-2.el7.noarch.rpm
python-jinja2-2.7.2-2.el7.noarch.rpm
python-markupsafe-0.11-10.el7.x86_64.rpm
python-werkzeug-0.9.1-2.el7.noarch.rpm
python2-peewee-2.10.2-1.fc27.x86_64.rpm
#実装
###■まずはデータを用意
今回はデータベースにpeewee,webフレームワークにflaskを使う。
peeweeで以下のデータとimport用のスクリプトを用意し、一気にデータを作成する。
#タブ区切り
#user firm isprivileged
Us01 firm1 True
Us02 firm2 True
Us03 firm3 False
Us04 firm4 False
Us05 firm5 True
Us06 firm6 False
Us07 firm7 True
Us08 firm8 False
項目はタブ区切り。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from peewee import *
db = SqliteDatabase('base.db')
class BaseModel(Model):
class Meta:
database = db
class User(BaseModel):
user = TextField()
firm = TextField()
isprivileged = BooleanField()
#モデルの定義に基いてテーブル作成
User.create_table()
#ファイルをreadモードで開き、1行ずつ読み込む
for line in open("userlist.tsv", "r"):
(user, firm, isprivileged) = tuple(line[:-1].split("\t"))
if user == '#user': #1行目が見出しなので、読み込まないように
pass
else:
#レコードを作成
User.create(user=user,
firm=firm,
isprivileged=isprivileged)
#レコードから値を取得して格納
a = User.get(User.user == user).user
b = User.get(User.user == user).firm
c = User.get(User.user == user).isprivileged
print 'created record : user=' + str(a) + ' firm=' + str(b) + ' privilegelevel=' + str(c)
以下はpeeweeのチュートリアルに載ってた、お約束事的なもの。
db = SqliteDatabase('base.db')
→DBはsqliteを使うよ、DBファイルはbase.dbを使うよ。
class BaseModel(Model):
class Meta:
database = db
→モデル定義し、それが上で言ってたDBと紐付くよ。
※peeweeではモデルなるものを作成して、DBを紐付けて操作をするらしい。
class User(BaseModel):
user = TextField()
firm = TextField()
isprivileged = BooleanField()
→BaseModelをオーバーライドして、Userというモデルを定義して、フィールドを定義。
※これは省略できるか?ただ、何個もモデルを持たせるなら、BaseModel定義はあった方がいい気がする。
上記を実行すると、以下の結果。
# ./import.py
created record : user=Us01 firm=firm1 privilegelevel=True
created record : user=Us02 firm=firm2 privilegelevel=True
created record : user=Us03 firm=firm3 privilegelevel=True
created record : user=Us04 firm=firm4 privilegelevel=True
created record : user=Us05 firm=firm5 privilegelevel=True
created record : user=Us06 firm=firm6 privilegelevel=True
created record : user=Us07 firm=firm7 privilegelevel=True
created record : user=Us08 firm=firm8 privilegelevel=True
#
DBから値を取得するには、pythonのインタプリタに入った後、以下のように実行する。
>>>from peewee import *
>>>db = SqliteDatabase('base.db')
>>>class BaseModel(Model):
... class Meta:
... database = db
...
>>>
>>>class <Model>(BaseModel):
... <Field1> = TextField()
... <Field2> = TextField()
... <Field3> = BooleanField()
...
>>>
>>><Model>.get(<Model>.<検索するField> == "検索キー").<値を取得したいField>
"<>"内は適宜読み替えてください。
###■FlaskでAPI
以下のスクリプト作成。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask, jsonify, abort, make_response, Response, request, url_for
from peewee import *
#利用するDB定義 ここから--------
db = SqliteDatabase("base.db")
class BaseModel(Model):
class Meta:
database = db
class User(BaseModel):
user = TextField()
firm = TextField()
isprivileged = TextField()
#ここまで----------------------
#Flask使うぜ!
api = Flask(__name__)
@api.route('/getUser/<string:users>', methods=['GET'])
def get_user(users):
try:
user = User.get(User.user == users)
except User.DoesNotExist:
abort(404)
result = {
"result":0,
"data":{
"User":user.user,
"firm":User.firm,
"isprivileged":User.isprivileged
}
}
return make_response(jsonify(result))
@api.errorhandler(404)
def not_found(error):
return make_response(jsonify({'error': 'Not found'}), 404)
if __name__ == '__main__':
api.run(host='0.0.0.0', port=80)
上記を部分ごとに説明。
@api.route('/getUser/string:users', methods=['GET'])
・"@"でデコレートする。
・Flaskでは、ユーザがアクセス先と許可するメソッドを@api.route()の中に書く。
apiは上でインスタンス化した"api = Flask(name)"なので、個々人の設定に沿う。
・string:usersはユーザが入力した値を変数usersに格納する、ということ。
def get_user(users):
try:
user = User.get(User.user == users)
except User.DoesNotExist:
abort(404)
・ユーザがアクセスしてきた際の処理内容を定義する。
・ユーザが入力した変数usersを使って、"User.get(User.user == users)"で
レコードが存在するか確認、なければ"abort(404)"する。
・abortはFlaskの便利屋さんで、"@api.errorhandler(404)"まで飛ばしてくれる。
return make_response(jsonify(result))
・resultに格納した内容をjson化して返却。
@api.errorhandler(404)
def not_found(error):
return make_response(jsonify({'error': 'Not found'}), 404)
・エラーハンドリング。ここでabortした際の処理が発生。
api.run(host='0.0.0.0', port=80)
・実際に動かします。
・"host='0.0.0.0'"は自身のIPアドレスになる。
・ポートを指定。デフォルトは確か80。
・debugしたいなら、api.run()の中に"debug=True"を加える(カンマ区切り)。
###■利用してみる
利用できる状態にするには、api.pyを実行します。
# ./api.py &
[1] 1738
# * Running on http://0.0.0.0:80/
Enter押せばプロンプト戻ります。
この状態で、別のブラウザなりlinuxなりからアクセスする。
以下はLinuxの例。
# curl -i -k http://XXX.XXX.XXX.XXX:80/getUser/Us01
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 100
Server: Werkzeug/0.9.1 Python/2.7.5
Date: Thu, 15 Mar 2018 03:32:40 GMT
{
"data": {
"User": "Us01",
"firm": "firm1",
"isprivileged": true
},
"result": 0
}
#