refactor: restructure codebase into modular architecture
- Split monolithic app.py (400+ lines) into organized modules - Extract models, forms, and commands into separate files - Implement Flask blueprints for route organization - Maintain full functionality with cleaner architecture - Update all templates to use new blueprint URLs - Enhance README with technical documentation Structure: ├── app.py (50 lines) - Flask app factory ├── models.py (62 lines) - SQLAlchemy models ├── forms.py (43 lines) - WTForms definitions ├── commands.py (74 lines) - CLI commands └── routes/ - Blueprint modules for each feature 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
		
							
								
								
									
										78
									
								
								routes/grading.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								routes/grading.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| from flask import Blueprint, render_template, redirect, url_for, flash, request | ||||
| from models import db, Assessment, Student, Grade, GradingElement, Exercise | ||||
|  | ||||
| bp = Blueprint('grading', __name__) | ||||
|  | ||||
| @bp.route('/assessments/<int:assessment_id>/grading') | ||||
| def assessment_grading(assessment_id): | ||||
|     assessment = Assessment.query.get_or_404(assessment_id) | ||||
|     students = Student.query.filter_by(class_group_id=assessment.class_group_id).order_by(Student.last_name, Student.first_name).all() | ||||
|      | ||||
|     # Get all grading elements for this assessment | ||||
|     grading_elements = [] | ||||
|     for exercise in assessment.exercises: | ||||
|         for element in exercise.grading_elements: | ||||
|             grading_elements.append(element) | ||||
|      | ||||
|     # Get existing grades | ||||
|     existing_grades = {} | ||||
|     for grade in Grade.query.join(GradingElement).join(Exercise).filter_by(assessment_id=assessment_id).all(): | ||||
|         key = f"{grade.student_id}_{grade.grading_element_id}" | ||||
|         existing_grades[key] = grade | ||||
|      | ||||
|     return render_template('assessment_grading.html',  | ||||
|                          assessment=assessment,  | ||||
|                          students=students,  | ||||
|                          grading_elements=grading_elements, | ||||
|                          existing_grades=existing_grades) | ||||
|  | ||||
| @bp.route('/assessments/<int:assessment_id>/grading/save', methods=['POST']) | ||||
| def save_grades(assessment_id): | ||||
|     assessment = Assessment.query.get_or_404(assessment_id) | ||||
|      | ||||
|     for key, value in request.form.items(): | ||||
|         if key.startswith('grade_'): | ||||
|             # Parse key: grade_<student_id>_<element_id> | ||||
|             parts = key.split('_') | ||||
|             if len(parts) == 3: | ||||
|                 student_id = int(parts[1]) | ||||
|                 element_id = int(parts[2]) | ||||
|                  | ||||
|                 # Find or create grade | ||||
|                 grade = Grade.query.filter_by( | ||||
|                     student_id=student_id, | ||||
|                     grading_element_id=element_id | ||||
|                 ).first() | ||||
|                  | ||||
|                 if value.strip():  # If value is not empty | ||||
|                     if not grade: | ||||
|                         grade = Grade( | ||||
|                             student_id=student_id, | ||||
|                             grading_element_id=element_id, | ||||
|                             value=value | ||||
|                         ) | ||||
|                         db.session.add(grade) | ||||
|                     else: | ||||
|                         grade.value = value | ||||
|                 elif grade:  # If value is empty but grade exists, delete it | ||||
|                     db.session.delete(grade) | ||||
|      | ||||
|     # Handle comments | ||||
|     for key, value in request.form.items(): | ||||
|         if key.startswith('comment_'): | ||||
|             parts = key.split('_') | ||||
|             if len(parts) == 3: | ||||
|                 student_id = int(parts[1]) | ||||
|                 element_id = int(parts[2]) | ||||
|                  | ||||
|                 grade = Grade.query.filter_by( | ||||
|                     student_id=student_id, | ||||
|                     grading_element_id=element_id | ||||
|                 ).first() | ||||
|                  | ||||
|                 if grade: | ||||
|                     grade.comment = value.strip() if value.strip() else None | ||||
|      | ||||
|     db.session.commit() | ||||
|     flash('Notes sauvegardées avec succès !', 'success') | ||||
|     return redirect(url_for('grading.assessment_grading', assessment_id=assessment_id)) | ||||
		Reference in New Issue
	
	Block a user