def cal_page(): """课表导出页面视图函数""" from everyclass.server.calendar import ics_generator from everyclass.server.db.dao import get_classes_for_student, get_my_semesters, check_if_stu_exist from everyclass.server.db.model import Semester # 如果请求中包含 id 就写入 session if request.values.get('id'): if not check_if_stu_exist(request.values.get('id')): flash("你输入的学号不存在") return redirect(url_for("main.main")) session['stu_id'] = request.values.get('id') # 如果 session 中有 stu_id 就生成 ics 并返回页面,没有就跳转回首页 if session.get('stu_id', None): # 获得学生姓名和他的合法学期 my_available_semesters, student_name = get_my_semesters( session['stu_id']) semester = Semester.get() student_classes = get_classes_for_student(session['stu_id'], semester) ics_generator.generate(session['stu_id'], student_name, student_classes, semester.to_str(simplify=True), semester.to_tuple()) return render_template('ics.html', student_id=session['stu_id'], semester=semester.to_str(simplify=True)) else: return redirect(url_for('main.main'))
def get_semesters(student_id): """ 提供学号,返回一个学生可用的学期。 :param student_id: 学号 """ from everyclass.server.db.dao import get_my_semesters # todo: handle if student doesn't exist semesters, student_name = get_my_semesters(student_id) # Elastic apm 业务 context elasticapm.set_custom_context(stu_id=student_id) response = jsonify({'name': student_name, 'semesters': [s.to_str() for s in semesters] }) return response
def get_ics(student_id, semester_str): """ iCalendar service """ from everyclass.server.calendar import ics_generator from everyclass.server.db.dao import check_if_stu_exist, get_my_semesters, get_classes_for_student from everyclass.server.db.model import Semester from everyclass.server.exceptions import IllegalSemesterException from everyclass.server import logger # TODO: generate ics here and return it to user, instead of generating .ics files in other places. # 临时 fix place = student_id.find('-') semester_str = student_id[place + 1:len(student_id)] + '-' + semester_str student_id = student_id[:place] # 学号检测 if not check_if_stu_exist(student_id): flash("{} 学号不存在".format(student_id)) logger.warning("[ics] {} 学号不存在".format(student_id)) return redirect(url_for("main.main")) # 学期检测 my_available_semesters, student_name = get_my_semesters(student_id) try: semester = Semester(semester_str) except IllegalSemesterException: flash("{} 学期格式错误".format(semester_str)) logger.warning("{} 学期格式错误".format(semester_str)) return redirect(url_for("main.main")) if semester not in my_available_semesters: flash("{} 学期不适用于此学生".format(semester_str)) logger.warning("{} 学期不适用于此学生".format(semester_str)) return redirect(url_for("main.main")) student_classes = get_classes_for_student(student_id, semester) ics_generator.generate(student_id, student_name, student_classes, semester.to_str(simplify=True), semester.to_tuple()) return send_from_directory("../../calendar_files", student_id + "-" + semester_str + ".ics", as_attachment=True, mimetype='text/calendar')
def get(): """ 获取当前学期。进入此模块前必须保证 session 内有 stu_id。 当 url 中没有显式表明 semester 时,不设置 session,而是在这里设置默认值。 """ from everyclass.server.exceptions import IllegalSemesterException from everyclass.server.config import get_config config = get_config() my_available_semesters = get_my_semesters(session.get('stu_id'))[0] if config.DEBUG: print('[model.Semester.get()] my_available_semesters:', my_available_semesters) # 如果 session 中包含学期信息且有效 if session.get('semester', None) and session.get( 'semester', None) in my_available_semesters: if config.DEBUG: print('[model.Semester.get()]have valid session') return Semester(session['semester']) # 如果没有 session或session无效 else: if config.DEBUG: print('[model.Semester.get()] no session or invalid session') # 选择对本人有效的最后一个学期 if my_available_semesters: if config.DEBUG: print( '[model.Semester.get()] choose last available semester' ) return my_available_semesters[-1] # 如果本人没有一个有效学期,则引出IllegalSemesterException else: raise IllegalSemesterException( 'No any available semester for this student')
def query(): """ 查询本人课表视图函数 正常情况应该是 post 方法,但是也兼容 get 防止意外情况,提高用户体验 """ from flask import request, render_template, redirect, url_for, session from flask import current_app as app import elasticapm from everyclass.server.tools import is_chinese_char from everyclass.server.exceptions import NoStudentException, IllegalSemesterException from everyclass.server.db.mysql import get_local_conn from everyclass.server.db.dao import faculty_lookup from everyclass.server.db.dao import class_lookup from everyclass.server.db.dao import get_classes_for_student from everyclass.server.db.model import Semester from everyclass.server.db.dao import get_privacy_settings from everyclass.server.db.dao import get_my_semesters from everyclass.server.db.dao import check_if_stu_exist # if under maintenance, return to maintenance.html if app.config["MAINTENANCE"]: return render_template("maintenance.html") db = get_local_conn() cursor = db.cursor() # 如 URL 中有 id 参数,判断是姓名还是学号,然后赋学号给student_id if request.values.get('id'): id_or_name = request.values.get('id') # 首末均为中文,判断为人名 if is_chinese_char(id_or_name[0:1]) and is_chinese_char( id_or_name[-1:]): # 使用人名查询打点 elasticapm.tag(ec_query_method='by_name') mysql_query = "SELECT name,xh FROM ec_students WHERE name=%s" cursor.execute(mysql_query, (id_or_name, )) result = cursor.fetchall() if cursor.rowcount > 1: # 查询到多个同名,进入选择界面 students_list = list() for each_student in result: students_list.append([ each_student[0], each_student[1], faculty_lookup(each_student[1]), class_lookup(each_student[1]) ]) return render_template("query_same_name.html", count=cursor.rowcount, student_info=students_list) elif cursor.rowcount == 1: # 仅能查询到一个人,则赋值学号 student_id = result[0][1] else: # 查无此人 elasticapm.tag(ec_query_not_found=True) return _no_student_handle(id_or_name) # id 不为中文,则为学号 else: # 学号查询打点 elasticapm.tag(ec_query_method='by_id') student_id = request.values.get('id') # 判断学号是否有效 if not check_if_stu_exist(student_id): elasticapm.tag(ec_query_not_found=True) return _no_student_handle(student_id) # 写入 session 的学号一定有效 session['stu_id'] = student_id # url 中没有 id 参数但 session 中有 elif session.get('stu_id', None): elasticapm.tag(ec_query_method='by_session') student_id = session['stu_id'] # 既没有 id 参数也没有 session,无法知道需要查询谁的课表,返回主页 else: elasticapm.tag(ec_query_method='exception') return redirect(url_for('main.main')) # 查询学生本人的可用学期 my_available_semesters, student_name = get_my_semesters(student_id) # 如果没有学期,则直接返回 if not my_available_semesters: logger.warning('Not any semester in ec_student', stack=True) return _no_student_handle() # 如URL参数中包含学期,判断有效性后更新 session if request.values.get('semester'): try: sem = Semester(request.values.get('semester')) if sem in my_available_semesters: session['semester'] = sem.to_tuple() if app.config['DEBUG']: print('[query.query] updated session semester to', Semester(session['semester']).to_str()) # 用户指定的学期格式不合法 except IllegalSemesterException: if app.config['DEBUG']: print('[query.query] IllegalSemesterException handled.' + Semester(session['semester']).to_str()) session['semester'] = my_available_semesters[-1].to_tuple() cursor.close() # 关闭数据库连接 # 如果 session 中无学期或学期无效,回落到本人可用最新学期 # session 中学期使用 tuple 保存,因为 Semester 对象无法被序列化 semester = session.get('semester', None) if not semester or Semester(semester) not in my_available_semesters: session['semester'] = my_available_semesters[-1].to_tuple() try: student_classes = get_classes_for_student(student_id=student_id, sem=Semester( session['semester'])) except NoStudentException: return _no_student_handle(student_id) else: # 空闲周末判断,考虑到大多数人周末都是没有课程的 empty_weekend = True for cls_time in range(1, 7): for cls_day in range(6, 8): if (cls_day, cls_time) in student_classes: empty_weekend = False # 空闲课程判断,考虑到大多数人11-12节都是没有课程的 empty_6 = True for cls_day in range(1, 8): if (cls_day, 6) in student_classes: empty_6 = False empty_5 = True for cls_day in range(1, 8): if (cls_day, 5) in student_classes: empty_5 = False # available_semesters 为当前学生所能选择的学期,是一个list。 # 当中每一项又是一个包含两项的list,第一项为学期string,第二项为True/False表示是否为当前学期。 available_semesters = [] for each_semester in my_available_semesters: if session['semester'] == each_semester: available_semesters.append([each_semester, True]) else: available_semesters.append([each_semester, False]) # Privacy settings # Available privacy settings: "show_table_on_page", "import_to_calender", "major" privacy_settings = get_privacy_settings(student_id) # privacy on if "show_table_on_page" in privacy_settings: return render_template( 'blocked.html', name=student_name, falculty=faculty_lookup(student_id), class_name=class_lookup(student_id), stu_id=student_id, available_semesters=available_semesters, no_import_to_calender=True if "import_to_calender" in privacy_settings else False) # privacy off return render_template('query.html', name=student_name, falculty=faculty_lookup(student_id), class_name=class_lookup(student_id), stu_id=student_id, classes=student_classes, empty_wkend=empty_weekend, empty_6=empty_6, empty_5=empty_5, available_semesters=available_semesters)