def public_gradebook(): students = Student.all(order='alias') assignments = [a for a in Assignment.all() if a.is_public] for student in students: # Set the grades following the order specified by assignment_pks grades = student.get_grades() grades_by_assignment_pk = dict([(g.assignment_pk, g) for g in grades]) student.points_by_assignment_pk = {} for assignment in assignments: grade = grades_by_assignment_pk.get(assignment.pk) if grade: grade.assignment = assignment points = grade.points if grade else 0 student.points_by_assignment_pk[assignment.pk] = points student.grades = grades student.has_comments = any((grade.comment for grade in grades)) now = datetime.now() return render_template( "public_gradebook.html", assignments=assignments, students=students, now=now )
def assignment_view(assignment_pk): assignment = Assignment.get(pk=assignment_pk) students = Student.all() grades = assignment.get_grades() g_by_student_pk = dict([(g.student_pk, g) for g in grades]) for s in students: s.grade = g_by_student_pk.get(s.pk) return render_template('assignment_view.html', assignment=assignment, students=students)
def assignment_view(assignment_pk): assignment = Assignment.get(pk=assignment_pk) students = Student.all() grades = assignment.get_grades() g_by_student_pk = dict([(g.student_pk, g) for g in grades]) for s in students: s.grade = g_by_student_pk.get(s.pk) return render_template( 'assignment_view.html', assignment=assignment, students=students )
def get(self): from model import Student import datetime import settings students = tuple(Student.all().filter("latest_logout_timestamp =", None)) for student in students: if datetime.datetime.now() > student.latest_login_timestamp + settings.STUDENT_SESSION_TIMEOUT: student.log_out(True) from helpers import log log('=> LOGGED OUT {0} FROM LESSON {1} BECAUSE SESSION TIMED OUT'.format(student.nickname,student.lesson.lesson_code))
def gradebook(): students = Student.all() assignments = Assignment.all() assignment_pks = [a.pk for a in assignments] for student in students: # Set the grades following the order specified by assignment_pks grades = student.get_grades() by_assignment_pk = dict([(g.assignment_pk, g) for g in grades]) student.grades = [by_assignment_pk.get(pk) for pk in assignment_pks] return render_template("gradebook.html", assignments=assignments, students=students)
def assignment_grades_update(assignment_pk): assignment = Assignment.get(pk=assignment_pk) students = Student.all() grades = assignment.get_grades() # We decorate the student's with their grades. # Ideally, this would be done with a select_related type thing in the # model. At the SQL level. TODO g_by_student_pk = dict([(grade.student_pk, grade) for grade in grades]) for s in students: s.grade = g_by_student_pk.get(s.pk) if request.method == 'GET': return render_template( "assignment_grades_update.html", assignment=assignment, students=students ) # TODO: This POSt method seems cumbersome. Can it be fixed? if request.method == 'POST': for student in students: # These keys are first generated in the template as input tag # name attributes. points_key = "student_{0}_points".format(student.pk) comment_key = "student_{0}_comment".format(student.pk) try: points = request.form[points_key].strip() comment = request.form[comment_key].strip() except KeyError: # This will prevent a 400 status code from being returned if we # try to get data from the form about a student that didn't # exist when the form was created. continue try: points = int(points.strip()) except ValueError: points = None comment = comment.strip() if student.grade is None: student.grade = Grade( student_pk=student.pk, assignment_pk=assignment.pk, points=points, comment=comment ) else: student.grade.points = points student.grade.comment = comment student.grade.save() return redirect(url_for('assignment_view', assignment_pk=assignment_pk))
def gradebook(): students = Student.all() assignments = Assignment.all() assignment_pks = [a.pk for a in assignments] for student in students: # Set the grades following the order specified by assignment_pks grades = student.get_grades() by_assignment_pk = dict([(g.assignment_pk, g) for g in grades]) student.grades = [by_assignment_pk.get(pk) for pk in assignment_pks] return render_template( "gradebook.html", assignments=assignments, students=students )
def log_out_all_students(self, lesson=None, write_response=True): assert self.is_teacher, "Must be logged in as teacher" if lesson is None: allLessonsForAllTeachers = self.request.get("which_lessons", "0") == "1" if allLessonsForAllTeachers: assert self.is_teacher and self.person.admin, "Must be admin to logout students from all lessons for all teachers." from model import Student if lesson is not None: students = tuple(Student.all().filter("lesson =", lesson)) elif allLessonsForAllTeachers: students = Student.all() else: students = tuple(Student.all().filter("teacher =", self.person)) for student in students: if student.is_logged_in or len(student.client_ids) > 0: from helpers import log log("Teacher logged out {0} from lesson {1}".format(student.nickname, student.lesson.lesson_code)) self.log_out_student(student, False) if write_response: self.write_response_plain_text("OK")
def assignment_grades_update(assignment_pk): assignment = Assignment.get(pk=assignment_pk) students = Student.all() grades = assignment.get_grades() # We decorate the student's with their grades. # Ideally, this would be done with a select_related type thing in the # model. At the SQL level. TODO g_by_student_pk = dict([(grade.student_pk, grade) for grade in grades]) for s in students: s.grade = g_by_student_pk.get(s.pk) if request.method == 'GET': return render_template("assignment_grades_update.html", assignment=assignment, students=students) # TODO: This POSt method seems cumbersome. Can it be fixed? if request.method == 'POST': for student in students: # These keys are first generated in the template as input tag # name attributes. points_key = "student_{0}_points".format(student.pk) comment_key = "student_{0}_comment".format(student.pk) try: points = request.form[points_key].strip() comment = request.form[comment_key].strip() except KeyError: # This will prevent a 400 status code from being returned if we # try to get data from the form about a student that didn't # exist when the form was created. continue try: points = int(points.strip()) except ValueError: points = None comment = comment.strip() if student.grade is None: student.grade = Grade(student_pk=student.pk, assignment_pk=assignment.pk, points=points, comment=comment) else: student.grade.points = points student.grade.comment = comment student.grade.save() return redirect(url_for('assignment_view', assignment_pk=assignment_pk))
def public_gradebook(): students = Student.all(order='alias') assignments = [a for a in Assignment.all() if a.is_public] for student in students: # Set the grades following the order specified by assignment_pks grades = student.get_grades() grades_by_assignment_pk = dict([(g.assignment_pk, g) for g in grades]) student.points_by_assignment_pk = {} for assignment in assignments: grade = grades_by_assignment_pk.get(assignment.pk) if grade: grade.assignment = assignment points = grade.points if grade else 0 student.points_by_assignment_pk[assignment.pk] = points student.grades = grades student.has_comments = any((grade.comment for grade in grades)) now = datetime.now() return render_template("public_gradebook.html", assignments=assignments, students=students, now=now)
def students(): students = Student.all() return render_template('student_list.html', students=students)
def displayStudents(): all_students = Student.all() return render_template('studentlist.html', rows=all_students)
def make_student_structure(self, lesson, student=None): # If student is None, then this will return info for all students who # worked on this lesson. from model import Student, StudentActivity if student is not None: students = (student,) filter_key = "student =" filter_value = student else: students = tuple( Student.all().filter("lesson =", lesson) ) # PERFORMANCE: Generator might be inefficient filter_key = "lesson =" filter_value = lesson student_structure = {} if len(students) > 0: num_tasks = len(lesson.tasks) for student in students: tasks_info = [{"searches":[], "answer":{"text":"", "explanation":""}, "history":[]} for _ in range(num_tasks)] student_structure[student.nickname] = { "task_idx" : student.task_idx, "logged_in" : student.is_logged_in, "tasks" : tasks_info } # Policy: Don't report same (query,student,task_idx) more than once. # This dictionary enforces that. searches_dict = {} # (student_nickname,task_idx,link_url) -> ([link_info,...], is_helpful) link_infos_and_ratings = {} activities = StudentActivity.fetch_all(filter_key, filter_value) for activity in activities: student_nickname = activity.student.nickname task_idx = activity.task_idx activity_type = activity.activity_type if activity_type in (StudentActivity.ACTIVITY_TYPE_LINK, StudentActivity.ACTIVITY_TYPE_LINK_RATING, StudentActivity.ACTIVITY_TYPE_SEARCH): link_url = activity.link key = (student_nickname,task_idx,link_url) link_infos_and_rating = link_infos_and_ratings.setdefault(key, [[],None]) if activity_type in (StudentActivity.ACTIVITY_TYPE_LINK, StudentActivity.ACTIVITY_TYPE_SEARCH): query = activity.search search_key = (student_nickname, task_idx, query) try: search_info = searches_dict[search_key] except KeyError: search_info = {"query":query, "links_followed":[]} student_structure[student_nickname]["tasks"][task_idx]["searches"].append(search_info) searches_dict[search_key] = search_info if activity_type==StudentActivity.ACTIVITY_TYPE_LINK: link_title = activity.link_title link_info = {"url":link_url, "title":link_title, "is_helpful":None} search_info["links_followed"].append(link_info) link_infos_and_rating[0].append(link_info) elif activity_type==StudentActivity.ACTIVITY_TYPE_LINK_RATING: link_infos_and_rating[1] = activity.is_helpful elif activity_type==StudentActivity.ACTIVITY_TYPE_ANSWER: # This will end up with the most recent answer because it is in ascending time order, so # later answers will overwrite the older ones. answer_info = student_structure[student_nickname]["tasks"][task_idx]["answer"] answer_info["text"] = activity.answer_text answer_info["explanation"] = activity.answer_explanation student_structure[student_nickname]["tasks"][task_idx]["history"].append(activity) for k,v in link_infos_and_ratings.items(): (student_nickname,task_idx,link_url) = k link_infos, is_helpful = v for link_info in link_infos: link_info["is_helpful"] = is_helpful return student_structure
def _attempt_to_identify_as_student(self): from model import Student from helpers import log # Initialize student # We still store changes to student record only, if any, but we don't want to store # the record needlessly, since that consumes billable resources. student = None student_is_dirty = False # There are two ways to identify a student: nickname + lesson code sent via CGI, # or the session ID. We will try them in that order. # Get CGI form values lesson_code = self.request.get("lesson_code", None) student_nickname = self.request.get("student_nickname", None) if lesson_code is not None and student_nickname is not None: # 1. Fetch student by nickname+lesson student_nickname = self.htmlunquote(student_nickname) key_name = Student.make_key_name(student_nickname=student_nickname, lesson_code=lesson_code) student = Student.get_by_key_name(key_name) log("=> SEARCHING BY NAME AND LESSON CODE: {0}, {1}, {2}".format(student_nickname, lesson_code, key_name)) if student is not None and self.session.sid != student.session_sid: if student.is_logged_in: # Prevent login if student already logged in to another session # GAE limits # of channels so we don't want to allow too many student windows from all_exceptions import StudentLoginException raise StudentLoginException( "Please choose another name. Someone is already logged in as %s." % (student_nickname.encode("ascii", "xmlcharrefreplace")), "Session ID doesn't match.", student.session_sid, self.session.sid, student.latest_login_timestamp, student.latest_logout_timestamp, ) # else: # # Need to update session id if student was logged into another browser previously (and then logged out) # student.session_sid = self.session.sid # student_is_dirty = True else: # 2. Fetch student by session id student = Student.all().filter("session_sid =", self.session.sid).get() log("=> SEARCHING FOR STUDENT BY SESSION ID {0}".format(self.session.sid)) if student is not None and not student.is_logged_in: # Passively log student in again. # At some point this student logged into this browser but logged out passively. from datetime import datetime student.latest_login_timestamp = datetime.now() student.latest_logout_timestamp = None student_is_dirty = True log("=> PASSIVE STUDENT LOGIN AFTER PASSIVE LOGOUT") if student_is_dirty: # Store changes to student record, if any. student.put() if student is not None and not student.is_logged_in: log("=> STUDENT IS **NOT** LOGGED IN") return student