Improve performance of calendar view
This commit is contained in:
@@ -32,38 +32,52 @@ def _get_date_range_and_links(date_obj, view):
|
|||||||
raise ValueError('Invalid view type specified.')
|
raise ValueError('Invalid view type specified.')
|
||||||
return start_date, end_date, prev_date, next_date
|
return start_date, end_date, prev_date, next_date
|
||||||
|
|
||||||
def _fetch_raw_workout_data(db_executor, person_id, start_date, end_date):
|
def _fetch_workout_data(db_executor, person_id, start_date, end_date, include_details=True):
|
||||||
"""Fetches workout data for a person within a date range."""
|
"""Fetches workout data for a person within a date range."""
|
||||||
query = """
|
if include_details:
|
||||||
SELECT
|
query = """
|
||||||
w.workout_id,
|
SELECT
|
||||||
w.start_date,
|
w.workout_id,
|
||||||
t.topset_id,
|
w.start_date,
|
||||||
t.repetitions,
|
t.topset_id,
|
||||||
t.weight,
|
t.repetitions,
|
||||||
e.name AS exercise_name,
|
t.weight,
|
||||||
p.name AS person_name
|
e.name AS exercise_name,
|
||||||
FROM
|
p.name AS person_name
|
||||||
person p
|
FROM
|
||||||
LEFT JOIN workout w ON p.person_id = w.person_id AND w.start_date BETWEEN %s AND %s
|
person p
|
||||||
LEFT JOIN topset t ON w.workout_id = t.workout_id
|
LEFT JOIN workout w ON p.person_id = w.person_id AND w.start_date BETWEEN %s AND %s
|
||||||
LEFT JOIN exercise e ON t.exercise_id = e.exercise_id
|
LEFT JOIN topset t ON w.workout_id = t.workout_id
|
||||||
WHERE
|
LEFT JOIN exercise e ON t.exercise_id = e.exercise_id
|
||||||
p.person_id = %s
|
WHERE
|
||||||
ORDER BY
|
p.person_id = %s
|
||||||
w.start_date,
|
ORDER BY
|
||||||
t.topset_id;
|
w.start_date,
|
||||||
"""
|
t.topset_id;
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
query = """
|
||||||
|
SELECT
|
||||||
|
w.workout_id,
|
||||||
|
w.start_date,
|
||||||
|
p.name AS person_name
|
||||||
|
FROM
|
||||||
|
person p
|
||||||
|
LEFT JOIN workout w ON p.person_id = w.person_id AND w.start_date BETWEEN %s AND %s
|
||||||
|
WHERE
|
||||||
|
p.person_id = %s
|
||||||
|
ORDER BY
|
||||||
|
w.start_date;
|
||||||
|
"""
|
||||||
# Ensure dates are passed in a format the DB understands (e.g., YYYY-MM-DD strings)
|
# Ensure dates are passed in a format the DB understands (e.g., YYYY-MM-DD strings)
|
||||||
return db_executor(query, [start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'), person_id])
|
return db_executor(query, [start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'), person_id])
|
||||||
|
|
||||||
def _group_workouts_by_date(workouts_data):
|
def _group_workouts_by_date(workouts_data):
|
||||||
"""Groups workout data by date and workout ID."""
|
"""Groups workout data by date and workout ID."""
|
||||||
# Structure: { 'YYYY-MM-DD': { workout_id: { workout_details..., 'sets': [...] } } }
|
# Structure: { date_object: { workout_id: { workout_details..., 'sets': [...] } } }
|
||||||
workouts_by_date = defaultdict(lambda: defaultdict(lambda: {'sets': []}))
|
workouts_by_date = defaultdict(lambda: defaultdict(lambda: {'sets': []}))
|
||||||
person_name = 'Unknown'
|
person_name = 'Unknown'
|
||||||
if workouts_data:
|
if workouts_data:
|
||||||
# Use .get() for safer access in case the key doesn't exist
|
|
||||||
person_name = workouts_data[0].get('person_name', 'Unknown')
|
person_name = workouts_data[0].get('person_name', 'Unknown')
|
||||||
|
|
||||||
for row in workouts_data:
|
for row in workouts_data:
|
||||||
@@ -72,29 +86,27 @@ def _group_workouts_by_date(workouts_data):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
workout_date = row['start_date']
|
workout_date = row['start_date']
|
||||||
workout_date_str = workout_date.strftime("%Y-%m-%d")
|
|
||||||
workout_id = row['workout_id']
|
workout_id = row['workout_id']
|
||||||
|
|
||||||
# Initialize workout details if this workout_id hasn't been seen for this date
|
# Initialize workout details if this workout_id hasn't been seen for this date
|
||||||
if workout_id not in workouts_by_date[workout_date_str]:
|
if workout_id not in workouts_by_date[workout_date]:
|
||||||
workouts_by_date[workout_date_str][workout_id].update({
|
workouts_by_date[workout_date][workout_id].update({
|
||||||
'workout_id': workout_id,
|
'workout_id': workout_id,
|
||||||
'start_date': workout_date,
|
'start_date': workout_date,
|
||||||
# 'sets' is already initialized by defaultdict
|
|
||||||
})
|
})
|
||||||
|
|
||||||
# Add set details if topset_id exists
|
# Add set details if topset_id exists
|
||||||
if row.get('topset_id'):
|
if row.get('topset_id'):
|
||||||
workouts_by_date[workout_date_str][workout_id]['sets'].append({
|
workouts_by_date[workout_date][workout_id]['sets'].append({
|
||||||
'repetitions': row.get('repetitions'),
|
'repetitions': row.get('repetitions'),
|
||||||
'weight': row.get('weight'),
|
'weight': row.get('weight'),
|
||||||
'exercise_name': row.get('exercise_name')
|
'exercise_name': row.get('exercise_name')
|
||||||
})
|
})
|
||||||
|
|
||||||
# Convert nested defaultdict to regular dict for easier handling/JSON serialization
|
# Convert nested defaultdict to regular dict
|
||||||
processed_workouts = {
|
processed_workouts = {
|
||||||
date_str: dict(workouts)
|
d: dict(w)
|
||||||
for date_str, workouts in workouts_by_date.items()
|
for d, w in workouts_by_date.items()
|
||||||
}
|
}
|
||||||
return processed_workouts, person_name
|
return processed_workouts, person_name
|
||||||
|
|
||||||
@@ -104,8 +116,7 @@ def _process_workouts_for_month_view(grouped_workouts, start_date, end_date, sel
|
|||||||
today = datetime.today().date()
|
today = datetime.today().date()
|
||||||
current_date = start_date
|
current_date = start_date
|
||||||
while current_date <= end_date:
|
while current_date <= end_date:
|
||||||
date_str = current_date.strftime("%Y-%m-%d")
|
day_workouts_dict = grouped_workouts.get(current_date, {})
|
||||||
day_workouts_dict = grouped_workouts.get(date_str, {})
|
|
||||||
day_workouts_list = list(day_workouts_dict.values()) # Convert workout dicts to list
|
day_workouts_list = list(day_workouts_dict.values()) # Convert workout dicts to list
|
||||||
|
|
||||||
days_data.append({
|
days_data.append({
|
||||||
@@ -134,8 +145,7 @@ def _process_workouts_for_year_view(grouped_workouts, year_date):
|
|||||||
month_days_data = []
|
month_days_data = []
|
||||||
current_day = start_date_month
|
current_day = start_date_month
|
||||||
while current_day <= end_date_month:
|
while current_day <= end_date_month:
|
||||||
date_str = current_day.strftime('%Y-%m-%d')
|
day_workouts_dict = grouped_workouts.get(current_day, {})
|
||||||
day_workouts_dict = grouped_workouts.get(date_str, {})
|
|
||||||
day_workouts_list = list(day_workouts_dict.values())
|
day_workouts_list = list(day_workouts_dict.values())
|
||||||
has_workouts = len(day_workouts_list) > 0
|
has_workouts = len(day_workouts_list) > 0
|
||||||
# Get first workout ID if workouts exist
|
# Get first workout ID if workouts exist
|
||||||
@@ -184,8 +194,9 @@ def get_calendar(person_id):
|
|||||||
# For now, returning a simple error response
|
# For now, returning a simple error response
|
||||||
return f"Error: Invalid view type '{selected_view}'.", 400
|
return f"Error: Invalid view type '{selected_view}'.", 400
|
||||||
|
|
||||||
# Fetch and process data
|
# Fetch and process data (only fetch details if in month view)
|
||||||
raw_workouts = _fetch_raw_workout_data(db.execute, person_id, start_date, end_date)
|
include_details = (selected_view == 'month')
|
||||||
|
raw_workouts = _fetch_workout_data(db.execute, person_id, start_date, end_date, include_details=include_details)
|
||||||
grouped_workouts, person_name = _group_workouts_by_date(raw_workouts)
|
grouped_workouts, person_name = _group_workouts_by_date(raw_workouts)
|
||||||
|
|
||||||
# Prepare base context for the template
|
# Prepare base context for the template
|
||||||
|
|||||||
Reference in New Issue
Block a user