-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcalculate_review_averages.py
More file actions
156 lines (144 loc) · 5.9 KB
/
calculate_review_averages.py
File metadata and controls
156 lines (144 loc) · 5.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
from tqdm import tqdm
from django.core.management.base import BaseCommand
from django.db import transaction
from django.db.models import OuterRef, Q, Subquery, Avg, F, Value, IntegerField
from courses.models import Course, Section, Instructor
from review.models import ReviewBit, Review
from review.views import section_filters_pcr
def calculate_course_review_averages(course_queryset, stdout):
"""
Calculates and updates review averages for a given Course queryset.
"""
# Use a simplified version of review_averages that only focuses on Course data
# We need to re-implement some parts as review_averages is too generic for direct use here
annotated_queryset = course_queryset.annotate(
avg_course_quality=Subquery(
ReviewBit.objects.filter(
review__section__course__topic=OuterRef('topic'),
field='course_quality',
review__responses__gt=0,
)
.values('field')
.order_by()
.annotate(avg=Avg('average'))
.values('avg')[:1]
),
avg_instructor_quality=Subquery(
ReviewBit.objects.filter(
review__section__course__topic=OuterRef('topic'),
field='instructor_quality',
review__responses__gt=0,
)
.values('field')
.order_by()
.annotate(avg=Avg('average'))
.values('avg')[:1]
),
avg_difficulty=Subquery(
ReviewBit.objects.filter(
review__section__course__topic=OuterRef('topic'),
field='difficulty',
review__responses__gt=0,
)
.values('field')
.order_by()
.annotate(avg=Avg('average'))
.values('avg')[:1]
),
avg_work_required=Subquery(
ReviewBit.objects.filter(
review__section__course__topic=OuterRef('topic'),
field='work_required',
review__responses__gt=0,
)
.values('field')
.order_by()
.annotate(avg=Avg('average'))
.values('avg')[:1]
),
)
with transaction.atomic():
for course in tqdm(annotated_queryset, desc="Updating Course Averages", file=stdout):
Course.objects.filter(pk=course.pk).update(
course_quality=course.avg_course_quality,
instructor_quality=course.avg_instructor_quality,
difficulty=course.avg_difficulty,
work_required=course.avg_work_required,
)
def calculate_section_review_averages(section_queryset, stdout):
"""
Calculates and updates review averages for a given Section queryset.
"""
# Similar to calculate_course_review_averages, we need to re-implement for sections
# as the original review_averages was too generic.
# Subquery for instructors related to the section
instructors_subquery = Subquery(
Instructor.objects.filter(section__id=OuterRef(OuterRef("id"))).values("id")
)
annotated_queryset = section_queryset.annotate(
avg_course_quality=Subquery(
ReviewBit.objects.filter(
Q(review__section__course__topic=OuterRef('course__topic')) & \
Q(review__instructor__in=instructors_subquery),
field='course_quality',
review__responses__gt=0,
)
.values('field')
.order_by()
.annotate(avg=Avg('average'))
.values('avg')[:1]
),
avg_instructor_quality=Subquery(
ReviewBit.objects.filter(
Q(review__section__course__topic=OuterRef('course__topic')) & \
Q(review__instructor__in=instructors_subquery),
field='instructor_quality',
review__responses__gt=0,
)
.values('field')
.order_by()
.annotate(avg=Avg('average'))
.values('avg')[:1]
),
avg_difficulty=Subquery(
ReviewBit.objects.filter(
Q(review__section__course__topic=OuterRef('course__topic')) & \
Q(review__instructor__in=instructors_subquery),
field='difficulty',
review__responses__gt=0,
)
.values('field')
.order_by()
.annotate(avg=Avg('average'))
.values('avg')[:1]
),
avg_work_required=Subquery(
ReviewBit.objects.filter(
Q(review__section__course__topic=OuterRef('course__topic')) & \
Q(review__instructor__in=instructors_subquery),
field='work_required',
review__responses__gt=0,
)
.values('field')
.order_by()
.annotate(avg=Avg('average'))
.values('avg')[:1]
),
)
with transaction.atomic():
for section in tqdm(annotated_queryset, desc="Updating Section Averages", file=stdout):
Section.objects.filter(pk=section.pk).update(
course_quality=section.avg_course_quality,
instructor_quality=section.avg_instructor_quality,
difficulty=section.avg_difficulty,
work_required=section.avg_work_required,
)
class Command(BaseCommand):
help = 'Calculates and saves review averages for Course and Section models.'
def handle(self, *args, **options):
self.stdout.write("Calculating Course review averages...")
calculate_course_review_averages(Course.objects.all(), self.stdout)
self.stdout.write(self.style.SUCCESS("Finished calculating Course review averages."))
self.stdout.write("Calculating Section review averages...")
calculate_section_review_averages(Section.objects.all(), self.stdout)
self.stdout.write(self.style.SUCCESS("Finished calculating Section review averages."))