Newer
Older
form = fpctx.page.post_form(
post_data=request.POST, files_data=request.FILES)
pressed_button = get_pressed_button(form)
if form.is_valid():
# {{{ form validated, process answer
messages.add_message(request, messages.INFO,
"Answer saved.")
page_visit = FlowPageVisit()
page_visit.flow_session = flow_session
page_visit.page_data = fpctx.page_data
page_visit.remote_address = request.META['REMOTE_ADDR']
answer_data = page_visit.answer = fpctx.page.answer_data(
fpctx.page_context, fpctx.page_data.data,
form, request.FILES)
page_visit.is_graded_answer = pressed_button == "submit"
answer_was_graded = page_visit.is_graded_answer
may_change_answer = (
not answer_was_graded
or flow_permission.change_answer
feedback = fpctx.page.grade(
page_context, page_data.data, page_visit.answer,
grade_data=None)
if page_visit.is_graded_answer:
grade = FlowPageVisitGrade()
grade.visit = page_visit
grade.max_points = fpctx.page.max_points(page_data.data)
grade.graded_at_git_commit_sha = pctx.course_commit_sha
bulk_feedback_json = None
if feedback is not None:
grade.correctness = feedback.correctness
grade.feedback, bulk_feedback_json = feedback.as_json()
grade.save()
print bulk_feedback_json
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
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_graded_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:
flow_permission.see_correctness in permissions
or (
(flow_permission.see_correctness_after_completion
and not flow_session.in_progress))
show_answer = (
flow_permission.see_answer in permissions
or (
(flow_permission.see_answer_after_completion
in permissions)
and not flow_session.in_progress))
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
or (
(flow_permission.see_answer_after_completion
in permissions)
and not flow_session.in_progress))
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, current_access_rule.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():
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)
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
@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)
current_access_rule = fctx.get_current_access_rule(
flow_session, pctx.role, pctx.participation,
get_now_or_fake_time(pctx.request))
if is_expiration_mode_allowed(expmode, current_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)
current_access_rule = fctx.get_current_access_rule(
flow_session, pctx.role, pctx.participation,
get_now_or_fake_time(request))
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(
fctx, flow_session, answer_visits)
is_graded_flow = bool(answered_count + unanswered_count)
if flow_permission.view not in current_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")
Andreas Klöckner
committed
grade_info = finish_flow_session(
fctx, flow_session, current_access_rule,
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(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)
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
# {{{ 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_id"] = forms.CharField(
required=False,
help_text="If non-empty, limit the regrading to sessions started "
"under this access rules ID.")
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"],
for_credit=False))
if form.cleaned_data["access_rules_id"]:
sessions = sessions.filter(
access_rules_id=form.cleaned_data["access_rules_id"])
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 only considers not-for-credit flow "
"sessions. 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",
})
# }}}