Files
notytex/routes/exercises.py
Bertrand Benjamin 3e49bd467c 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>
2025-08-03 20:59:10 +02:00

113 lines
5.6 KiB
Python

from flask import Blueprint, render_template, redirect, url_for, flash, request
from models import db, Assessment, Exercise, GradingElement
from forms import ExerciseForm, GradingElementForm
bp = Blueprint('exercises', __name__)
# Exercise routes
@bp.route('/assessments/<int:assessment_id>/exercises/new', methods=['GET', 'POST'])
def new(assessment_id):
assessment = Assessment.query.get_or_404(assessment_id)
form = ExerciseForm()
# Set default order to next available
if form.order.data == 1: # Only if it's the default value
max_order = db.session.query(db.func.max(Exercise.order)).filter_by(assessment_id=assessment_id).scalar()
form.order.data = (max_order or 0) + 1
if form.validate_on_submit():
exercise = Exercise(
assessment_id=assessment_id,
title=form.title.data,
description=form.description.data,
order=form.order.data
)
db.session.add(exercise)
db.session.commit()
flash('Exercice créé avec succès !', 'success')
return redirect(url_for('exercises.detail', assessment_id=assessment_id, id=exercise.id))
return render_template('exercise_form.html', form=form, assessment=assessment, title='Nouvel exercice')
@bp.route('/assessments/<int:assessment_id>/exercises/<int:id>')
def detail(assessment_id, id):
assessment = Assessment.query.get_or_404(assessment_id)
exercise = Exercise.query.filter_by(id=id, assessment_id=assessment_id).first_or_404()
return render_template('exercise_detail.html', assessment=assessment, exercise=exercise)
@bp.route('/assessments/<int:assessment_id>/exercises/<int:id>/edit', methods=['GET', 'POST'])
def edit(assessment_id, id):
assessment = Assessment.query.get_or_404(assessment_id)
exercise = Exercise.query.filter_by(id=id, assessment_id=assessment_id).first_or_404()
form = ExerciseForm(obj=exercise)
if form.validate_on_submit():
exercise.title = form.title.data
exercise.description = form.description.data
exercise.order = form.order.data
db.session.commit()
flash('Exercice modifié avec succès !', 'success')
return redirect(url_for('exercises.detail', assessment_id=assessment_id, id=exercise.id))
return render_template('exercise_form.html', form=form, assessment=assessment, exercise=exercise, title='Modifier l\'exercice')
@bp.route('/assessments/<int:assessment_id>/exercises/<int:id>/delete', methods=['POST'])
def delete(assessment_id, id):
assessment = Assessment.query.get_or_404(assessment_id)
exercise = Exercise.query.filter_by(id=id, assessment_id=assessment_id).first_or_404()
db.session.delete(exercise)
db.session.commit()
flash('Exercice supprimé avec succès !', 'success')
return redirect(url_for('assessments.detail', id=assessment_id))
# GradingElement routes
@bp.route('/assessments/<int:assessment_id>/exercises/<int:exercise_id>/elements/new', methods=['GET', 'POST'])
def new_grading_element(assessment_id, exercise_id):
assessment = Assessment.query.get_or_404(assessment_id)
exercise = Exercise.query.filter_by(id=exercise_id, assessment_id=assessment_id).first_or_404()
form = GradingElementForm()
if form.validate_on_submit():
element = GradingElement(
exercise_id=exercise_id,
label=form.label.data,
description=form.description.data,
skill=form.skill.data,
max_points=form.max_points.data,
grading_type=form.grading_type.data
)
db.session.add(element)
db.session.commit()
flash('Élément de notation créé avec succès !', 'success')
return redirect(url_for('exercises.detail', assessment_id=assessment_id, id=exercise_id))
return render_template('grading_element_form.html', form=form, assessment=assessment, exercise=exercise, title='Nouvel élément de notation')
@bp.route('/assessments/<int:assessment_id>/exercises/<int:exercise_id>/elements/<int:id>/edit', methods=['GET', 'POST'])
def edit_grading_element(assessment_id, exercise_id, id):
assessment = Assessment.query.get_or_404(assessment_id)
exercise = Exercise.query.filter_by(id=exercise_id, assessment_id=assessment_id).first_or_404()
element = GradingElement.query.filter_by(id=id, exercise_id=exercise_id).first_or_404()
form = GradingElementForm(obj=element)
if form.validate_on_submit():
element.label = form.label.data
element.description = form.description.data
element.skill = form.skill.data
element.max_points = form.max_points.data
element.grading_type = form.grading_type.data
db.session.commit()
flash('Élément de notation modifié avec succès !', 'success')
return redirect(url_for('exercises.detail', assessment_id=assessment_id, id=exercise_id))
return render_template('grading_element_form.html', form=form, assessment=assessment, exercise=exercise, element=element, title='Modifier l\'élément de notation')
@bp.route('/assessments/<int:assessment_id>/exercises/<int:exercise_id>/elements/<int:id>/delete', methods=['POST'])
def delete_grading_element(assessment_id, exercise_id, id):
assessment = Assessment.query.get_or_404(assessment_id)
exercise = Exercise.query.filter_by(id=exercise_id, assessment_id=assessment_id).first_or_404()
element = GradingElement.query.filter_by(id=id, exercise_id=exercise_id).first_or_404()
db.session.delete(element)
db.session.commit()
flash('Élément de notation supprimé avec succès !', 'success')
return redirect(url_for('exercises.detail', assessment_id=assessment_id, id=exercise_id))