192 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from flask import Flask, render_template, request, redirect, url_for, flash, jsonify
 | |
| from flask_sqlalchemy import SQLAlchemy
 | |
| from flask_wtf import FlaskForm
 | |
| from wtforms import StringField, TextAreaField, FloatField, SelectField, DateField, IntegerField
 | |
| from wtforms.validators import DataRequired, Email, NumberRange, Optional
 | |
| from datetime import datetime
 | |
| 
 | |
| app = Flask(__name__)
 | |
| app.config['SECRET_KEY'] = 'your-secret-key-here'
 | |
| app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///school_management.db'
 | |
| app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
 | |
| 
 | |
| db = SQLAlchemy(app)
 | |
| 
 | |
| class ClassGroup(db.Model):
 | |
|     id = db.Column(db.Integer, primary_key=True)
 | |
|     name = db.Column(db.String(100), nullable=False, unique=True)
 | |
|     description = db.Column(db.Text)
 | |
|     year = db.Column(db.String(20), nullable=False)
 | |
|     students = db.relationship('Student', backref='class_group', lazy=True)
 | |
|     assessments = db.relationship('Assessment', backref='class_group', lazy=True)
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return f'<ClassGroup {self.name}>'
 | |
| 
 | |
| class Student(db.Model):
 | |
|     id = db.Column(db.Integer, primary_key=True)
 | |
|     last_name = db.Column(db.String(100), nullable=False)
 | |
|     first_name = db.Column(db.String(100), nullable=False)
 | |
|     email = db.Column(db.String(120), unique=True)
 | |
|     class_group_id = db.Column(db.Integer, db.ForeignKey('class_group.id'), nullable=False)
 | |
|     grades = db.relationship('Grade', backref='student', lazy=True)
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return f'<Student {self.first_name} {self.last_name}>'
 | |
| 
 | |
| class Assessment(db.Model):
 | |
|     id = db.Column(db.Integer, primary_key=True)
 | |
|     title = db.Column(db.String(200), nullable=False)
 | |
|     description = db.Column(db.Text)
 | |
|     date = db.Column(db.Date, nullable=False, default=datetime.utcnow)
 | |
|     class_group_id = db.Column(db.Integer, db.ForeignKey('class_group.id'), nullable=False)
 | |
|     coefficient = db.Column(db.Float, default=1.0)
 | |
|     exercises = db.relationship('Exercise', backref='assessment', lazy=True, cascade='all, delete-orphan')
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return f'<Assessment {self.title}>'
 | |
| 
 | |
| class Exercise(db.Model):
 | |
|     id = db.Column(db.Integer, primary_key=True)
 | |
|     assessment_id = db.Column(db.Integer, db.ForeignKey('assessment.id'), nullable=False)
 | |
|     title = db.Column(db.String(200), nullable=False)
 | |
|     description = db.Column(db.Text)
 | |
|     order = db.Column(db.Integer, default=1)
 | |
|     grading_elements = db.relationship('GradingElement', backref='exercise', lazy=True, cascade='all, delete-orphan')
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return f'<Exercise {self.title}>'
 | |
| 
 | |
| class GradingElement(db.Model):
 | |
|     id = db.Column(db.Integer, primary_key=True)
 | |
|     exercise_id = db.Column(db.Integer, db.ForeignKey('exercise.id'), nullable=False)
 | |
|     label = db.Column(db.String(200), nullable=False)
 | |
|     description = db.Column(db.Text)
 | |
|     skill = db.Column(db.String(200))
 | |
|     max_points = db.Column(db.Float, nullable=False)
 | |
|     grading_type = db.Column(db.String(10), nullable=False, default='points')  # 'score' or 'points'
 | |
|     grades = db.relationship('Grade', backref='grading_element', lazy=True, cascade='all, delete-orphan')
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return f'<GradingElement {self.label}>'
 | |
| 
 | |
| class Grade(db.Model):
 | |
|     id = db.Column(db.Integer, primary_key=True)
 | |
|     student_id = db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False)
 | |
|     grading_element_id = db.Column(db.Integer, db.ForeignKey('grading_element.id'), nullable=False)
 | |
|     value = db.Column(db.String(10))  # String to handle scores (0,1,2,3,.) and points
 | |
|     comment = db.Column(db.Text)
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return f'<Grade {self.value} for {self.student.first_name}>'
 | |
| 
 | |
| @app.route('/')
 | |
| def index():
 | |
|     recent_assessments = Assessment.query.order_by(Assessment.date.desc()).limit(5).all()
 | |
|     total_students = Student.query.count()
 | |
|     total_assessments = Assessment.query.count()
 | |
|     total_classes = ClassGroup.query.count()
 | |
|     return render_template('index.html', 
 | |
|                          recent_assessments=recent_assessments,
 | |
|                          total_students=total_students,
 | |
|                          total_assessments=total_assessments,
 | |
|                          total_classes=total_classes)
 | |
| 
 | |
| @app.route('/classes')
 | |
| def classes():
 | |
|     classes = ClassGroup.query.order_by(ClassGroup.year, ClassGroup.name).all()
 | |
|     return render_template('classes.html', classes=classes)
 | |
| 
 | |
| @app.route('/students')
 | |
| def students():
 | |
|     students = Student.query.join(ClassGroup).order_by(ClassGroup.name, Student.last_name, Student.first_name).all()
 | |
|     return render_template('students.html', students=students)
 | |
| 
 | |
| @app.route('/assessments')
 | |
| def assessments():
 | |
|     assessments = Assessment.query.join(ClassGroup).order_by(Assessment.date.desc()).all()
 | |
|     return render_template('assessments.html', assessments=assessments)
 | |
| 
 | |
| @app.cli.command()
 | |
| def init_db():
 | |
|     """Initialize the database with sample data."""
 | |
|     db.create_all()
 | |
|     
 | |
|     # Check if data already exists
 | |
|     if ClassGroup.query.first():
 | |
|         print("Database already initialized!")
 | |
|         return
 | |
|     
 | |
|     # Create sample class groups
 | |
|     classe_6a = ClassGroup(name="6ème A", description="Classe de 6ème A", year="2024-2025")
 | |
|     classe_5b = ClassGroup(name="5ème B", description="Classe de 5ème B", year="2024-2025")
 | |
|     
 | |
|     db.session.add(classe_6a)
 | |
|     db.session.add(classe_5b)
 | |
|     db.session.commit()
 | |
|     
 | |
|     # Create sample students
 | |
|     students_data = [
 | |
|         ("Dupont", "Marie", "marie.dupont@email.com", classe_6a.id),
 | |
|         ("Martin", "Pierre", "pierre.martin@email.com", classe_6a.id),
 | |
|         ("Durand", "Sophie", "sophie.durand@email.com", classe_6a.id),
 | |
|         ("Moreau", "Lucas", "lucas.moreau@email.com", classe_5b.id),
 | |
|         ("Bernard", "Emma", "emma.bernard@email.com", classe_5b.id),
 | |
|     ]
 | |
|     
 | |
|     for last_name, first_name, email, class_group_id in students_data:
 | |
|         student = Student(
 | |
|             last_name=last_name,
 | |
|             first_name=first_name,
 | |
|             email=email,
 | |
|             class_group_id=class_group_id
 | |
|         )
 | |
|         db.session.add(student)
 | |
|     
 | |
|     db.session.commit()
 | |
|     
 | |
|     # Create sample assessment
 | |
|     assessment = Assessment(
 | |
|         title="Évaluation de mathématiques",
 | |
|         description="Évaluation sur les fractions et les décimaux",
 | |
|         class_group_id=classe_6a.id,
 | |
|         coefficient=2.0
 | |
|     )
 | |
|     db.session.add(assessment)
 | |
|     db.session.commit()
 | |
|     
 | |
|     # Create sample exercise
 | |
|     exercise = Exercise(
 | |
|         assessment_id=assessment.id,
 | |
|         title="Exercice 1 - Fractions",
 | |
|         description="Calculs avec les fractions",
 | |
|         order=1
 | |
|     )
 | |
|     db.session.add(exercise)
 | |
|     db.session.commit()
 | |
|     
 | |
|     # Create sample grading elements
 | |
|     elements_data = [
 | |
|         ("Calcul de base", "Addition et soustraction de fractions", "Calculer", 4.0, "points"),
 | |
|         ("Méthode", "Justification de la méthode utilisée", "Raisonner", 2.0, "score"),
 | |
|         ("Présentation", "Clarté de la présentation", "Communiquer", 2.0, "score"),
 | |
|     ]
 | |
|     
 | |
|     for label, description, skill, max_points, grading_type in elements_data:
 | |
|         element = GradingElement(
 | |
|             exercise_id=exercise.id,
 | |
|             label=label,
 | |
|             description=description,
 | |
|             skill=skill,
 | |
|             max_points=max_points,
 | |
|             grading_type=grading_type
 | |
|         )
 | |
|         db.session.add(element)
 | |
|     
 | |
|     db.session.commit()
 | |
|     print("Database initialized with sample data!")
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     with app.app_context():
 | |
|         db.create_all()
 | |
|     app.run(debug=True) |