Привет! Мы уже знаем, как создавать веб-приложения на Flask. Теперь пришло время научиться создавать API — серверную часть, которая общается с клиентом через JSON.
В этой статье мы создадим простое API для управления списком пользователей (CRUD).
В этой статье мы разберём:
- Настройку Flask-приложения
- GET — получение данных
- POST — создание данных
- PUT — обновление данных
- DELETE — удаление данных
- Что нужно знать перед началом
- Основная часть
- Настройка приложения
- GET — получение всех пользователей
- GET — получение одного пользователя
- POST — создание пользователя
- PUT — полное обновление пользователя
- PATCH — частичное обновление пользователя
- DELETE — удаление пользователя
- Полный код
- Задачи для закрепления
- Нюансы и подводные камни
- Частые ошибки и как их избежать
- Ошибка 1: Забыл jsonify() для JSON-ответа
- Ошибка 2: Неправильная обработка request.get_json()
- Ошибка 3: Глобальные переменные для хранения данных
- Шпаргалка
- Заключение
- КВИЗ
- Что дальше?
Что нужно знать перед началом
Для этого урока тебе понадобится:
- Установленный Flask
- Базовое понимание HTTP-методов и JSON
Совет: CRUD — это основа любого API: Create, Read, Update, Delete.
Основная часть
Настройка приложения
Создай файл app.py:
from flask import Flask, request, jsonify
app = Flask(__name__)
# Заглушка базы данных
users = [
{"id": 1, "name": "Анна", "age": 25},
{"id": 2, "name": "Иван", "age": 30}
]
next_id = 3
if __name__ == '__main__':
app.run(debug=True)GET — получение всех пользователей
@app.route('/users', methods=['GET'])
def get_users():
return jsonify(users)Пример запроса: GET /users
Ответ:
[
{"id": 1, "name": "Анна", "age": 25},
{"id": 2, "name": "Иван", "age": 30}
]GET — получение одного пользователя
@app.route('/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
user = next((u for u in users if u["id"] == user_id), None)
if user is None:
return jsonify({"error": "Пользователь не найден"}), 404
return jsonify(user)Пример запроса: GET /users/1
Ответ:
{"id": 1, "name": "Анна", "age": 25}POST — создание пользователя
@app.route('/users', methods=['POST'])
def create_user():
data = request.get_json()
if not data or "name" not in data or "age" not in data:
return jsonify({"error": "Имя и возраст обязательны"}), 400
global next_id
user = {"id": next_id, "name": data["name"], "age": data["age"]}
users.append(user)
next_id += 1
return jsonify(user), 201Пример запроса:
POST /users
{
"name": "Петр",
"age": 35
}Ответ:
{"id": 3, "name": "Петр", "age": 35}PUT — полное обновление пользователя
@app.route('/users/<int:user_id>', methods=['PUT'])
def update_user(user_id):
data = request.get_json()
if not data or "name" not in data or "age" not in data:
return jsonify({"error": "Имя и возраст обязательны"}), 400
user = next((u for u in users if u["id"] == user_id), None)
if user is None:
return jsonify({"error": "Пользователь не найден"}), 404
user["name"] = data["name"]
user["age"] = data["age"]
return jsonify(user)PATCH — частичное обновление пользователя
@app.route('/users/<int:user_id>', methods=['PATCH'])
def patch_user(user_id):
data = request.get_json()
user = next((u for u in users if u["id"] == user_id), None)
if user is None:
return jsonify({"error": "Пользователь не найден"}), 404
if "name" in data:
user["name"] = data["name"]
if "age" in data:
user["age"] = data["age"]
return jsonify(user)DELETE — удаление пользователя
@app.route('/users/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):
global users
user = next((u for u in users if u["id"] == user_id), None)
if user is None:
return jsonify({"error": "Пользователь не найден"}), 404
users = [u for u in users if u["id"] != user_id]
return jsonify({"message": "Пользователь удалён"})Полный код
from flask import Flask, request, jsonify
app = Flask(__name__)
users = [
{"id": 1, "name": "Анна", "age": 25},
{"id": 2, "name": "Иван", "age": 30}
]
next_id = 3
@app.route('/users', methods=['GET'])
def get_users():
return jsonify(users)
@app.route('/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
user = next((u for u in users if u["id"] == user_id), None)
if user is None:
return jsonify({"error": "Пользователь не найден"}), 404
return jsonify(user)
@app.route('/users', methods=['POST'])
def create_user():
data = request.get_json()
if not data or "name" not in data or "age" not in data:
return jsonify({"error": "Имя и возраст обязательны"}), 400
global next_id
user = {"id": next_id, "name": data["name"], "age": data["age"]}
users.append(user)
next_id += 1
return jsonify(user), 201
@app.route('/users/<int:user_id>', methods=['PUT'])
def update_user(user_id):
data = request.get_json()
if not data or "name" not in data or "age" not in data:
return jsonify({"error": "Имя и возраст обязательны"}), 400
user = next((u for u in users if u["id"] == user_id), None)
if user is None:
return jsonify({"error": "Пользователь не найден"}), 404
user["name"] = data["name"]
user["age"] = data["age"]
return jsonify(user)
@app.route('/users/<int:user_id>', methods=['PATCH'])
def patch_user(user_id):
data = request.get_json()
user = next((u for u in users if u["id"] == user_id), None)
if user is None:
return jsonify({"error": "Пользователь не найден"}), 404
if "name" in data:
user["name"] = data["name"]
if "age" in data:
user["age"] = data["age"]
return jsonify(user)
@app.route('/users/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):
global users
user = next((u for u in users if u["id"] == user_id), None)
if user is None:
return jsonify({"error": "Пользователь не найден"}), 404
users = [u for u in users if u["id"] != user_id]
return jsonify({"message": "Пользователь удалён"})
if __name__ == '__main__':
app.run(debug=True)Задачи для закрепления
Задача 1. Создай эндпоинт для получения списка товаров.
Задача 2. Создай эндпоинт для создания товара.
Задача 3. Создай эндпоинт для обновления товара.
Задача 4. Создай эндпоинт для удаления товара.
Задача 5. Что возвращает request.get_json()?
Ответы:
Задача 1.
@app.route('/products', methods=['GET'])
def get_products():
return jsonify(products)Задача 2.
@app.route('/products', methods=['POST'])
def create_product():
data = request.get_json()
# ...
return jsonify(product), 201Задача 3.
@app.route('/products/<int:product_id>', methods=['PUT'])
def update_product(product_id):
# ...
return jsonify(product)Задача 4.
@app.route('/products/<int:product_id>', methods=['DELETE'])
def delete_product(product_id):
# ...
return jsonify({"message": "Товар удалён"})Задача 5.
# request.get_json() возвращает словарь с данными из тела запросаНюансы и подводные камни
- Flask по умолчанию возвращает HTML. Для JSON используй
jsonify(). request.get_json()— для получения JSON из запроса.- Статус-коды возвращаются вторым аргументом:
jsonify(data), 201. - В режиме
debug=Trueсервер перезагружается при изменениях. - Flask не валидирует данные автоматически — нужно делать вручную.
- Глобальные переменные (
users,next_id) — небезопасны для многопоточности.
Частые ошибки и как их избежать
Ошибка 1: Забыл jsonify() для JSON-ответа
Используй jsonify(data) для JSON.
Ошибка 2: Неправильная обработка request.get_json()
Проверяй, что данные получены: if not data: return jsonify({"error": "Нет данных"}), 400
Ошибка 3: Глобальные переменные для хранения данных
Используй базу данных для продакшена.
Шпаргалка
| Что нужно | Как пишется |
|---|---|
| GET | @app.route('/users', methods=['GET']) |
| POST | @app.route('/users', methods=['POST']) |
| PUT | @app.route('/users/<int:id>', methods=['PUT']) |
| DELETE | @app.route('/users/<int:id>', methods=['DELETE']) |
| Получить JSON | request.get_json() |
| Вернуть JSON | jsonify(data) |
| Статус-код | return jsonify(data), 201 |
Заключение
Сегодня мы:
- Создали простое API на Flask
- Реализовали CRUD операции
- Работали с JSON-данными
- Разобрали обработку ошибок








