Flaskアプリケーションでコーディングテストをしてみた

こんばんは。

Flaskアプリケーションでコーディングテストをしてみました。

# 問題

簡単なFlaskアプリケーションを作成し、本のリストを管理するRESTful APIを提供してください。それぞれの本は、id、title、authorを持ちます。APIは以下の操作をサポートする必要があります：

- GET /books: 全ての本のリストを取得します。
- POST /books: 新しい本を追加します。
- GET /books/<id>: 特定のIDを持つ本を取得します。
- PUT /books/<id>: 特定のIDを持つ本を更新します。
- DELETE /books/<id>: 特定のIDを持つ本を削除します。

# 要件:

- メモリ内リストを使用して本を保存します。
- 入力データを検証し、titleとauthorが空でない文字列であることを確認します。
- 適切なHTTPステータスコードを返します（例：200、201、404、400）。

# コーディング

```python
from flask import Flask, request, jsonify

app = Flask(__name__)

# メモリ内リストに本を保存
books = []
next_id = 1

@app.route('/books', methods=['GET'])
def get_books():
    return jsonify(books)

@app.route('/books', methods=['POST'])
def add_book():
    global next_id
    data = request.json
    title = data.get('title')
    author = data.get('author')

    if not title or not author:
        return jsonify({'error': 'Titleとauthorは必須です。'}), 400

    book = {
        'id': next_id,
        'title': title,
        'author': author
    }
    global next_id
    next_id += 1
    books.append(book)
    return jsonify(book), 201

@app.route('/books/<int:id>', methods=['GET'])
def get_book(id):
    book = next((b for b in books if b['id'] == id), None)
    if book is None:
        return jsonify({'error': '本が見つかりません。'}), 404
    return jsonify(book)

@app.route('/books/<int:id>', methods=['PUT'])
def update_book(id):
    data = request.json
    title = data.get('title')
    author = data.get('author')

    if not title or not author:
        return jsonify({'error': 'Titleとauthorは必須です。'}), 400

    book = next((b for b in books if b['id'] == id), None)
    if book is None:
        return jsonify({'error': '本が見つかりません。'}), 404

    book['title'] = title
    book['author'] = author
    return jsonify(book)

@app.route('/books/<int:id>', methods=['DELETE'])
def delete_book(id):
    global books
    books = [b for b in books if b['id'] != id]
    return '', 204

if __name__ == '__main__':
    app.run(debug=True)
```

# 説明 (ルートとメソッドの定義)

## 全ての本を取得する（GET /books）

```python@app.route('/books', methods=['GET'])
def get_books():
    return jsonify(books)
```

`/books` エンドポイントに対してGETリクエストが来たときに、books リストの内容をJSON形式で返します。

## 新しい本を追加する（POST /books）

```python
@app.route('/books', methods=['POST'])
def add_book():
    global next_id
    data = request.json
    title = data.get('title')
    author = data.get('author')

    if not title or not author:
        return jsonify({'error': 'Titleとauthorは必須です。'}), 400

    book = {
        'id': next_id,
        'title': title,
        'author': author
    }
    next_id += 1
    books.append(book)
    return jsonify(book), 201
```

- `/books` エンドポイントに対してPOSTリクエストが来たときに、新しい本をリストに追加します。
- `request.json` でリクエストのボディからJSONデータを取得します。
- `title` または author が空の場合、400エラーとエラーメッセージを返します。
- 新しい本を作成し、books リストに追加します。
- 新しく追加した本の情報と201ステータスコードを返します。

## 特定のIDの本を取得する（GET /books/<id>）

```python
@app.route('/books/<int:id>', methods=['GET'])
def get_book(id):
    book = next((b for b in books if b['id'] == id), None)
    if book is None:
        return jsonify({'error': '本が見つかりません。'}), 404
    return jsonify(book)
```

- `/books/<id>` エンドポイントに対してGETリクエストが来たときに、指定されたIDの本を検索します。
- `next` 関数を使って、指定されたIDと一致する本をリストから検索します。
- 本が見つからない場合は404エラーとエラーメッセージを返します。
- 見つかった本の情報をJSON形式で返します。

## 特定のIDの本を更新する（PUT /books/<id>）

```python
@app.route('/books/<int:id>', methods=['PUT'])
def update_book(id):
    data = request.json
    title = data.get('title')
    author = data.get('author')

    if not title or not author:
        return jsonify({'error': 'Titleとauthorは必須です。'}), 400

    book = next((b for b in books if b['id'] == id), None)
    if book is None:
        return jsonify({'error': '本が見つかりません。'}), 404

    book['title'] = title
    book['author'] = author
    return jsonify(book)
```

- `/books/<id>` エンドポイントに対してPUTリクエストが来たときに、指定されたIDの本を更新します。
- `request.json` でリクエストのボディから新しいデータを取得します。
- `title` または `author` が空の場合、400エラーとエラーメッセージを返します。
- 指定されたIDの本をリストから検索し、見つからない場合は404エラーとエラーメッセージを返します。
- 見つかった本を更新し、その本の新しい情報をJSON形式で返します。

## 特定のIDの本を削除する（DELETE /books/<id>）

```python@app.route('/books/<int:id>', methods=['DELETE'])
def delete_book(id):
    global books
    books = [b for b in books if b['id'] != id]
    return '', 204
```

- `/books/<id>` エンドポイントに対してDELETEリクエストが来たときに、指定されたIDの本を削除します。
- `books` リストから指定されたIDの本を取り除きます。
- 削除成功後、204ステータスコードを返します（レスポンスボディは空です）。


このアプリケーションを実行すると、RESTful APIを介して本のリストを管理できるシンプルなアプリケーションが動作します。

今日は以上です。

ありがとうございました。
よろしくお願いいたします。