Files
bloodpressure/app/routes/data.py

77 lines
2.8 KiB
Python

import csv
from io import StringIO
from flask import Blueprint, render_template, redirect, request, send_file, url_for, flash
from app.models import Reading, db
from flask_login import login_required, current_user
from datetime import datetime
data = Blueprint('data', __name__)
@data.route('/', methods=['GET', 'POST'])
@login_required
def manage_data():
if request.method == 'POST':
# Handle CSV file upload
file = request.files.get('file')
if file and file.filename.endswith('.csv'):
try:
csv_data = csv.reader(StringIO(file.read().decode('utf-8')))
next(csv_data) # Skip the header row
readings_to_add = []
for row in csv_data:
timestamp, systolic, diastolic, heart_rate = row
readings_to_add.append(Reading(
user_id=current_user.id,
timestamp=datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S'),
systolic=int(systolic),
diastolic=int(diastolic),
heart_rate=int(heart_rate),
))
db.session.bulk_save_objects(readings_to_add)
db.session.commit()
flash('Data imported successfully!', 'success')
except Exception as e:
flash(f'Error importing data: {str(e)}', 'danger')
else:
flash('Please upload a valid CSV file.', 'danger')
return redirect(url_for('data.manage_data'))
return render_template('data.html')
@data.route('/export', methods=['GET'])
@login_required
def export_data():
import io
from flask import Response
def generate_csv():
"""Stream CSV rows to avoid loading all readings into memory."""
# Write header
output = io.StringIO()
writer = csv.writer(output)
writer.writerow(['Timestamp', 'Systolic', 'Diastolic', 'Heart Rate'])
yield output.getvalue()
output.seek(0)
output.truncate(0)
# Stream readings in chunks using yield_per
readings = Reading.query.filter_by(user_id=current_user.id).order_by(
Reading.timestamp
).yield_per(500)
for reading in readings:
writer.writerow([
reading.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
reading.systolic,
reading.diastolic,
reading.heart_rate,
])
yield output.getvalue()
output.seek(0)
output.truncate(0)
return Response(
generate_csv(),
mimetype='text/csv',
headers={'Content-Disposition': 'attachment; filename=readings.csv'}
)