mirror of
https://github.com/kennethreitz/responder.git
synced 2026-06-05 23:00:17 +00:00
a3b49ab9fd
New documentation pages: - Authentication: API keys, JWT tokens, session auth, custom exceptions - WebSocket Tutorial: echo server, chat room, HTML client, data formats - Writing Middleware: hooks vs middleware, Starlette integration, ordering - Configuration: env vars, .env files, secret keys, debug mode, production setup Also: - Complete working example at end of quickstart with cross-references - Three new example files: rest_api.py, websocket_chat.py, sse_stream.py - Changelog updated for v3.2.0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
71 lines
1.5 KiB
Python
71 lines
1.5 KiB
Python
# Complete REST API example with Pydantic validation.
|
|
# https://responder.kennethreitz.org/tutorial-rest.html
|
|
import responder
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class BookIn(BaseModel):
|
|
title: str
|
|
author: str
|
|
year: int
|
|
isbn: str | None = None
|
|
|
|
|
|
class BookOut(BaseModel):
|
|
id: int
|
|
title: str
|
|
author: str
|
|
year: int
|
|
isbn: str | None = None
|
|
|
|
|
|
api = responder.API(
|
|
title="Book Catalog",
|
|
version="1.0",
|
|
openapi="3.0.2",
|
|
docs_route="/docs",
|
|
)
|
|
|
|
books_db: dict[int, dict] = {}
|
|
next_id = 1
|
|
|
|
|
|
@api.route("/books", methods=["GET"])
|
|
def list_books(req, resp):
|
|
resp.media = list(books_db.values())
|
|
|
|
|
|
@api.route("/books", methods=["POST"], check_existing=False,
|
|
request_model=BookIn, response_model=BookOut)
|
|
async def create_book(req, resp):
|
|
global next_id
|
|
data = await req.media()
|
|
book = {"id": next_id, **data}
|
|
books_db[next_id] = book
|
|
next_id += 1
|
|
resp.media = book
|
|
resp.status_code = 201
|
|
|
|
|
|
@api.route("/books/{book_id:int}", methods=["GET"])
|
|
def get_book(req, resp, *, book_id):
|
|
if book_id not in books_db:
|
|
resp.status_code = 404
|
|
resp.media = {"error": f"Book {book_id} not found"}
|
|
return
|
|
resp.media = books_db[book_id]
|
|
|
|
|
|
@api.route("/books/{book_id:int}", methods=["DELETE"], check_existing=False)
|
|
def delete_book(req, resp, *, book_id):
|
|
if book_id not in books_db:
|
|
resp.status_code = 404
|
|
resp.media = {"error": f"Book {book_id} not found"}
|
|
return
|
|
del books_db[book_id]
|
|
resp.status_code = 204
|
|
|
|
|
|
if __name__ == "__main__":
|
|
api.run()
|