М4. Web (+ Web Advanced)¶
Програми говорять мережею: спершу — як клієнт до чужих API, далі — власні сервери на Django і FastAPI.
Уроки модуля:
- Урок 32. HTTP: requests, httpx, aiohttp — шлях запиту: URL, IP і DNS, порти, TCP-рукостискання, TLS; HTTP як текст (запит сокетом), методи й статус-коди;
requests:params,json, заголовки й токен,raise_for_status, тайм-аути й ієрархія винятків, повторні спроби з backoff і чому не дляPOST,Session; справжній API PyPI;httpxіAsyncClient+gather,aiohttp, потоки; архітектура: свій клієнт до API з доменними винятками, вибір бібліотеки. Практика — на навчальному API диспетчерськоїsmachno_api.py. - Урок 33. REST: принципи дизайну API — метео-API викладача (телеграми SYNOP з ogimet.com,
pymetdecoder): усі типи API на одних даних — HTTP+CSV, JSON-RPC, GraphQL, SOAP, gRPC, WebSocket, SSE, webhook з підписом HMAC — і як обрати; REST: ресурси й URL, методи й ідемпотентність, статус-коди й формат помилок, фільтри,fields, пагінація,PATCH,202 Accepted, OpenAPI; кейс v1 → v2; архітектура: репозиторій → FastAPI → клієнт-клас → Streamlit-карта погоди, Docker Compose. - Урок 34. Django intro: MVT, ORM, admin — перший крок застосунку нотаток, що виросте до Notes Chat App викладача (кроки 1–2 маршруту Zero to Hero Django-книги):
startproject/startapp,settings.py, MVT і шлях запиту, view,path/include, модельNote,makemigrations/sqlmigrate/migrate, ORM (create,filter, lookups,get, лінивий QuerySet,.query,update,delete), шаблон, адмінка й суперкористувач; практика —is_pinned,priority, блокноти. - Урок 35. Django: forms, HTML practice — два рефакторинги проєкту уроку 34 на стартовому коді (кроки 2 і 4 Django-книги): голий HTML → Bootstrap CRUD (
ModelForm, PRG,messages,base.html, CSRF) і Bootstrap → crispy dashboard (3-рівневі шаблони,FormHelper+Layout, context processor); «Знайди помилку» —is_pinnedгубиться при створенні. - Урок 36. DRF overview + Django vs FastAPI — рефакторинг 3 проєкту уроку 35: REST API поруч зі сторінками поверх тих самих services/selectors (код з Django-книги):
REST_FRAMEWORK, вхідний і вихідний серіалізатори,ViewSet+DefaultRouter,@actionpin,IsAuthenticatedі чому403, IDOR →404,PATCHзpartial=True, browsable API, OpenAPI (drf-spectacular +extend_schema), тести; той самий API на FastAPI і як обрати; «Знайди помилку» —auto_nowне оновлюється зupdate_fields. - Урок 37. Typing + Pydantic — крок 1 новинного агрегатора (FastAPI-гілка): стартовий парсер
parse_rbc_newsз анотаціями типів (list[RawNews],TypedDict,X | None,Literal),mypyі--strict, модельNewsItemна Pydantic (Field,field_validator,model_validator(mode="before"),frozen), перевірка знімка 168 справжніх новин rbc.ua,validate_newsбез мовчазних втрат, JSON Schema,TypeAdapter; «Знайди помилку» — URL, розібраний рядком. - Урок 38. FastAPI basics + Postman + OpenAPI — крок 2 агрегатора: FastAPI над
NewsItemз прототипуnews_dashboard— маршрути,QueryіLiteral,422,response_model; сховище черезDependsіlifespan, підміна залежностей у тестах;POST /api/scrape(aiohttp,gather, знімок, захист від SSRF);/docsі/openapi.json; колекція Postman з перевірками і newman; виміриfastapi_demo:async def+time.sleep— 20 запитів за 40 с,defіawait— за 2 с (і як тест навантаження вимірював сам себе). Довідник: FastAPI — архітектура і async. - Урок 39. FastAPI + SQLAlchemy: повний CRUD — крок 3 агрегатора:
NewsStore→ PostgreSQL/SQLite на шарі бази стартовогоproduction_bot— async-engine і сесія на запит (get_db),NewsRow(Mapped),NewsRepositoryз тим самим інтерфейсом, SQL, який генерує SQLAlchemy,INSERT … ON CONFLICT DO NOTHINGпокроково (і чому id «перескакують»); повний CRUD201/404/409/204, пошук; Alembic-міграції; з FastAPI 0.118 COMMIT уyield-залежності йде після відповіді →scope="function"; «Знайди помилку» — гонка «перевір, потім встав». - Урок 40. Middlewares і кешування (Redis на практиці) — крок 4 агрегатора: HTTP-middleware (
X-Request-ID,X-Process-Time, порядок шарів покроково); кешGET /api/newsі/statsу Redis (cache-aside, версія кешу, інвалідація після COMMIT); rate limit зі стартовогоai_bot—429іRetry-After, атомарніINCR+EXPIRE NXзамість «ключ без TTL блокує назавжди», межа фіксованого вікна виміряна; фоновий збір202+ статус у Redis з polling; «Знайди помилку» — сесія запиту у фоновій задачі: «збережено 168», а в базі 0. - Урок 41. Автентифікація та security basics (JWT, hashing, OWASP) — рефакторинг 4 застосунку нотаток на стартовому коді автентифікації: нотатки групи (
Q(user) | Q(group__in=…), читати — учасникам, змінювати — автору), перевірка автора в API →403; паролі — PBKDF2 з сіллю, скидання листом без розкриття акаунтів; JWT наsimplejwt(header.payload.signature покроково, підправлений / чужий / прострочений токен →401, refresh з ротацією, порядок автентифікаторів DRF:401чи403), throttle/api/token/;check --deploy; OWASP Top 10 на нашому коді; «Знайди помилку» —SECRET_KEYу публічному репозиторії. - Урок 42. Тестування API (pytest + httpx) — рефакторинг 5 агрегатора новин: переробляємо лише тести уроку 40. Шари unit / integration з маркерами; збережені сторінки rbc.ua як фікстури й тест конвеєра «парсер → модель»; мок мережі й «patch where used» (покрокова діаграма); фейковий HTTP-сервер (
aiohttpTestServer) і межа фейку (fakeredis не показує гонок);httpx.AsyncClient+ASGITransportдля одночасних запитів; покриття гілок зconcurrency = greenlet; прогін на мінімальних версіях залежностей. Тести ловлять 4 помилки: ISO-час, битий байт UTF-8,fakerbc.ua, beautifulsoup4 4.12. «Знайди помилку» — два зелені тести, які разом пропустили помилку контракту. - Урок 43. AI-інструменти розробника + ризики й валідація — рефакторинг 6 агрегатора новин і рецензія AI-проєкту.
news_hubотримуєCLAUDE.md(замість застарілого прикладу з довідника),.claude/settings.json(allow / ask / deny), hookpytest -m unitпісля кожної правки і skill/add-news-source. Експеримент: Claude Code двічі додає RSS «Української правди» — з голим запитом (101 зелений власний тест, але час у GMT, тиха відмова на битому XML і вигадана фікстура) і за специфікацією з тестів (2 файли, тести не змінено); рецензія знаходить ще 3 випадки поза специфікацією.allowз репозиторію не діє без довіри до папки. Кейсdepression_dashboard(Flask + Streamlit + scikit-learn, згенерований AI): 17 тестів рецензії доводять 10 вад, зокрема алфавітний порядок «топ-ознак» черезjsonify, вигадані назви кластерів, підробні похідні ознаки в/api/predict, витік даних, незахищений/api/train. Довідник Claude Code — звірений з документацією. - Урок 44. Інтеграція LLM API (Gemini / Anthropic) — рефакторинг 7 агрегатора новин: тема, тональність, підсумок і ключові слова від LLM замість правил
nlp.py(у знімку всі 168 новин — категорія «Новини»). стартовийai_service.py→llm.py: один інтерфейсLLMClientдля Gemini (асинхроннийclient.aio, пул моделей: 404/429/5xx — наступна, 400/401/403 — стоп) і Anthropic,FakeLLMдля тестів; відповідь — JSON за схемою й перевірка Pydantic з одним повтором; промпт-ін'єкція (дані в<news>, схема з переліками); circuit breaker наINCR+EXPIRE NX→503+Retry-After(справжній запуск з невалідним ключем); база → кеш за хешем тексту → модель, токени й вартість, пакетний аналіз у фоні. «Знайди помилку» — схема зextra="forbid", яку Gemini відхиляє400, хоча всі тести з фейком зелені; контрактний тест без ключа. - Урок 45. Архітектура застосунків і патерни — рефакторинг 5 застосунку нотаток (крок 3 Django-книги) і каталог патернів обох проєктів. Правило «хто що бачить» жило у views і selectors кількома копіями, які розійшлися: список, поділений з двома, падав з
500(MultipleObjectsReturnedчерез M2M + OR), список групи був у переліку, але відкривався з404. Теперselectors.*_visible_to/*_owned_byповертають QuerySet — одне правило для сторінок, CBV і API; тест наastстежить, щоб уviews.pyіapi.pyне було ORM. Нотатки, записники й теги — class-based views зі стартовогоnotes_project_cbv(LoginRequiredMixin→OwnerRequiredMixinпо MRO, чому нічого з базою вsetup()); відкритий редирект?next=закрито. PostgreSQL черезDATABASE_URL(SQLite без змінної), 49 тестів на обох базах, кількість SQL-запитів як контракт (безselect_related— 97 замість 8). Каталог: Service layer, CQRS-light, Repository, DI, Strategy (LLMClient), Decorator (GuardedLLM), Factory (make_llm), Template method, Unit of Work — на коді нотаток іnews_hub; коли патерн зайвий; «куди класти код». - Урок 46. WebSockets + практика: чат — рефакторинг 6 застосунку нотаток (крок 7B Django-книги): груповий чат зі стартового коду — Django Channels, ASGI (
ProtocolTypeRouter, daphne), consumer, channel layer (у пам'яті або Redis заREDIS_URL), JS-клієнт. Consumer — ще один транспорт над тими самими selectors і services: членство —selectors.is_group_member, запис —services.post_chat_message(межі тексту й права — на кожне повідомлення). Вилучили з групи або групу видалили → подія після COMMIT закриває відкрите з'єднання кодом4403;AllowedHostsOriginValidator— захист від Cross-Site WebSocket Hijacking; JS не перепідключається після відмови. Тести —WebsocketCommunicator+TransactionTestCase, 76 на SQLite + InMemory і PostgreSQL + Redis; ноутбук — чат з кількома «браузерами» без сервера. - Урок 47. Security advanced — рефакторинг 8 агрегатора
news_hub: у проєкті уроку 44 будь-хто міг стерти базу (DELETE /api/news) і запустити платний аналіз. Адмін-JWT зі стартовогоproduction_bot: пароль — bcrypt-хеш у env (безpasslib, який не працює з bcrypt 5), без секретів «change-me» (не налаштовано → 503, короткий секрет → не стартує), HS256 і обов'язковіexp/sub/role, ліміт спроб входу; тест обходить усі маршрути й порівнює незахищені з перелікомPUBLIC. SSRF: RSS-джерела адміна завантажуєsafe_fetch— IP перевіряє resolver з'єднання (після DNS), кожне перенаправлення знову, порти, розмір, тип; старий захист allowlist-ом обходиться одним302. Підписані webhook: HMAC(час + сирі байти тіла), вікно 5 хв,SET NXпроти повтору,compare_digest, секрет не в URL. 279 тестів на SQLite і PostgreSQL + Redis; ноутбук — підробка токенів, SSRF на локальних серверах, повтор webhook. - Урок 48. Telegram Bot API — рефакторинг 9 агрегатора
news_hub: Telegram-бот на aiogram 3 зі стартовихai_botіecho_bot—/news,/digest(аналіз LLM),/subscribe <слово>і сповіщення про нові новини після кожного збору, адмінська/scrapeзаuser_id. Бот — ще один вхід у той самий застосунок: ті самі репозиторії,analyze_news, rate limit на Redis; сесія бази на кожен update (inner middleware), роутер — новий на кожен диспетчер. Відповіді в HTML: усе ззовні екранується (ім'я «Tom & Jerry» у стартовому коді — бот мовчить), довгий текст ділиться між рядками, а не кожні 4000 символів. Сповіщення: лише нові новини (RETURNING), 403 → підписки видаляються, 429 →retry_after. Webhook у FastAPI з секретом у заголовку (verify_secret_tokenуроку 47), polling —python -m news_hub.bot. Тести й ноутбук — на двійнику Telegram Bot API, без токена й мережі.
Решта уроків — 🚧 у розробці.
Django-книга викладача. Уроки М4 про Django ведуть по маршруту Zero to Hero Django-книги: урок 34 — кроки 1–2, 34 — кроки 2 і 4, 35 — API до нотаток, 38 і 44 — крок 3, 40 — крок 5, 41 — крок 6, 45 — крок 7, 48–49 — кроки 8–9. Стартовий код — готові проєкти, кожен урок — рефакторинг проєкту попереднього (що змінилося, діфи, архітектура до/після); сторінки курсу — стислий урок із практикою, книга — поглиблення (посилання «Поглиблено» в кожному розділі).
17 уроків (лекції #31–47 у навігаційній таблиці v5.0): HTTP/REST → Django intro → DRF/FastAPI → повний CRUD → middlewares/кешування → auth/security basics → тестування API (лекції #31–41, «Web»), потім AI-інструменти розробника, інтеграція LLM API, архітектура застосунків, WebSockets, security advanced, Telegram Bot API (лекції #42–47, «Web Advanced»).
«Web Advanced» — це продовження М4, не окремий модуль: обидва блоки йдуть під одним наскрізним номером уроку, а модулі М5/М6 зберігають свої номери одразу після «Web Advanced» без зсуву.