Python初心者が1日でREST APIを実装してみた

[Nagoya.Swift+ 5月度勉強会](https://nagoyaswiftplus.connpass.com/event/53937/)へ参加させていただきました。
自分がやったことのまとめです。

## 経緯
普段Swiftを書いていますが、機械学習などに興味がわき、とりあえずPythonのシンタックスから慣れようと思い、他言語で実装経験のあるREST APIを実装してみました。

## 実装
@Morinikki様の[PythonでREST APIをサクっと実装](http://qiita.com/Morinikki/items/c2af4ffa180856d1bf30) を参考にさせていただき、GETを実装。

エンドポイントの作り方がわかったので、同様にPOST、PUT、DELETEを生やし、peeweeの[ドキュメント](http://docs.peewee-orm.com/en/latest/peewee/querying.html)を読みながら実装しました。

```api.py
# -*- coding: utf-8 -*-
from flask import Flask, jsonify, abort, make_response, request
import peewee as pe
import random
import json

# ランダム文字列
def random_string(length, seq='0123456789abcdefghijklmnopqrstuvwxyz'):
    sr = random.SystemRandom()
    return ''.join([sr.choice(seq) for i in range(length)])


db = pe.SqliteDatabase("datas.db")

# モデル
class User(pe.Model):
    userId = pe.TextField()
    name = pe.TextField()
    caption = pe.TextField()
    old = pe.IntegerField()

    class Meta:
        database = db

api = Flask(__name__)

# ユーザの取得
@api.route('/user/<string:userId>', methods=['GET'])
def get_user(userId):
    try:
        user = User.get(User.userId == userId)
    except User.DoesNotExist:
        abort(404)

    result = {
        "result":True,
        "data":{
            "userId":user.userId,
            "name":user.name,
            "caption":user.caption,
            "old":int(user.old)
            }
        }

    return make_response(jsonify(result))

# 追加
@api.route('/user', methods=['POST'])
def post_user():
    userId = 'us_'+random_string(6)
    dataDict = json.loads(request.data)
    try:
        q = User.insert(userId=userId, name=dataDict["name"], caption=dataDict["caption"], old=dataDict["old"])
        q.execute()  # perform the insert.
        user = User.get(User.userId == userId)
    except User.DoesNotExist:
        abort(404)

    result = {
        "result":True,
        "data":{
            "userId":user.userId,
            "name":user.name,
            "caption":user.caption,
            "old":int(user.old)
            }
        }

    return make_response(jsonify(result))

# 更新
@api.route('/user/<string:userId>', methods=['PUT'])
def put_user(userId):
    dataDict = json.loads(request.data)
    try:
        q = User.update(name=dataDict["name"], caption=dataDict["caption"], old=dataDict["old"]).where(User.userId == userId)
        q.execute()
    except User.DoesNotExist:
        abort(404)

    result = {
        "result":True
        }

    return make_response(jsonify(result))

# 削除
@api.route('/user/<string:userId>', methods=['DELETE'])
def del_user(userId):
    try:
        q = User.delete().where(User.userId == userId)
        q.execute() 
    except User.DoesNotExist:
        abort(404)

    result = {
        "result":True,
        }

    return make_response(jsonify(result))

# 全ユーザ取得
@api.route('/users', methods=['GET'])
def get_users():
    try:
        users = User.select()
    except User.DoesNotExist:
        abort(404)

    arr = []
    for user in users:
        arr.append({
            "userId":user.userId,
            "name":user.name,
            "caption":user.caption,
            "old":int(user.old)
            })

    result = {
        "result":True,
        "data":arr
        }

    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=3000)

```

## 所感
大体ここまでが5時間ぐらいで実装できました。
初Pythonにしてはなかなかうまくできたのではないかと思います。
ただ、理解しながら書いたわけではないのでしっかりと理解を深めることが必要。

この後、余った時間でiOSクライアント(時間の都合でGETとDELETEのみ実装)を作り、デモできたのは良かった(Nagoya.Swift+という勉強会なのでどこかでSwiftを書きたかった)