inne bazy z opcjach

This commit is contained in:
Mateusz Gruszczyński
2025-07-23 09:30:27 +02:00
parent 48f1841649
commit 57a3866ec8
12 changed files with 170 additions and 17 deletions

View File

@@ -23,4 +23,14 @@ AUTH_COOKIE_MAX_AGE=86400
HEALTHCHECK_TOKEN=alamapsaikota123
# sesja zalogowanego usera (domyślnie 7 dni)
SESSION_TIMEOUT_MINUTES=10080
SESSION_TIMEOUT_MINUTES=10080
# Rodzaj bazy: sqlite, pgsql, mysql, firebird
DB_ENGINE=sqlite
# Wspólne zmienne (dla pgsql, mysql, firebird)
DB_HOST=db
DB_PORT=5432
DB_NAME=myapp
DB_USER=user
DB_PASSWORD=pass

26
_tools/db/migrate.txt Normal file
View File

@@ -0,0 +1,26 @@
Scenariusz migracji
Zatrzymaj obecny kontener:
docker-compose down
Ustaw w .env:
.env
DB_ENGINE=pgsql
DB_NAME=myapp
DB_USER=user
DB_PASSWORD=pass
Uruchom bazę i aplikację:
docker-compose --profile pgsql up -d
Wykonaj migrację danych:
bash _tools/db/migrate_to_new_db.sh pgsql
Sprawdź działanie aplikacji.

View File

@@ -0,0 +1,49 @@
import os
from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import sessionmaker
from config import Config
# Źródło: SQLite
sqlite_engine = create_engine("sqlite:///instance/shopping.db")
sqlite_meta = MetaData(bind=sqlite_engine)
sqlite_meta.reflect()
# Cel: PostgreSQL (czytany z .env przez Config)
pg_engine = create_engine(Config.SQLALCHEMY_DATABASE_URI)
pg_meta = MetaData(bind=pg_engine)
pg_meta.reflect()
# Sesje
SQLiteSession = sessionmaker(bind=sqlite_engine)
PGSession = sessionmaker(bind=pg_engine)
sqlite_session = SQLiteSession()
pg_session = PGSession()
def migrate_table(table_name):
print(f"Migruję tabelę: {table_name}")
source_table = sqlite_meta.tables.get(table_name)
target_table = pg_meta.tables.get(table_name)
if not source_table or not target_table:
print(f"Pominięto: {table_name} (brak w jednej z baz)")
return
rows = sqlite_session.execute(source_table.select()).fetchall()
if not rows:
print("Brak danych do migracji.")
return
insert_data = [dict(row._mapping) for row in rows]
with pg_engine.begin() as conn:
conn.execute(target_table.insert(), insert_data)
print(f"✅ Przeniesiono: {len(rows)} rekordów")
def main():
tables = ["user", "shopping_list", "item", "expense", "receipt", "suggested_product"]
for table in tables:
migrate_table(table)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,14 @@
#!/bin/bash
set -e
APP_CONTAINER=web
DB_ENGINE=${1:-pgsql} # domyślnie pgsql
echo "Migracja z SQLite do $DB_ENGINE..."
docker-compose run --rm $APP_CONTAINER bash -c "
export FLASK_APP=app.py
flask db upgrade
"
echo "Migracja zakończona."

View File

@@ -3,7 +3,24 @@ import os
class Config:
SECRET_KEY = os.environ.get("SECRET_KEY", "D8pceNZ8q%YR7^7F&9wAC2")
SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL", "sqlite:///shopping.db")
DB_ENGINE = os.environ.get("DB_ENGINE", "sqlite").lower()
if DB_ENGINE == "sqlite":
SQLALCHEMY_DATABASE_URI = "sqlite:///instance/shopping.db"
elif DB_ENGINE == "pgsql":
SQLALCHEMY_DATABASE_URI = f"postgresql://{os.environ['DB_USER']}:{os.environ['DB_PASSWORD']}@{os.environ['DB_HOST']}:{os.environ.get('DB_PORT', 5432)}/{os.environ['DB_NAME']}"
elif DB_ENGINE == "mysql":
SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{os.environ['DB_USER']}:{os.environ['DB_PASSWORD']}@{os.environ['DB_HOST']}:{os.environ.get('DB_PORT', 3306)}/{os.environ['DB_NAME']}"
elif DB_ENGINE == "firebird":
SQLALCHEMY_DATABASE_URI = f"firebird+fdb://{os.environ['DB_USER']}:{os.environ['DB_PASSWORD']}@{os.environ['DB_HOST']}/{os.environ['DB_NAME']}.fdb"
else:
raise ValueError("Nieobsługiwany typ bazy danych.")
SQLALCHEMY_TRACK_MODIFICATIONS = False
SYSTEM_PASSWORD = os.environ.get("SYSTEM_PASSWORD", "admin")
DEFAULT_ADMIN_USERNAME = os.environ.get("DEFAULT_ADMIN_USERNAME", "admin")

View File

@@ -8,6 +8,8 @@ echo "Pobieram najnowszy kod z repozytorium..."
git pull
echo "Buduję obrazy i uruchamiam kontenery..."
docker compose up -d --build
#docker compose up -d --build
DB_ENGINE=pgsql docker compose --profile pgsql up -d --build
echo "Gotowe!"

View File

@@ -10,18 +10,53 @@ services:
timeout: 10s
retries: 3
start_period: 10s
environment:
- FLASK_APP=app.py
- FLASK_ENV=production
- SECRET_KEY=${SECRET_KEY}
- SYSTEM_PASSWORD=${SYSTEM_PASSWORD}
- DEFAULT_ADMIN_USERNAME=${DEFAULT_ADMIN_USERNAME}
- DEFAULT_ADMIN_PASSWORD=${DEFAULT_ADMIN_PASSWORD}
- UPLOAD_FOLDER=${UPLOAD_FOLDER}
- AUTHORIZED_COOKIE_VALUE=${AUTHORIZED_COOKIE_VALUE}
- AUTH_COOKIE_MAX_AGE=${AUTH_COOKIE_MAX_AGE}
- HEALTHCHECK_TOKEN=${HEALTHCHECK_TOKEN}
- SESSION_TIMEOUT_MINUTES=${SESSION_TIMEOUT_MINUTES}
env_file:
- .env
volumes:
- .:/app
restart: unless-stopped
- ./uploads:/app/uploads
- ./instance:/app/instance
restart: unless-stopped
# depends_on:
# - ${DB_ENGINE:-sqlite}
pgsql:
image: postgres:17
container_name: pgsql-db
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- ./db/pgsql:/var/lib/postgresql/data
ports:
- "5432:5432"
restart: unless-stopped
profiles: ["pgsql"]
mysql:
image: mysql:8
container_name: mysql-db
environment:
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: root
volumes:
- ./db/mysql:/var/lib/mysql
ports:
- "3306:3306"
restart: unless-stopped
profiles: ["mysql"]
firebird:
image: jacobalberty/firebird
container_name: firebird-db
environment:
ISC_PASSWORD: ${DB_PASSWORD}
volumes:
- ./db/firebird:/firebird/data
ports:
- "3050:3050"
restart: unless-stopped
profiles: ["firebird"]

View File

@@ -10,4 +10,4 @@ psutil
pillow-heif
pytesseract
opencv-python-headless
opencv-python-headless