Как одним HTTP POST-запросом создать или обновить несколько разнотипных ресурсов

Ответ

Да, POST — это наиболее гибкий и подходящий метод для выполнения пакетных (batch) операций, таких как создание или обновление нескольких ресурсов разных типов за один запрос.

Принцип работы: В теле POST-запроса передается структурированный документ (обычно JSON), содержащий массив или объект с данными для каждого ресурса. Сервер обрабатывает эту структуру и выполняет соответствующие операции.

Пример на FastAPI:

Серверная часть, принимающая данные о пользователе и продукте одновременно.

from fastapi import FastAPI
from pydantic import BaseModel
from typing import List

app = FastAPI()

class UserUpdate(BaseModel):
    id: int
    name: str

class ProductUpdate(BaseModel):
    sku: str
    stock: int

class BatchUpdateRequest(BaseModel):
    users: List[UserUpdate]
    products: List[ProductUpdate]

@app.post("/batch-update")
async def batch_update(data: BatchUpdateRequest):
    # Здесь логика обновления пользователей и продуктов в БД
    print(f"Updating {len(data.users)} users...")
    print(f"Updating {len(data.products)} products...")
    return {"status": "success", "updated_items": data.dict()}

Пример тела JSON-запроса:

{
  "users": [
    { "id": 1, "name": "Alice" },
    { "id": 2, "name": "Bob" }
  ],
  "products": [
    { "sku": "TSHIRT-RED-L", "stock": 99 }
  ]
}

Ключевые аспекты:

  • Гибкость: POST не привязан к семантике полного или частичного обновления и идеально подходит для сложных бизнес-операций.
  • Неидемпотентность: Повторная отправка POST-запроса может привести к созданию дубликатов или повторному выполнению операции. Это ожидаемое поведение.
  • URL: Запрос обычно отправляется на специальный эндпоинт, отражающий суть операции (например, /api/batch-update или /api/transactions).

Ответ 18+ 🔞

А, ну вот, смотри, классическая ситуация! Ты хочешь одним махом, одним запросом, нахуярить на сервер кучу всего разного — пользователей там, товары, чёрта лысого. И правильно думаешь, что POST — это твой верный пёс в этом деле.

Потому что POST, он как раз для таких нестандартных, комплексных операций и создан. Не для того, чтобы просто страничку получить (GET), а чтобы отправить пакет данных и сказать: «На, сервак, разберись с этим дерьмом, сделай что надо».

Как это работает, если по-простому: Ты в теле запроса, обычно в JSON'е, пакуешь всю свою хуйню — массив пользователей, массив товаров, что угодно. Сервер этот пакет распаковывает и начинает по списку всё обрабатывать. Один запрос — куча действий. Удобно, ёпта!

Вот тебе живой пример на FastAPI, смотри:

from fastapi import FastAPI
from pydantic import BaseModel
from typing import List

app = FastAPI()

class UserUpdate(BaseModel):
    id: int
    name: str

class ProductUpdate(BaseModel):
    sku: str
    stock: int

class BatchUpdateRequest(BaseModel):
    users: List[UserUpdate]
    products: List[ProductUpdate]

@app.post("/batch-update")
async def batch_update(data: BatchUpdateRequest):
    # Здесь логика обновления пользователей и продуктов в БД
    print(f"Updating {len(data.users)} users...")
    print(f"Updating {len(data.products)} products...")
    return {"status": "success", "updated_items": data.dict()}

А вот как примерно будет выглядеть JSON, который ты этому ендпоинту впаришь:

{
  "users": [
    { "id": 1, "name": "Alice" },
    { "id": 2, "name": "Bob" }
  ],
  "products": [
    { "sku": "TSHIRT-RED-L", "stock": 99 }
  ]
}

Важные моменты, которые надо держать в голове, чтобы не обосраться:

  • Гибкость — овердохуища: POST не заточен под какое-то одно действие. Хочешь обновить, хочешь создать, хочешь смешать — всё можно запихнуть в одну операцию. Главное, чтобы серверную логику под это написать.
  • Неидемпотентность, ёбушки-воробушки: Это значит, что если ты два раза подряд шлёшь один и тот же POST-запрос, то операция может выполниться дважды. Пользователей создашь двух одинаковых, товары задвоишь. Это норма для POST, так и задумано. Если тебе такое не нужно — думай над логикой, ставь проверки на дубли.
  • URL — твоя песочница: Ты сам придумываешь адрес, куда это всё слать. Не /users или /products, а что-то вроде /api/batch-update или /api/transactions. Эндпоинт, который отражает суть твоей пакетной операции.

Вот и вся магия. Упаковал всё в один JSON, отправил POST'ом — и сидишь, ждёшь, пока сервер не отчитается, что всё сделал. Главное, чтобы на той стороне код был написан так, чтобы не словить пиздец, если что-то пойдёт не так в середине процесса.