查询出dd(user_id,class_no,score)这个表中平均分最低的班级?

本文提供了一个MySQL数据库操作示例,包括创建表、插入数据及使用GROUP BY进行分组查询来计算各班级平均分数的方法。

 

 

 

 

 

 

 

 

 


在MySQL下面测试通过。


按照以下内容一、学生端功能闭环(避免漏操作) 1. 新增“未提交作业查询接口”:学生能查看所有“未截止且未提交”的作业,按截止时间倒序排序(优先显示快截止的),避免漏做。需关联 Assignment 和 Submission ,筛选“学生未提交”的作业。 2. 提交作业支持“重新提交”:当前重复提交直接拦截,可改为允许覆盖(需提示“重新提交会覆盖原分数”),满足学生修改答案的需求,只需在 submit_assignment 接口中,若存在旧提交则更新 answer 和 score,而非创建新记录。 二、老师端教学辅助(提升管理效率) 1. 作业详情补充“提交率统计”:在老师查看作业列(view_assignments)时,增加“已提交人数/总学生数”“提交率”字段(如“30/50,60%”),方便老师快速掌握作业完成情况。 2. 新增“人工复评接口”:老师可修改系统评分并添加评语,需在 Submission 加 teacher_comment 字段,同时新增接口允许老师传入 submission_id、new_score、comment 进行更新。 三、数据与体验细节(降低使用门槛) 1. MusicXML返回优化:当前 convert_and_grade 可能返回 None,需在接口中判断,若为 None 则返回“简谱格式错误,无法生成五线谱”的友好提示,避免前端接收异常数据。 2. 作业内容支持“音频链接存储”:当前 Assignment.content 可存储音频文件路径(如 /audio/melody1.mid),需新增“获取作业音频接口”(如 /assignments/<<int:assignment_id>/audio),返回音频文件流,学生做题时可直接播放(无需手动上传)。 3. 接口返回“格式化时间”:所有涉及时间的字段(如作业截止时间、提交时间),统一返回格式化字符串(如 2025-12-31 23:59:59),避免前端处理 datetime 类型数据错。 四、部署前安全收尾(避免线上风险) 1. 关闭Debug模式:线上部署时需将 app.run(debug=True) 改为 app.run(debug=False),并配置 app.config['SECRET_KEY'](随机字符串),避免暴露代码和敏感信息。 2. 音频文件权限控制:若后端托管音频文件,需在“获取音频接口”中加Token校验,确保只有已登录用户能访问,避免音频文件被非法下载。修改一下代码,然后给我完整版代码from flask import Flask, request, jsonify, make_response from flask_sqlalchemy import SQLAlchemy from music21 import converter, note, stream, pitch import datetime from werkzeug.security import generate_password_hash, check_password_hash import re from functools import wraps app = Flask(__name__) # 需自行修改数据库连接信息 app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///music_app.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) # 用户模型 class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) password = db.Column(db.String(120), nullable=False) role = db.Column(db.String(20), nullable=False) # 'teacher' or 'student' def set_password(self, password): # 密码强度校验 if not re.match(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$', password): raise ValueError("Password must be at least 8 characters long and contain at least one uppercase letter, one lowercase letter, and one digit.") self.password = generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password, password) # 作业模型 class Assignment(db.Model): id = db.Column(db.Integer, primary_key=True) teacher_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) title = db.Column(db.String(200), nullable=False) content = db.Column(db.Text, nullable=False) deadline = db.Column(db.DateTime, nullable=False) answer = db.Column(db.Text, nullable=False) assignment_type = db.Column(db.String(50), nullable=False) # 新增作业类型字段 # 学生提交作业模型 class Submission(db.Model): id = db.Column(db.Integer, primary_key=True) student_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) assignment_id = db.Column(db.Integer, db.ForeignKey('assignment.id'), nullable=False) answer = db.Column(db.Text, nullable=False) score = db.Column(db.Float) # 权限验证装饰器 def token_required(f): @wraps(f) def decorated(*args, **kwargs): token = None if 'x-access-token' in request.headers: token = request.headers['x-access-token'] if not token: return jsonify({'message': 'Token is missing!'}), 401 try: user = User.query.filter_by(id=token).first() if not user: return jsonify({'message': 'Invalid token!'}), 401 except: return jsonify({'message': 'Invalid token!'}), 401 return f(user, *args, **kwargs) return decorated # 注册接口 @app.route('/register', methods=['POST']) def register(): data = request.get_json() username = data.get('username') password = data.get('password') role = data.get('role') if not username or not password or not role: return jsonify({"message": "Missing required fields"}), 400 if User.query.filter_by(username=username).first(): return jsonify({"message": "Username already exists"}), 400 new_user = User(username=username, role=role) try: new_user.set_password(password) except ValueError as e: return jsonify({"message": str(e)}), 400 db.session.add(new_user) db.session.commit() return jsonify({"message": "User registered successfully"}), 201 # 登录接口 @app.route('/login', methods=['POST']) def login(): data = request.get_json() username = data.get('username') password = data.get('password') user = User.query.filter_by(username=username).first() if user and user.check_password(password): return jsonify({"message": "Login successful", "role": user.role, "x-access-token": user.id}), 200 else: return jsonify({"message": "Invalid username or password"}), 401 # 老师布置作业接口 @app.route('/assignments', methods=['POST']) @token_required def create_assignment(user): if user.role != 'teacher': return jsonify({"message": "Only teachers can create assignments"}), 403 data = request.get_json() teacher_id = user.id title = data.get('title') content = data.get('content') deadline_str = data.get('deadline') answer = data.get('answer') assignment_type = data.get('assignment_type') # 获取作业类型 if not title or not content or not deadline_str or not answer or not assignment_type: return jsonify({"message": "Missing required fields"}), 400 try: deadline = datetime.datetime.strptime(deadline_str, '%Y-%m-%d %H:%M:%S') except ValueError: return jsonify({"message": "Invalid deadline format. Use 'YYYY-MM-DD HH:MM:SS'"}), 400 new_assignment = Assignment(teacher_id=teacher_id, title=title, content=content, deadline=deadline, answer=answer, assignment_type=assignment_type) db.session.add(new_assignment) db.session.commit() return jsonify({"message": "Assignment created successfully"}), 201 # 学生提交作业接口 @app.route('/submissions', methods=['POST']) @token_required def submit_assignment(user): if user.role != 'student': return jsonify({"message": "Only students can submit assignments"}), 403 data = request.get_json() student_id = user.id assignment_id = data.get('assignment_id') answer = data.get('answer') if not assignment_id or not answer: return jsonify({"message": "Missing required fields"}), 400 assignment = Assignment.query.get(assignment_id) if not assignment: return jsonify({"message": "Assignment not found"}), 404 if datetime.datetime.now() > assignment.deadline: return jsonify({"message": "Assignment deadline has passed"}), 400 # 重复提交控制 existing_submission = Submission.query.filter_by(student_id=student_id, assignment_id=assignment_id).first() if existing_submission: return jsonify({"message": "You have already submitted this assignment"}), 400 # 自动批阅 score = 0 if answer == assignment.answer: score = 100 new_submission = Submission(student_id=student_id, assignment_id=assignment_id, answer=answer, score=score) db.session.add(new_submission) db.session.commit() musicxml, _ = convert_and_grade(answer, assignment.answer) return jsonify({"message": "Assignment submitted successfully", "score": score, "musicxml": musicxml}), 201 # 老师查看学生作业情况接口 @app.route('/teachers/<int:teacher_id>/submissions', methods=['GET']) @token_required def view_submissions(user, teacher_id): if user.role != 'teacher' or user.id != teacher_id: return jsonify({"message": "You are not authorized to view these submissions"}), 403 page = request.args.get('page', 1, type=int) per_page = request.args.get('per_page', 10, type=int) assignments = Assignment.query.filter_by(teacher_id=teacher_id).paginate(page=page, per_page=per_page, error_out=False) submissions = [] for assignment in assignments.items: sub_list = Submission.query.filter_by(assignment_id=assignment.id).all() for sub in sub_list: student = User.query.get(sub.student_id) submissions.append({ "assignment_title": assignment.title, "student_username": student.username, "answer": sub.answer, "score": sub.score }) return jsonify(submissions), 200 # 学生查看自己的作业/提交记录接口 @app.route('/students/<int:student_id>/submissions', methods=['GET']) @token_required def view_student_submissions(user, student_id): if user.role != 'student' or user.id != student_id: return jsonify({"message": "You are not authorized to view these submissions"}), 403 page = request.args.get('page', 1, type=int) per_page = request.args.get('per_page', 10, type=int) submissions = Submission.query.filter_by(student_id=student_id).paginate(page=page, per_page=per_page, error_out=False) result = [] for sub in submissions.items: assignment = Assignment.query.get(sub.assignment_id) result.append({ "assignment_title": assignment.title, "answer": sub.answer, "score": sub.score }) return jsonify(result), 200 # 简谱转五线谱并批阅(扩展支持高低音和休止符) def convert_and_grade(jianpu, answer): try: s = stream.Stream() for note_str in jianpu.split(): if note_str == '0': # 处理休止符 n = note.Rest() else: # 处理高低音,这里简单示例,实际可能需要更复杂处理 # 假设高音用 '+' 后缀,低音用 '-' 后缀 if note_str.endswith('+'): n = note.Note(note_str[:-1]) n.octave += 1 elif note_str.endswith('-'): n = note.Note(note_str[:-1]) n.octave -= 1 else: n = note.Note(note_str) s.append(n) # 简单评分逻辑,可根据需求扩展 correct_count = sum([1 for i, j in zip(jianpu.split(), answer.split()) if i == j]) total_count = len(answer.split()) score = (correct_count / total_count) * 100 if total_count > 0 else 0 return s.write('musicxml'), score except Exception as e: return None, 0 # 老师查询作业接口,可按类型分类 @app.route('/teachers/<int:teacher_id>/assignments', methods=['GET']) @token_required def view_assignments(user, teacher_id): if user.role != 'teacher' or user.id != teacher_id: return jsonify({"message": "You are not authorized to view these assignments"}), 403 assignment_type = request.args.get('assignment_type') if assignment_type: assignments = Assignment.query.filter_by(teacher_id=teacher_id, assignment_type=assignment_type).all() else: assignments = Assignment.query.filter_by(teacher_id=teacher_id).all() result = [] for assignment in assignments: result.append({ "id": assignment.id, "title": assignment.title, "content": assignment.content, "deadline": assignment.deadline.strftime('%Y-%m-%d %H:%M:%S'), "answer": assignment.answer, "assignment_type": assignment.assignment_type }) return jsonify(result), 200 # 成绩统计接口 @app.route('/teachers/<int:teacher_id>/statistics', methods=['GET']) @token_required def view_statistics(user, teacher_id): if user.role != 'teacher' or user.id != teacher_id: return jsonify({"message": "You are not authorized to view these statistics"}), 403 assignments = Assignment.query.filter_by(teacher_id=teacher_id).all() total_students = User.query.filter_by(role='student').count() total_assignments = len(assignments) total_submissions = 0 average_score = 0 for assignment in assignments: sub_list = Submission.query.filter_by(assignment_id=assignment.id).all() total_submissions += len(sub_list) scores = [sub.score for sub in sub_list] if scores: average_score += sum(scores) / len(scores) if total_assignments > 0: average_score /= total_assignments return jsonify({ "total_students": total_students, "total_assignments": total_assignments, "total_submissions": total_submissions, "average_score": average_score }), 200 if __name__ == '__main__': with app.app_context(): db.create_all() app.run(debug=True)
最新发布
10-13
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值