Привет! В REST API каждый HTTP-метод имеет своё предназначение. Понимание этих методов — основа для создания правильных и удобных API.
В этой статье мы разберём:
- GET — получение данных
- POST — создание данных
- PUT — полное обновление
- PATCH — частичное обновление
- DELETE — удаление данных
- Что нужно знать перед началом
- Основная часть
- GET — получение данных
- POST — создание данных
- PUT — полное обновление
- PATCH — частичное обновление
- DELETE — удаление данных
- Таблица методов
- Полный пример
- Статус-коды для каждого метода
- Задачи для закрепления
- Нюансы и подводные камни
- Частые ошибки и как их избежать
- Ошибка 1: PUT для частичного обновления
- Ошибка 2: POST для идемпотентных операций
- Ошибка 3: GET для изменения данных
- Шпаргалка
- Заключение
- КВИЗ
- Что дальше?
Что нужно знать перед началом
Для этого урока тебе понадобится:
- Базовое понимание HTTP
- Установленный FastAPI
Совет: Правильное использование методов HTTP делает API интуитивно понятным.
Основная часть
GET — получение данных
GET используется для получения данных. Он не должен изменять состояние сервера.
from fastapi import FastAPI
app = FastAPI()
# Список всех пользователей
@app.get("/users")
def get_users():
return {"users": [{"id": 1, "name": "Анна"}, {"id": 2, "name": "Иван"}]}
# Получение одного пользователя
@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"id": user_id, "name": f"Пользователь {user_id}"}Особенности GET:
- Не изменяет данные
- Можно кешировать
- Параметры передаются в URL
POST — создание данных
POST используется для создания новых ресурсов.
from fastapi import FastAPI, HTTPException
app = FastAPI()
# Заглушка БД
users_db = {}
next_id = 1
@app.post("/users")
def create_user(name: str):
global next_id
user = {"id": next_id, "name": name}
users_db[next_id] = user
next_id += 1
return {"message": "Пользователь создан", "user": user}Особенности POST:
- Создаёт новый ресурс
- Не идемпотентен (повторный запрос создаёт новый ресурс)
- Данные передаются в теле запроса
PUT — полное обновление
PUT используется для полного обновления ресурса. Заменяет весь объект.
@app.put("/users/{user_id}")
def update_user(user_id: int, name: str):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="Пользователь не найден")
user = {"id": user_id, "name": name}
users_db[user_id] = user
return {"message": "Пользователь обновлён", "user": user}Особенности PUT:
- Полное обновление ресурса
- Идемпотентен (повторный запрос даёт тот же результат)
- Если ресурса нет — можно создать (не рекомендуется)
PATCH — частичное обновление
PATCH используется для частичного обновления ресурса. Изменяет только указанные поля.
from fastapi import FastAPI, HTTPException
app = FastAPI()
# Заглушка БД
users_db = {
1: {"id": 1, "name": "Анна", "age": 25},
2: {"id": 2, "name": "Иван", "age": 30}
}
@app.patch("/users/{user_id}")
def patch_user(user_id: int, name: str = None, age: int = None):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="Пользователь не найден")
user = users_db[user_id]
if name is not None:
user["name"] = name
if age is not None:
user["age"] = age
return {"message": "Пользователь обновлён", "user": user}Особенности PATCH:
- Частичное обновление
- Не обязательно идемпотентен
- Экономит трафик
DELETE — удаление данных
DELETE используется для удаления ресурсов.
@app.delete("/users/{user_id}")
def delete_user(user_id: int):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="Пользователь не найден")
deleted_user = users_db.pop(user_id)
return {"message": "Пользователь удалён", "deleted": deleted_user}Особенности DELETE:
- Удаляет ресурс
- Идемпотентен (повторный запрос возвращает 404)
- Обычно возвращает 204 No Content или 200 OK
Таблица методов
| Метод | Назначение | Идемпотентен | Тело запроса |
|---|---|---|---|
| GET | Получение | Да | Нет |
| POST | Создание | Нет | Да |
| PUT | Полное обновление | Да | Да |
| PATCH | Частичное обновление | Нет | Да |
| DELETE | Удаление | Да | Нет |
Совет: Идемпотентность означает, что повторный запрос не изменяет состояние сервера.
Полный пример
from fastapi import FastAPI, HTTPException
app = FastAPI()
# Заглушка БД
users_db = {
1: {"id": 1, "name": "Анна", "age": 25},
2: {"id": 2, "name": "Иван", "age": 30}
}
next_id = 3
# GET — получить всех пользователей
@app.get("/users")
def get_users():
return {"users": list(users_db.values())}
# GET — получить одного пользователя
@app.get("/users/{user_id}")
def get_user(user_id: int):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="Пользователь не найден")
return users_db[user_id]
# POST — создать пользователя
@app.post("/users")
def create_user(name: str, age: int):
global next_id
user = {"id": next_id, "name": name, "age": age}
users_db[next_id] = user
next_id += 1
return {"message": "Пользователь создан", "user": user}
# PUT — полное обновление
@app.put("/users/{user_id}")
def update_user(user_id: int, name: str, age: int):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="Пользователь не найден")
user = {"id": user_id, "name": name, "age": age}
users_db[user_id] = user
return {"message": "Пользователь обновлён", "user": user}
# PATCH — частичное обновление
@app.patch("/users/{user_id}")
def patch_user(user_id: int, name: str = None, age: int = None):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="Пользователь не найден")
user = users_db[user_id]
if name is not None:
user["name"] = name
if age is not None:
user["age"] = age
return {"message": "Пользователь обновлён", "user": user}
# DELETE — удаление пользователя
@app.delete("/users/{user_id}")
def delete_user(user_id: int):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="Пользователь не найден")
deleted = users_db.pop(user_id)
return {"message": "Пользователь удалён", "deleted": deleted}Статус-коды для каждого метода
| Метод | Успех | Ошибка |
|---|---|---|
| GET | 200 OK | 404 Not Found |
| POST | 201 Created | 400 Bad Request |
| PUT | 200 OK | 404 Not Found |
| PATCH | 200 OK | 404 Not Found |
| DELETE | 200 OK / 204 No Content | 404 Not Found |
Задачи для закрепления
Задача 1. Создай эндпоинт GET для получения списка товаров.
Задача 2. Создай эндпоинт POST для создания товара.
Задача 3. Создай эндпоинт PUT для обновления товара.
Задача 4. Создай эндпоинт DELETE для удаления товара.
Задача 5. Чем отличается PUT от PATCH?
Ответы:
Задача 1.
@app.get("/products")
def get_products():
return {"products": []}Задача 2.
@app.post("/products")
def create_product(name: str):
return {"message": "Товар создан"}Задача 3.
@app.put("/products/{product_id}")
def update_product(product_id: int, name: str):
return {"message": f"Товар {product_id} обновлён"}Задача 4.
@app.delete("/products/{product_id}")
def delete_product(product_id: int):
return {"message": f"Товар {product_id} удалён"}Задача 5.
# PUT — полное обновление
# PATCH — частичное обновлениеНюансы и подводные камни
- GET — не должен изменять состояние сервера (идемпотентен).
- POST — не идемпотентен. Повторный запрос создаёт новый ресурс.
- PUT — идемпотентен. Повторный запрос не изменяет состояние.
- PATCH — не обязательно идемпотентен.
- DELETE — идемпотентен. Повторный запрос возвращает 404.
- PUT заменяет весь ресурс, PATCH — только указанные поля.
- В FastAPI методы указываются в декораторе:
@app.get(),@app.post(),@app.put(),@app.patch(),@app.delete().
Частые ошибки и как их избежать
Ошибка 1: PUT для частичного обновления
Используй PUT только для полной замены ресурса.
Ошибка 2: POST для идемпотентных операций
Используй PUT или PATCH для обновлений.
Ошибка 3: GET для изменения данных
GET должен быть безопасным и идемпотентным.
Шпаргалка
| Метод | Как пишется в FastAPI |
|---|---|
| GET | @app.get("/path") |
| POST | @app.post("/path") |
| PUT | @app.put("/path") |
| PATCH | @app.patch("/path") |
| DELETE | @app.delete("/path") |
Заключение
Сегодня мы:
- Изучили методы HTTP
- Разобрали GET, POST, PUT, PATCH, DELETE
- Узнали про идемпотентность
- Примеры с FastAPI








