From Json to PostgreSQL

This commit is contained in:
Greg 2025-05-11 09:31:20 +02:00
parent 00365460d4
commit 94b0f9f693
2 changed files with 97 additions and 26 deletions

121
app.py
View File

@ -1,32 +1,92 @@
from flask import Flask, render_template, request, jsonify, send_from_directory from flask import Flask, render_template, request, jsonify
import json from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import func
import os import os
app = Flask(__name__) app = Flask(__name__)
DATA_FILE = 'data/attendance_data.json' app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL')
db = SQLAlchemy(app)
# Default player names # Models
DEFAULT_PLAYERS = [ class Player(db.Model):
"Alice", "Bob", "Charlie", "David", "Eve", "Frank", "Grace", "Hannah" id = db.Column(db.Integer, primary_key=True)
] name = db.Column(db.String(50), nullable=False, unique=True)
DEFAULT_GUEST = "Guest"
def load_data(): class Date(db.Model):
if not os.path.exists(DATA_FILE): id = db.Column(db.Integer, primary_key=True)
data = { date_str = db.Column(db.String(20), nullable=False, unique=True) # e.g. '08/05/25'
"players": DEFAULT_PLAYERS,
"guest": DEFAULT_GUEST,
"dates": [],
"attendance": {}
}
with open(DATA_FILE, 'w') as f:
json.dump(data, f)
with open(DATA_FILE, 'r') as f:
return json.load(f)
def save_data(data): class Attendance(db.Model):
with open(DATA_FILE, 'w') as f: id = db.Column(db.Integer, primary_key=True)
json.dump(data, f, indent=2) date_id = db.Column(db.Integer, db.ForeignKey('date.id'), nullable=False)
player_id = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=False)
status = db.Column(db.String(10), nullable=False) # 'yes' or 'no'
__table_args__ = (db.UniqueConstraint('date_id', 'player_id', name='_date_player_uc'),)
class GuestName(db.Model):
id = db.Column(db.Integer, primary_key=True)
date_id = db.Column(db.Integer, db.ForeignKey('date.id'), nullable=False, unique=True)
name = db.Column(db.String(50), nullable=False)
def get_initial_data():
# Ensure tables exist
db.create_all()
# If no players, insert defaults
if Player.query.count() == 0:
for name in ["Alice", "Bob", "Charlie", "David", "Eve", "Frank", "Grace", "Hannah"]:
db.session.add(Player(name=name))
db.session.commit()
if not GuestName.query.first():
# Set default guest name for all dates
pass
def db_to_json():
players = [p.name for p in Player.query.order_by(Player.id)]
guest = "Guest"
dates = [d.date_str for d in Date.query.order_by(Date.id)]
attendance = {}
for att in Attendance.query.all():
date = Date.query.get(att.date_id).date_str
player = Player.query.get(att.player_id)
colIdx = players.index(player.name) if player.name in players else len(players) # guest is last
key = f"{date}|{colIdx}"
attendance[key] = True if att.status == 'yes' else 'no'
guest_names = {Date.query.get(g.date_id).date_str: g.name for g in GuestName.query.all()}
return {
"players": players,
"guest": guest,
"dates": dates,
"attendance": attendance,
"guestNames": guest_names
}
def json_to_db(data):
db.session.query(Attendance).delete()
db.session.query(Date).delete()
db.session.query(GuestName).delete()
db.session.commit()
# Players are assumed fixed
for date_str in data.get("dates", []):
date = Date(date_str=date_str)
db.session.add(date)
db.session.commit()
# Attendance
for idx, player_name in enumerate(data["players"] + [data["guest"]]):
key = f"{date_str}|{idx}"
status = data["attendance"].get(key)
if status:
if player_name == data["guest"]:
# Guest is not stored as player, skip
continue
player = Player.query.filter_by(name=player_name).first()
if player:
db.session.add(Attendance(date_id=date.id, player_id=player.id, status='yes' if status is True else 'no'))
# Guest name
guest_name = data.get("guestNames", {}).get(date_str)
if guest_name:
db.session.add(GuestName(date_id=date.id, name=guest_name))
db.session.commit()
@app.route('/') @app.route('/')
def index(): def index():
@ -38,17 +98,26 @@ def reports():
@app.route('/api/data', methods=['GET']) @app.route('/api/data', methods=['GET'])
def get_data(): def get_data():
return jsonify(load_data()) get_initial_data()
return jsonify(db_to_json())
@app.route('/api/data', methods=['POST']) @app.route('/api/data', methods=['POST'])
def update_data(): def update_data():
data = request.json data = request.json
save_data(data) json_to_db(data)
return jsonify({"status": "success"}) return jsonify({"status": "success"})
# Optional: export from DB as JSON (for compatibility)
@app.route('/export-data') @app.route('/export-data')
def export_data(): def export_data():
return send_from_directory(directory='data', path='attendance_data.json', as_attachment=True) from flask import Response
get_initial_data()
data = db_to_json()
return Response(
response=json.dumps(data, indent=2),
mimetype='application/json',
headers={'Content-Disposition': 'attachment;filename=attendance_data.json'}
)
if __name__ == '__main__': if __name__ == '__main__':
import os import os

View File

@ -1 +1,3 @@
flask flask
sqlalchemy
psycopg2-binary