← Назад к вопросам
Какие типы ответов можно возвращать в FastAPI?
2.3 Middle🔥 251 комментариев
#FastAPI и Flask
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Типы ответов в FastAPI
FastAPI предоставляет гибкую систему для возврата разных типов ответов. Расскажу о каждом.
1. Базовый тип (dict, list)
Автоматически преобразуется в JSON:
from fastapi import FastAPI
app = FastAPI()
@app.get("/users")
def get_users():
return {
"status": "ok",
"users": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]
}
# Response: {"status": "ok", "users": [{"id": 1, "name": "Alice"}, ...]}
2. Pydantic модели (рекомендуется)
Основной способ с типизацией и валидацией:
from pydantic import BaseModel
from typing import Optional
from datetime import datetime
class User(BaseModel):
id: int
name: str
email: str
age: Optional[int] = None
created_at: datetime
class PaginatedUsers(BaseModel):
total: int
page: int
users: list[User]
@app.get("/users", response_model=PaginatedUsers)
def get_users(page: int = 1):
return PaginatedUsers(
total=100,
page=page,
users=[
User(id=1, name="Alice", email="alice@mail.com", created_at=datetime.now())
]
)
# Автоматическая валидация, документация Swagger
3. Список моделей
Возвращаем массив объектов:
class UserResponse(BaseModel):
id: int
name: str
email: str
@app.get("/users", response_model=list[UserResponse])
def list_users():
return [
UserResponse(id=1, name="Alice", email="alice@mail.com"),
UserResponse(id=2, name="Bob", email="bob@mail.com"),
]
4. JSON Response
Для явного контроля:
from fastapi.responses import JSONResponse
@app.get("/users/{user_id}")
def get_user(user_id: int):
if user_id < 0:
return JSONResponse(
status_code=400,
content={"detail": "Invalid user_id"}
)
return JSONResponse(
status_code=200,
content={"id": user_id, "name": "Alice"}
)
5. HTMLResponse
Возвращение HTML:
from fastapi.responses import HTMLResponse
@app.get("/", response_class=HTMLResponse)
def get_html():
return """
<html>
<body>
<h1>Welcome to API</h1>
</body>
</html>
"""
6. FileResponse
Отправка файлов:
from fastapi.responses import FileResponse
from pathlib import Path
@app.get("/download")
def download_file():
file_path = Path("./documents/report.pdf")
return FileResponse(
path=file_path,
media_type='application/pdf',
filename="report.pdf"
)
# Или с streaming для больших файлов
@app.get("/download-large")
def download_large():
return FileResponse(
path="./videos/movie.mp4",
media_type='video/mp4',
filename="movie.mp4"
)
7. StreamingResponse
Для потока данных (видео, большие файлы):
import asyncio
from fastapi.responses import StreamingResponse
async def generate_data():
for i in range(10):
await asyncio.sleep(0.1)
yield f"data: chunk {i}\n".encode()
@app.get("/stream")
async def stream_data():
return StreamingResponse(
generate_data(),
media_type="text/event-stream"
)
8. PlainTextResponse
Обычный текст:
from fastapi.responses import PlainTextResponse
@app.get("/text", response_class=PlainTextResponse)
def get_text():
return "Hello, World!"
9. RedirectResponse
Перенаправление:
from fastapi.responses import RedirectResponse
@app.get("/old-path")
def redirect_to_new():
return RedirectResponse(url="/new-path", status_code=301)
10. Custom Response
Пользовательский ответ с заголовками:
from fastapi.responses import JSONResponse
@app.get("/custom")
def custom_response():
return JSONResponse(
status_code=200,
content={"message": "Success"},
headers={
"X-Custom-Header": "custom-value",
"Cache-Control": "no-cache"
}
)
11. Union типы (несколько возможных ответов)
from typing import Union
class SuccessResponse(BaseModel):
id: int
name: str
class ErrorResponse(BaseModel):
detail: str
code: int
@app.get("/users/{user_id}", response_model=Union[SuccessResponse, ErrorResponse])
def get_user(user_id: int):
if user_id < 1:
return ErrorResponse(detail="Invalid ID", code=400)
return SuccessResponse(id=user_id, name="Alice")
12. Асинхронные ответы
from fastapi import BackgroundTasks
class ReportResponse(BaseModel):
report_id: str
status: str
@app.post("/generate-report")
async def generate_report(background_tasks: BackgroundTasks):
report_id = "report_123"
# Отправить ответ сразу
background_tasks.add_task(slow_report_generation, report_id)
return ReportResponse(
report_id=report_id,
status="processing"
)
async def slow_report_generation(report_id: str):
# Это выполнится в фоне
await asyncio.sleep(5)
print(f"Report {report_id} generated")
13. Множество моделей ответов
from fastapi import status
class User(BaseModel):
id: int
name: str
class ErrorDetail(BaseModel):
detail: str
@app.get(
"/users/{user_id}",
response_model=User,
responses={
200: {"description": "User found"},
404: {"model": ErrorDetail, "description": "User not found"},
500: {"model": ErrorDetail, "description": "Internal error"},
}
)
def get_user(user_id: int):
if user_id < 1:
return JSONResponse(
status_code=404,
content={"detail": "User not found"}
)
return User(id=user_id, name="Alice")
14. Кастомные заголовки ответов
from fastapi import Response
@app.get("/custom-headers")
def custom_headers(response: Response):
response.headers["X-Token"] = "secret-token"
response.headers["Cache-Control"] = "max-age=3600"
return {"message": "OK"}
15. Cookies в ответе
@app.get("/login")
def login(response: Response):
response.set_cookie(
key="session_id",
value="abc123xyz",
max_age=3600,
secure=True,
httponly=True
)
return {"status": "logged in"}
16. Status codes
from fastapi import status
@app.post("/users", status_code=status.HTTP_201_CREATED)
def create_user(user: User):
# Автоматически вернёт 201
return user
@app.delete("/users/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_user(user_id: int):
# 204 No Content
return None
Рекомендуемые практики
# ✅ ХОРОШО — используй Pydantic модели
from pydantic import BaseModel
class UserResponse(BaseModel):
id: int
name: str
email: str
@app.get("/users/{user_id}", response_model=UserResponse)
def get_user(user_id: int):
return UserResponse(id=user_id, name="Alice", email="alice@mail.com")
# ✅ ХОРОШО — обработка ошибок
from fastapi import HTTPException
@app.get("/users/{user_id}")
def get_user_safe(user_id: int):
if user_id < 1:
raise HTTPException(status_code=404, detail="User not found")
return UserResponse(id=user_id, name="Alice", email="alice@mail.com")
# ✅ ХОРОШО — документация в Swagger
class CreateUserRequest(BaseModel):
name: str
email: str
@app.post("/users", response_model=UserResponse)
def create_user(user: CreateUserRequest):
"""Создаёт нового пользователя."""
return UserResponse(id=1, name=user.name, email=user.email)
# ❌ ПЛОХО — raw dict без типизации
@app.get("/users")
def get_users():
return {"id": 1, "name": "Alice"} # Нет валидации
Чеклист для ответов
- Используй response_model — автоматическая валидация
- Явно задай status_code — 201 для создания, 204 для удаления
- Документируй responses — для Swagger
- Обрабатывай ошибки через HTTPException — красивые ошибки
- Добавляй заголовки для кэширования — если нужно
- Используй Union для множественных типов ответов
- Streaming для больших файлов — не грузи всё в память
- Background tasks — для долгих операций
FastAPI автоматически сериализует Pydantic модели в JSON и генерирует OpenAPI документацию. Это главное его преимущество перед Flask.