82 lines
3.2 KiB
Python
82 lines
3.2 KiB
Python
# 2026-03-09
|
||
# notes_crud.py — CRUD роутер для таблицы notes.
|
||
#
|
||
# Назначение: единая функция, которая обрабатывает все операции с записями.
|
||
# Роутинг осуществляется по sub-path URL (event._path), который runtime
|
||
# берёт из входящего HTTP-запроса и добавляет в event автоматически.
|
||
#
|
||
# Доступные маршруты (все POST):
|
||
# /fn/default/notes/add?title=...&body=... → создать запись
|
||
# /fn/default/notes/update?id=1&title=...&body=... → обновить запись
|
||
# /fn/default/notes/delete?id=1 → удалить запись
|
||
#
|
||
# Параметры берутся из query string (event._query) или из тела запроса (event).
|
||
# event._path и event._query добавляет Python runtime (server.py) автоматически.
|
||
import os
|
||
import psycopg2
|
||
import psycopg2.extras
|
||
|
||
|
||
def crud(event):
|
||
dsn = os.environ['PG_DSN']
|
||
# sub-path без ведущего слэша: "add", "update", "delete"
|
||
action = event.get('_path', '/').strip('/')
|
||
q = event.get('_query', {})
|
||
|
||
conn = psycopg2.connect(dsn)
|
||
try:
|
||
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
||
|
||
if action == 'add':
|
||
title = q.get('title') or event.get('title', '')
|
||
body = q.get('body') or event.get('body', '')
|
||
if not title:
|
||
return {'error': 'title is required'}
|
||
cur.execute(
|
||
"INSERT INTO notes (title, body) VALUES (%s, %s)"
|
||
" RETURNING id, title, body, created_at::text",
|
||
(title, body)
|
||
)
|
||
row = cur.fetchone()
|
||
conn.commit()
|
||
return dict(row)
|
||
|
||
elif action == 'update':
|
||
id_ = q.get('id') or event.get('id')
|
||
if not id_:
|
||
return {'error': 'id is required'}
|
||
title = q.get('title') or event.get('title', '')
|
||
body = q.get('body') or event.get('body', '')
|
||
cur.execute(
|
||
"UPDATE notes SET title=%s, body=%s WHERE id=%s"
|
||
" RETURNING id, title, body, created_at::text",
|
||
(title, body, int(id_))
|
||
)
|
||
row = cur.fetchone()
|
||
conn.commit()
|
||
return dict(row) if row else {'error': 'not found'}
|
||
|
||
elif action == 'delete':
|
||
id_ = q.get('id') or event.get('id')
|
||
if not id_:
|
||
return {'error': 'id is required'}
|
||
cur.execute(
|
||
"DELETE FROM notes WHERE id=%s RETURNING id",
|
||
(int(id_),)
|
||
)
|
||
row = cur.fetchone()
|
||
conn.commit()
|
||
return {'deleted': row['id']} if row else {'error': 'not found'}
|
||
|
||
else:
|
||
return {
|
||
'error': f'unknown action: /{action}',
|
||
'hint': 'use /add?title=...&body=..., /update?id=X&title=...&body=..., /delete?id=X'
|
||
}
|
||
|
||
except Exception as e:
|
||
conn.rollback()
|
||
return {'error': str(e)}
|
||
finally:
|
||
conn.close()
|