From e5fce97e8eae7331d7f6801b89ffacbddc70eb8a Mon Sep 17 00:00:00 2001 From: Repinoid Date: Thu, 1 Oct 2026 18:37:26 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20created=5Fat/created=5Fby=20=E2=80=94?= =?UTF-8?q?=20=D0=B2=D0=B8=D0=B4=D0=BD=D0=BE=20=D0=B2=D1=80=D0=B5=D0=BC?= =?UTF-8?q?=D1=8F=20=D0=B8=20=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81,=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=B2=D1=88=D0=B8=D0=B9=20?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=BA=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CREATE TABLE IF NOT EXISTS дополнена колонками: created_at TIMESTAMPTZ NOT NULL DEFAULT now() created_by TEXT NOT NULL DEFAULT '' - ALTER TABLE ... ADD COLUMN IF NOT EXISTS досыпает колонки в уже существующую таблицу — данные при этом не теряются; - INSERT пишет created_by из env SERVICE_NAME (задаётся в json_env манифеста), created_at ставит сама СУБД; - список записей и UI показывают обе колонки. Зачем: три приложения (flask / lucee / nodejs) пишут в ОДНУ таблицу — теперь сразу видно, какое из них и когда добавило строку. --- site/app.py | 37 ++++++++-- site/templates/index.html | 150 ++++++++++++++++++++------------------ 2 files changed, 108 insertions(+), 79 deletions(-) diff --git a/site/app.py b/site/app.py index 1c6aed9..d34c7e5 100644 --- a/site/app.py +++ b/site/app.py @@ -15,6 +15,10 @@ from flask import Flask, render_template, request, redirect, url_for, g VERSION = "1.0.0" TABLE_NAME = os.environ.get("TABLE_NAME", "crud_items") +# SERVICE_NAME — какое приложение добавило строку (колонка created_by). +# Задаётся в json_env манифеста отдельно для каждого сервиса (flask / lucee / nodejs), +# чтобы три приложения, пишущие в ОДНУ таблицу, были различимы. +SERVICE_NAME = os.environ.get("SERVICE_NAME", "flask") app = Flask(__name__) @@ -34,17 +38,33 @@ def get_db(): def init_db(): - """CREATE TABLE IF NOT EXISTS — никогда не дропает существующую таблицу.""" + """Создать таблицу, если её нет, и досыпать новые колонки. + + Таблица выставочная — кроме id/value храним только две метки: + created_at — когда строка добавлена (ставит сама СУБД); + created_by — какое приложение её добавило (flask / lucee / nodejs). + + ALTER TABLE ... ADD COLUMN IF NOT EXISTS нужен, чтобы таблица, созданная + предыдущей версией приложения, получила новые колонки без потери данных. + """ db = get_db() cur = db.cursor() cur.execute( f""" CREATE TABLE IF NOT EXISTS {TABLE_NAME} ( - id SERIAL PRIMARY KEY, - value TEXT NOT NULL DEFAULT '' + id SERIAL PRIMARY KEY, + value TEXT NOT NULL DEFAULT '', + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + created_by TEXT NOT NULL DEFAULT '' ) """ ) + cur.execute( + f"ALTER TABLE {TABLE_NAME} ADD COLUMN IF NOT EXISTS created_at TIMESTAMPTZ NOT NULL DEFAULT now()" + ) + cur.execute( + f"ALTER TABLE {TABLE_NAME} ADD COLUMN IF NOT EXISTS created_by TEXT NOT NULL DEFAULT ''" + ) cur.close() @@ -65,9 +85,10 @@ def index(): action = request.form.get("action", "") if action == "create": + # created_at ставит СУБД (DEFAULT now()), created_by — имя этого сервиса cur.execute( - f"INSERT INTO {TABLE_NAME} (value) VALUES (%s)", - (request.form.get("value", ""),), + f"INSERT INTO {TABLE_NAME} (value, created_by) VALUES (%s, %s)", + (request.form.get("value", ""), SERVICE_NAME), ) elif action == "update": @@ -90,15 +111,15 @@ def index(): edit_id = request.args.get("edit") if edit_id: cur.execute( - f"SELECT id, value FROM {TABLE_NAME} WHERE id = %s", + f"SELECT id, value, created_at, created_by FROM {TABLE_NAME} WHERE id = %s", (int(edit_id),), ) row = cur.fetchone() if row: edit_row = dict(row) - # Список всех записей - cur.execute(f"SELECT id, value FROM {TABLE_NAME} ORDER BY id") + # Список всех записей — вместе с метками «когда» и «кем» добавлено + cur.execute(f"SELECT id, value, created_at, created_by FROM {TABLE_NAME} ORDER BY id") rows = cur.fetchall() cur.close() diff --git a/site/templates/index.html b/site/templates/index.html index a579c95..2ec7b02 100644 --- a/site/templates/index.html +++ b/site/templates/index.html @@ -20,89 +20,97 @@ ---> + CRUD Flask Example — {{ table_name }} + -
+
-
- Nubes -

CRUD Flask Example

-
+
+ Nubes +

CRUD Flask Example

+
-
-
Записи
-
- - - - - - - - - - - {% for row in rows %} - - - - - - - {% endfor %} - -
IDVALUE
{{ row.id }}{{ row.value }} - ✏️ - -
- - - -
-
- {% if not rows %} -
Нет записей. Создайте первую.
+
+
Записи
+
+ + + + + + + + + + + + + {% for row in rows %} + + + + + + + + + {% endfor %} + +
IDVALUEДОБАВЛЕНОКЕМ
{{ row.id }}{{ row.value }}{{ row.created_at.strftime('%d.%m.%Y %H:%M:%S') if row.created_at else '' }}{{ row.created_by }} + ✏️ + +
+ + + +
+
+ {% if not rows %} +
Нет записей. Создайте первую.
+ {% endif %} +
+
+ +
+ {% if edit_row %} +
Редактировать #{{ edit_row.id }}
+
+
+ + +
+ + + Отмена +
+
+
+ {% else %} +
Добавить
+
+
+ +
+ + +
+
+
{% endif %}
+
-
- {% if edit_row %} -
Редактировать #{{ edit_row.id }}
-
-
- - -
- - - Отмена -
-
-
- {% else %} -
Добавить
-
-
- -
- - -
-
-
- {% endif %} + - -
- - - + + \ No newline at end of file