Newer
Older
grade.save()
delete_other_bulk_feedback(page_data)
if bulk_feedback_json is not None:
FlowPageBulkFeedback(
page_data=page_data,
grade=grade,
bulk_feedback=bulk_feedback_json
).save()
del grade
else:
feedback = None
if (pressed_button == "save_and_next"
and not will_receive_feedback(permissions)):
return redirect("course.flow.view_flow_page",
pctx.course.identifier,
fpctx.ordinal + 1)
elif (pressed_button == "save_and_finish"
and not will_receive_feedback(permissions)):
return redirect("course.flow.finish_flow_session_view",
pctx.course.identifier, flow_session_id)
form = fpctx.page.make_form(
page_visit.answer, not may_change_answer)
# continue at common flow page generation below
# }}}
del page_visit
else:
# form did not validate
create_flow_page_visit(request, flow_session, fpctx.page_data)
answer_was_graded = False
may_change_answer = True
# because we were allowed this far in by the check above
feedback = None
# continue at common flow page generation below
else:
create_flow_page_visit(request, flow_session, fpctx.page_data)
if fpctx.prev_answer_visit is not None:
answer_was_graded = fpctx.prev_answer_visit.is_submitted_answer
else:
answer_was_graded = False
may_change_answer = (
(not answer_was_graded
or (flow_permission.change_answer in permissions))
and flow_session.in_progress)
if fpctx.prev_answer_visit is not None:
answer_data = fpctx.prev_answer_visit.answer
most_recent_grade = fpctx.prev_answer_visit.get_most_recent_grade()
if most_recent_grade is not None:
feedback = get_feedback_for_grade(most_recent_grade)
grade_data = most_recent_grade.grade_data
else:
feedback = None
grade_data = None
else:
feedback = None
form = fpctx.page.make_form(
answer_data, not may_change_answer)
feedback = None
# start common flow page generation
# defined at this point:
# form, form_html, may_change_answer, answer_was_graded, feedback
if form is not None and may_change_answer:
form = add_buttons_to_form(form, fpctx, flow_session,
show_correctness = None
show_answer = None
shown_feedback = None
if fpctx.page.expects_answer() and answer_was_graded:
show_correctness = flow_permission.see_correctness in permissions
show_answer = flow_permission.see_answer in permissions
if show_correctness or show_answer:
shown_feedback = feedback
elif fpctx.page.expects_answer() and not answer_was_graded:
# Don't show answer yet
pass
else:
show_answer = flow_permission.see_answer in permissions
title = fpctx.page.title(page_context, page_data.data)
body = fpctx.page.body(page_context, page_data.data)
if show_answer:
correct_answer = fpctx.page.correct_answer(
page_context, page_data.data,
answer_data, grade_data)
else:
correct_answer = None
if form is not None:
form_html = fpctx.page.form_to_html(
pctx.request, page_context, form, answer_data)
else:
form_html = None
expiration_mode_choices = []
for key, descr in FLOW_SESSION_EXPIRATION_MODE_CHOICES:
if is_expiration_mode_allowed(key, permissions):
expiration_mode_choices.append((key, descr))
args = {
"flow_identifier": fpctx.flow_identifier,
"flow_desc": fpctx.flow_desc,
"ordinal": fpctx.ordinal,
"page_data": fpctx.page_data,
"percentage": int(100*(fpctx.ordinal+1) / flow_session.page_count),
"flow_session": flow_session,
"page_numbers": zip(
range(flow_session.page_count),
range(1, flow_session.page_count+1)),
"feedback": shown_feedback,
"correct_answer": correct_answer,
"may_change_graded_answer": (
(flow_permission.change_answer
and flow_session.in_progress),
"will_receive_feedback": will_receive_feedback(permissions),
"expiration_mode_choices": expiration_mode_choices,
"expiration_mode_choice_count": len(expiration_mode_choices),
"expiration_mode": flow_session.expiration_mode,
if fpctx.page.expects_answer() and fpctx.page.is_answer_gradable():
args["max_points"] = fpctx.page.max_points(fpctx.page_data)
return render_course_page(
pctx, "course/flow-page.html", args,
allow_instant_flow_requests=False)
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
@course_view
def update_expiration_mode(pctx, flow_session_id):
if pctx.request.method != "POST":
raise SuspiciousOperation("only POST allowed")
flow_session = get_object_or_404(FlowSession, id=flow_session_id)
if flow_session.participation != pctx.participation:
raise PermissionDenied("may only change your own flow sessions")
if not flow_session.in_progress:
raise PermissionDenied("may only change in-progress flow sessions")
expmode = pctx.request.POST.get("expiration_mode")
if not any(expmode == em_key
for em_key, _ in FLOW_SESSION_EXPIRATION_MODE_CHOICES):
raise SuspiciousOperation("invalid expiration mode")
fctx = FlowContext(pctx.repo, pctx.course, flow_session.flow_id,
participation=pctx.participation,
flow_session=flow_session)
access_rule = get_session_access_rule(
flow_session, pctx.role, fctx.flow_desc,
get_now_or_fake_time(pctx.request))
if is_expiration_mode_allowed(expmode, access_rule.permissions):
flow_session.expiration_mode = expmode
flow_session.save()
return http.HttpResponse("OK")
else:
raise PermissionDenied()
# {{{ view: finish flow
def finish_flow_session_view(pctx, flow_session_id):
Andreas Klöckner
committed
now_datetime = get_now_or_fake_time(pctx.request)
request = pctx.request
flow_session_id = int(flow_session_id)
flow_session = get_and_check_flow_session(
pctx, flow_session_id)
flow_identifier = flow_session.flow_id
fctx = FlowContext(pctx.repo, pctx.course, flow_identifier,
participation=pctx.participation,
flow_session=flow_session)
access_rule = get_session_access_rule(
flow_session, pctx.role, fctx.flow_desc, now_datetime)
answer_visits = assemble_answer_visits(flow_session)
from course.content import markup_to_html
completion_text = markup_to_html(
fctx.course, fctx.repo, pctx.course_commit_sha,
fctx.flow_desc.completion_text)
(answered_count, unanswered_count) = count_answered_gradable(
fctx, flow_session, answer_visits)
is_graded_flow = bool(answered_count + unanswered_count)
if flow_permission.view not in access_rule.permissions:
raise PermissionDenied()
def render_finish_response(template, **kwargs):
render_args = {
"flow_identifier": fctx.flow_identifier,
"flow_desc": fctx.flow_desc,
}
render_args.update(kwargs)
return render_course_page(
pctx, template, render_args,
allow_instant_flow_requests=False)
if request.method == "POST":
if "submit" not in request.POST:
raise SuspiciousOperation("odd POST parameters")
if not flow_session.in_progress:
raise PermissionDenied("Can't end a session that's already ended")
# reject answer update if modify permission not present
if flow_permission.modify not in access_rule.permissions:
raise PermissionDenied("not permitted to modify flow")
grading_rule = get_session_grading_rule(
flow_session, pctx.role, fctx.flow_desc, now_datetime)
Andreas Klöckner
committed
grade_info = finish_flow_session(
fctx, flow_session, grading_rule,
Andreas Klöckner
committed
now_datetime=now_datetime)
if is_graded_flow:
return render_finish_response(
"course/flow-completion-grade.html",
completion_text=completion_text,
grade_info=grade_info)
else:
return render_finish_response(
"course/flow-completion.html",
last_page_nr=None,
flow_session=flow_session,
completion_text=completion_text)
if not is_graded_flow:
# Not serious--no questions in flow.
return render_finish_response(
"course/flow-completion.html",
flow_session=flow_session,
completion_text=completion_text)
elif not flow_session.in_progress:
# Just reviewing: re-show grades.
grade_info = gather_grade_info(fctx, flow_session, answer_visits)
return render_finish_response(
"course/flow-completion-grade.html",
completion_text=completion_text,
grade_info=grade_info)
else:
# confirm ending flow
return render_finish_response(
"course/flow-confirm-completion.html",
flow_session=flow_session,
answered_count=answered_count,
unanswered_count=unanswered_count,
total_count=answered_count+unanswered_count)
# {{{ view: regrade flow
class RegradeFlowForm(StyledForm):
def __init__(self, flow_ids, *args, **kwargs):
super(RegradeFlowForm, self).__init__(*args, **kwargs)
self.fields["flow_id"] = forms.ChoiceField(
choices=[(fid, fid) for fid in flow_ids],
initial=participation_role.student,
required=True)
self.fields["access_rules_tag"] = forms.CharField(
required=False,
help_text="If non-empty, limit the regrading to sessions started "
"under this access rules tag.")
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
self.fields["regraded_session_in_progress"] = forms.ChoiceField(
choices=(
("any", "Regrade in-progress and not-in-progress sessions"),
("yes", "Regrade in-progress sessions only"),
("no", "Regrade not-in-progress sessions only"),
))
self.helper.add_input(
Submit("regrade", "Regrade", css_class="col-lg-offset-2"))
@transaction.atomic
def _regrade_sessions(repo, course, sessions):
count = 0
from course.flow import regrade_session
for session in sessions:
regrade_session(repo, course, session)
count += 1
return count
@course_view
def regrade_not_for_credit_flows_view(pctx):
if pctx.role != participation_role.instructor:
raise PermissionDenied("must be instructor to regrade flows")
from course.content import list_flow_ids
flow_ids = list_flow_ids(pctx.repo, pctx.course_commit_sha)
request = pctx.request
if request.method == "POST":
form = RegradeFlowForm(flow_ids, request.POST, request.FILES)
if form.is_valid():
sessions = (FlowSession.objects
.filter(
course=pctx.course,
flow_id=form.cleaned_data["flow_id"]))
if form.cleaned_data["access_rules_tag"]:
access_rules_tag=form.cleaned_data["access_rules_tag"])
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
inprog_value = {
"any": None,
"yes": True,
"no": False,
}[form.cleaned_data["regraded_session_in_progress"]]
if inprog_value is not None:
sessions = sessions.filter(
in_progress=inprog_value)
count = _regrade_sessions(pctx.repo, pctx.course, sessions)
messages.add_message(request, messages.SUCCESS,
"%d sessions regraded." % count)
else:
form = RegradeFlowForm(flow_ids)
return render_course_page(pctx, "course/generic-course-form.html", {
"form": form,
"form_text":
"<p>This regrading process is only intended for flows "
"that do not show up in the grade book."
"If you would like to regrade for-credit flows, "
"use the corresponding functionality in the grade book.</p>",
"form_description": "Regrade not-for-credit Flow Sessions",
})