Skip to main content

School Management System with Python, Flask and MySQL

In our previous Python project tutorial, we have explained to Face Recognition Based Attendance System with Python. In this tutorial, we will explain how to develop School Management System with Python, Flask and MySQL.

School Management Systems (SMS) is an online system that’s used in schools to manage students, classes, sections, subjects, teachers and attendance.

Here in this tutorial, we haved developed a very simple school management systems for learning purpose and can be enhanced according to requirement to develop a perfect advance level system.

We will cover following in this tutorial:

  • Manage User Login
  • Manage Teachers
  • Manage Students
  • Manage Classes
  • Manage Sections
  • Manage Subjects
  • Manage Attendance
  • Attendance Report
    • 1. MySQL Database

      First we will create MySQL database python_sms and create tables for our system.

      We will create table sms_teacher to store teachers details.

      CREATE TABLE `sms_teacher` (
        `teacher_id` int(11) NOT NULL,
        `teacher` varchar(255) NOT NULL,
        `subject_id` int(11) NOT NULL
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
      
      ALTER TABLE `sms_teacher`
        ADD PRIMARY KEY (`teacher_id`);
      

      We will create table sms_students to store students details.

      CREATE TABLE `sms_students` (
        `id` int(10) UNSIGNED NOT NULL,
        `name` varchar(40) NOT NULL,
        `gender` varchar(40) NOT NULL,
        `dob` varchar(255) NOT NULL,
        `photo` varchar(40) DEFAULT NULL,
        `mobile` int(10) UNSIGNED NOT NULL,
        `email` varchar(40) DEFAULT NULL,
        `current_address` varchar(40) DEFAULT NULL,
        `permanent_address` varchar(40) DEFAULT NULL,
        `father_name` varchar(255) NOT NULL,
        `father_mobile` int(10) UNSIGNED NOT NULL,
        `father_occupation` varchar(255) NOT NULL,
        `mother_name` varchar(255) NOT NULL,
        `mother_mobile` int(10) UNSIGNED NOT NULL,
        `admission_no` int(11) NOT NULL,
        `roll_no` int(11) NOT NULL,
        `class` int(10) UNSIGNED NOT NULL,
        `section` int(11) NOT NULL,
        `stream` int(10) UNSIGNED DEFAULT NULL,
        `hostel` int(10) UNSIGNED DEFAULT NULL,
        `admission_date` varchar(255) NOT NULL,
        `category` int(10) UNSIGNED DEFAULT NULL,
        `academic_year` int(10) UNSIGNED NOT NULL
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      ALTER TABLE `sms_students`
        ADD PRIMARY KEY (`id`);
      

      We will create table sms_classes to store school class details.

      CREATE TABLE `sms_classes` (
        `id` int(10) UNSIGNED NOT NULL,
        `name` varchar(40) NOT NULL,
        `section` varchar(255) NOT NULL,
        `teacher_id` int(11) NOT NULL
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      ALTER TABLE `sms_classes`
        MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
      

      We will create table sms_section to store school class section details.

      CREATE TABLE `sms_section` (
        `section_id` int(11) NOT NULL,
        `section` varchar(255) NOT NULL
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
      
      ALTER TABLE `sms_section`
        MODIFY `section_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
      

      We will create table sms_subjects to store subject details.

      CREATE TABLE `sms_subjects` (
        `subject_id` int(11) NOT NULL,
        `subject` varchar(255) NOT NULL,
        `type` varchar(255) NOT NULL,
        `code` int(11) NOT NULL
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
      
      ALTER TABLE `sms_subjects`
        MODIFY `subject_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
      

      We will create table sms_attendance to store students attendance details.

      CREATE TABLE `sms_attendance` (
        `attendance_id` int(11) NOT NULL,
        `student_id` int(11) NOT NULL,
        `class_id` int(11) NOT NULL,
        `section_id` int(11) NOT NULL,
        `attendance_status` int(11) NOT NULL,
        `attendance_date` varchar(255) NOT NULL
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
      
      ALTER TABLE `sms_attendance`
        MODIFY `attendance_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=9;
      

      We will create table sms_user to store user login details to access system.

      CREATE TABLE `sms_user` (
        `id` int(11) NOT NULL,
        `first_name` varchar(50) NOT NULL,
        `last_name` varchar(50) NOT NULL,
        `email` varchar(50) NOT NULL,
        `password` varchar(50) NOT NULL,
        `gender` enum('male','female') CHARACTER SET utf8 NOT NULL,
        `mobile` varchar(50) NOT NULL,
        `designation` varchar(50) NOT NULL,
        `image` varchar(250) NOT NULL,
        `type` varchar(250) NOT NULL DEFAULT 'general',
        `status` enum('active','pending','deleted','') NOT NULL DEFAULT 'pending',
        `authtoken` varchar(250) NOT NULL
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
      
      ALTER TABLE `sms_user`
        ADD PRIMARY KEY (`id`);
      

      2. Setup Porject File

      We will create our application file app.py and import required modules. We will setup our Flask app and also configure to connect with MySQL database. Here we will connect to python_sms MySQL database.

      from flask import Flask, render_template, request, redirect, url_for, session, jsonify
      from flask_mysqldb import MySQL
      import MySQLdb.cursors
      from datetime import date
      import re
      import os
      import sys
      
      app = Flask(__name__)
         
      app.secret_key = 'abcd21234455'  
      app.config['MYSQL_HOST'] = 'localhost'
      app.config['MYSQL_USER'] = 'root'
      app.config['MYSQL_PASSWORD'] = ''
      app.config['MYSQL_DB'] = 'python_sms'
        
      mysql = MySQL(app)
      

      3. User Login

      We will create route in app.js for login and create login() function to implement user login functionality to access system. The login.html template file will be called for displaying user login form. The login functionality willl be handled when login form submitted.

      @app.route('/')
      @app.route('/login', methods =['GET', 'POST'])
      def login():
          mesage = ''
          if request.method == 'POST' and 'email' in request.form and 'password' in request.form:
              email = request.form['email']        
              password = request.form['password']
              cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
              cursor.execute('SELECT * FROM sms_user WHERE status="active" AND email = % s AND password = % s', (email, password, ))
              user = cursor.fetchone()
              if user:
                  session['loggedin'] = True
                  session['userid'] = user['id']
                  session['name'] = user['first_name']
                  session['email'] = user['email']
                  session['role'] = user['type']
                  mesage = 'Logged in successfully !'            
                  return redirect(url_for('dashboard'))
              else:
                  mesage = 'Please enter correct email / password !'
          return render_template('login.html', mesage = mesage)
      

      We will create login.html template file and create login form html.

      {% include 'header.html' %}
      <body>
        <div class="container-fluid" id="main">
        {% include 'top_menus.html' %}  	
          <div class="row row-offcanvas row-offcanvas-left">      
            <div class="col-md-9 col-lg-10 main"> 
      		<h2>User Login</h2>
      		<form action="{{ url_for('login') }}" method="post">
      			{% if mesage is defined and mesage %}
      				<div class="alert alert-warning">{{ mesage }}</div>
      			{% endif %}
      			<div class="form-group">
      				<label for="email">Email:</label>
      				<input type="email" class="form-control" id="email" name="email" placeholder="Enter email" name="email">
      			</div>
      			<div class="form-group">
      				<label for="pwd">Password:</label>
      				<input type="password" class="form-control" id="password" name="password" placeholder="Enter password" name="pswd">
      			</div>    
      			<button type="submit" class="btn btn-primary">Login</button>
      			
      		</form>
              
              <hr>         
             </div>       
            </div>     
          </div>
        </body>
      </html>
      

      4. Manage Teachers

      We will create route in app.js for teacher and get details. We will load teacher.html and pass teachers details to display.

      @app.route("/teacher", methods =['GET', 'POST'])
      def teacher():
          if 'loggedin' in session:   
              cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
              cursor.execute('SELECT t.teacher_id, t.teacher, s.subject FROM sms_teacher t LEFT JOIN sms_subjects s ON s.subject_id = t.subject_id')
              teachers = cursor.fetchall() 
                 
              cursor.execute('SELECT * FROM sms_subjects')
              subjects = cursor.fetchall()  
              return render_template("teacher.html", teachers = teachers, subjects = subjects)
          return redirect(url_for('login')) 
      

      We will create teacher.html template file and create HTML to list teachers.

      {% include 'top_menus.html' %}
      <div class="container">        
        {% include 'left_menus.html' %}    
        <div class="content">
      	<div class="container-fluid">   	
      		<div class="row">
      		<a href="#"><strong><span class="ti-crown"></span> Teachers Section</strong></a>
      		<hr>	
      		<div class="float-right mb-2 col-md-2">
      			<button type="button" id="addTeacher" class="btn btn-info" title="Add teacher"><span class="glyphicon glyphicon-plus">Add</span></button>
      		</div>
      		<br><br>
      		<table class="table table-striped">
      		<thead>
      		  <tr>
      			<th>id</th>
      			<th>Name</th>
      			<th>Specialization</th>				
      			<th></th>
      			<th></th>				
      		  </tr>
      		</thead>
      		<tbody>
      		  {% for teacher in teachers %}
      		  <tr>
      			<td>{{teacher.teacher_id}}</td>
      			<td>{{teacher.teacher}}</td>
      			<td>{{teacher.subject}}</td>						
      			<td><a href="{{url_for('edit_teacher', teacher_id=teacher.teacher_id)}}" id="{{teacher.teacher_id}}" class="btn btn-primary update">Edit</a></td>
      			<td><a href="{{url_for('delete_teacher', teacher_id=teacher.teacher_id)}}" class="btn btn-danger">Delete</a></td>
      		  </tr> 
      		{% endfor %}	  
      		</tbody>
      	  </table>	        
      	<hr> 
      		</div>
      	</div>	
      </div>	
      </div>
      

      5. Manage Students

      We will create route in app.js for student and get students details. We will load student.html and student details.

      @app.route("/student", methods =['GET', 'POST'])
      def student():
          if 'loggedin' in session:       
              
              cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
              cursor.execute('SELECT s.id, s.admission_no, s.roll_no, s.name, s.photo, c.name AS class, sec.section FROM sms_students s LEFT JOIN sms_section sec ON sec.section_id = s.section LEFT JOIN sms_classes c ON c.id = s.class')
              students = cursor.fetchall() 
              
              cursor.execute('SELECT * FROM sms_classes')
              classes = cursor.fetchall() 
              
              cursor.execute('SELECT * FROM sms_section')
              sections = cursor.fetchall()
              
              return render_template("student.html", students = students, classes = classes, sections = sections)
          return redirect(url_for('login')) 
      

      We will create student.html template file and create HTML to list student.

      {% include 'top_menus.html' %}
      <div class="container">        
        {% include 'left_menus.html' %}    
        <div class="content">
      	<div class="container-fluid">   	
      		<div class="row">
      			<a href="#"><strong><span class="ti-crown"></span> Student Section</strong></a>
      			<hr>		
      			<div class="panel-heading">
      				<div class="row">
      					<div class="col-md-10">
      						<h3 class="panel-title"></h3>
      					</div>
      					<div class="col-md-2" align="right">
      						<button type="button" name="add" id="addStudent" class="btn btn-success btn-xs">Student Admission</button>
      					</div>
      				</div>
      			</div>
      			<table id="studentList" class="table table-bordered table-striped">
      				<thead>
      					<tr>
      						<th>ID</th>
      						<th>Reg No</th>
      						<th>Roll No</th>	
      						<th>Name</th>
      						<th>Photo</th>	
      						<th>Class</th>
      						<th>Section</th>							
      						<th></th>
      						<th></th>							
      					</tr>
      				</thead>
      				<tbody>
      				  {% for student in students %}
      				  <tr>
      					<td>{{student.id}}</td>
      					<td>{{student.admission_no}}</td>
      					<td>{{student.roll_no}}</td>
      					<td>{{student.name}}</td>
      					<td>{{student.photo}}</td>						
      					<td>{{student.class}}</td>
      					<td>{{student.section}}</td>
      					<td>{{student.section}}</td>						
      					<td><a href="{{url_for('edit_student', student_id=student.id)}}" class="btn btn-primary update">Edit</a></td>
      					<td><a href="{{url_for('delete_student', student_id=student.id)}}" class="btn btn-danger">Delete</a></td>
      				  </tr> 
      				{% endfor %}	  
      				</tbody>
      			</table>
      		</div>
      	</div>	
      </div>
      </div>
      

      6. Manage Classes

      We will create route in app.js for class and get class details. We will load class.html template file and pass classes details to list.

      @app.route("/classes", methods =['GET', 'POST'])
      def classes():
          if 'loggedin' in session:  
              cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
              cursor.execute('SELECT c.id, c.name, s.section, t.teacher FROM sms_classes c LEFT JOIN sms_section s ON s.section_id = c.section LEFT JOIN sms_teacher t ON t.teacher_id = c.teacher_id')
              classes = cursor.fetchall() 
                 
              cursor.execute('SELECT * FROM sms_section')
              sections = cursor.fetchall() 
              
              cursor.execute('SELECT * FROM sms_teacher')
              teachers = cursor.fetchall()
              
              return render_template("class.html", classes = classes, sections = sections, teachers = teachers)
          return redirect(url_for('login'))
      

      We will create class.html template file and create HTML to list classes.

      {% include 'top_menus.html' %}
      <div class="container">        
        {% include 'left_menus.html' %}    
        <div class="content">
      	<div class="container-fluid">   	
      		<div class="row">
      			<a href="#"><strong><span class="ti-crown"></span> Classes Section</strong></a>
      			<hr>		
      			<div class="panel-heading">
      				<div class="row">
      					<div class="col-md-10">
      						<h3 class="panel-title"></h3>
      					</div>
      					<div class="col-md-2" align="right">
      						<button type="button" name="add" id="addClass" class="btn btn-success btn-xs">Add New Class</button>
      					</div>
      				</div>
      			</div>
      			<table id="classList" class="table table-bordered table-striped">
      				<thead>
      					<tr>
      						<th>ID</th>
      						<th>Name</th>	
      						<th>Sections</th>
      						<th>Class Teacher</th>							
      						<th></th>
      						<th></th>							
      					</tr>
      				</thead>
      				<tbody>
      				  {% for class in classes %}
      				  <tr>
      					<td>{{class.id}}</td>
      					<td>{{class.name}}</td>
      					<td>{{class.section}}</td>
      					<td>{{class.teacher}}</td>							
      					<td><a href="{{url_for('edit_class', class_id=class.id)}}" class="btn btn-primary update">Edit</a></td>
      					<td><a href="{{url_for('delete_class', class_id=class.id)}}" class="btn btn-danger">Delete</a></td>
      				  </tr> 
      				{% endfor %}	  
      				</tbody>
      			</table>
      		</div>
      	</div>	
      </div>
      </div>
      

      7. Manage Sections

      We will create route in app.js for sections. We will get sections details and pass with template file to list.

      @app.route("/sections", methods =['GET', 'POST'])
      def sections():
          if 'loggedin' in session:      
              cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
              cursor.execute('SELECT * FROM sms_section')
              sections = cursor.fetchall()          
              return render_template("sections.html", sections = sections)
          return redirect(url_for('login')) 
      

      We will create section.html template file and create HTML to list sections.

      {% include 'top_menus.html' %}
      <div class="container">        
        {% include 'left_menus.html' %}    
        <div class="content">
      	<div class="container-fluid">   	
      		<div class="row">
      			<a href="#"><strong><span class="ti-crown"></span> Classes Section</strong></a>
      			<hr>		
      			<div class="panel-heading">
      				<div class="row">
      					<div class="col-md-10">
      						<h3 class="panel-title"></h3>
      					</div>
      					<div class="col-md-2" align="right">
      						<button type="button" name="add" id="addSection" class="btn btn-success btn-xs">Add New Section</button>
      					</div>
      				</div>
      			</div>
      			<table id="sectionList" class="table table-bordered table-striped">
      				<thead>
      					<tr>
      						<th>ID</th>
      						<th>Name</th>											
      						<th></th>
      						<th></th>							
      					</tr>
      				</thead>
      				<tbody>
      				  {% for section in sections %}
      				  <tr>
      					<td>{{section.section_id}}</td>
      					<td>{{section.section}}</td>											
      					<td><a href="{{url_for('edit_sections', section_id=section.section_id)}}" id="{{section.section_id}}" class="btn btn-primary update">Edit</a></td>
      					<td><a href="{{url_for('delete_sections', section_id=section.section_id)}}" class="btn btn-danger">Delete</a></td>
      				  </tr> 
      				{% endfor %}	  
      				</tbody>
      			</table>
      		</div>
      	</div>	
      </div>
      </div>
      

      8. Manage Subjects

      We will create route in app.js for subject and get subjetc details. We will load template file and passed details to list.

      @app.route("/subject", methods =['GET', 'POST'])
      def subject():
          if 'loggedin' in session:       
              cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
              cursor.execute('SELECT * FROM sms_subjects')
              subjects = cursor.fetchall()          
              return render_template("subject.html", subjects = subjects)
          return redirect(url_for('login'))
      

      We will create subject.html template file and create HTML to list subjects.

      {% include 'top_menus.html' %}
      <div class="container">        
        {% include 'left_menus.html' %}    
        <div class="content">
      	<div class="container-fluid">   	
      		<div class="row">				 
      			<a href="#"><strong><span class="ti-crown"></span> Subjects Section</strong></a>
      			<hr>		
      			<div class="panel-heading">
      				<div class="row">
      					<div class="col-md-10">
      						<h3 class="panel-title"></h3>
      					</div>
      					<div class="col-md-2" align="right">
      						<button type="button" name="add" id="addSubject" class="btn btn-success btn-xs">Add</button>
      					</div>
      				</div>
      			</div>
      			<table id="subjectList" class="table table-bordered table-striped">
      				<thead>
      					<tr>
      						<th>ID</th>
      						<th>Subject</th>	
      						<th>Code</th>
      						<th>Subject Type</th>							
      						<th></th>
      						<th></th>							
      					</tr>
      				</thead>
      				<tbody>
      				  {% for subject in subjects %}
      				  <tr>
      					<td>{{subject.subject_id}}</td>
      					<td>{{subject.subject}}</td>
      					<td>{{subject.code}}</td>
      					<td>{{subject.type}}</td>							
      					<td><a href="{{url_for('edit_subject', subject_id=subject.subject_id)}}" class="btn btn-primary update">Edit</a></td>
      					<td><a href="{{url_for('delete_subject', subject_id=subject.subject_id)}}" class="btn btn-danger">Delete</a></td>
      				  </tr> 
      				{% endfor %}	  
      				</tbody>
      			</table>						
      			</div>	
      		</div>
      	</div>	
      </div>
      

      9. Manage Attendance

      We will create route in app.js for attendance and get attendance details.

      @app.route("/getClassAttendance", methods =['GET', 'POST'])
      def getClassAttendance():
          if 'loggedin' in session:  
              if request.method == 'POST' and 'classid' in request.form and 'sectionid' in request.form:
              
                  classid = request.form['classid']
                  sectionid = request.form['sectionid']
                  
                  cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)   
                  
                  cursor.execute('SELECT * FROM sms_classes')
                  classes = cursor.fetchall() 
                  
                  cursor.execute('SELECT * FROM sms_section')
                  sections = cursor.fetchall() 
      
                  currentDate = date.today().strftime('%Y/%m/%d')
                           
                  cursor.execute('SELECT s.id, s.name, s.photo, s.gender, s.dob, s.mobile, s.email, s.current_address, s.father_name, s.mother_name,s.admission_no, s.roll_no, s.admission_date, s.academic_year, a.attendance_status, a.attendance_date FROM sms_students as s LEFT JOIN sms_attendance as a ON s.id = a.student_id WHERE s.class = '+classid+' AND s.section = '+sectionid)              
                  students = cursor.fetchall()   
                            
                  return render_template("attendance.html", classes = classes, sections = sections, students = students, classId = classid, sectionId = sectionid)        
              elif request.method == 'POST':
                  msg = 'Please fill out the form field !'        
              return redirect(url_for('attendance'))        
          return redirect(url_for('login')) 
      

      We will create attendance.html template file and create HTML to list attendance.

      {% include 'top_menus.html' %}
      <div class="container">        
        {% include 'left_menus.html' %}    
        <div class="content">
      	<div class="container-fluid">   	
      		<div class="row">
      			<div class="col-md-12">
      				<div class="box box-primary">
      					<div class="box-header with-border">
      						<h3 class="box-title"><i class="fa fa-search"></i> Select Criteria</h3>
      					</div>
      					<form id="form1" action="{{ url_for('getClassAttendance')}}" method="post" accept-charset="utf-8">
      						<div class="box-body">						
      							<div class="row">
      								<div class="col-md-4">
      									<div class="form-group">
      										<label for="exampleInputEmail1">Class</label><small class="req"> *</small>
      										<select id="classid" name="classid" class="form-control" required>
      											<option value="">Select</option>
      											{% for class in classes %}								
      												<option value="{{class.id}}" {% if class.id == classId %} selected {% endif %}>{{class.name}}</option>				
      											{% endfor %}												
      										</select>
      										<span class="text-danger"></span>
      									</div>
      								</div>
      								<div class="col-md-4">
      									<div class="form-group">
      										<label for="exampleInputEmail1">Section</label><small class="req"> *</small>
      											<select name="sectionid" id="sectionid" class="form-control" required>
      												<option value="">Select</option>
      												{% for section in sections %}
      													<option value="{{section.section_id}}" {% if section.section_id == sectionId %} selected {% endif %}>{{section.section}}</option>	
      												{% endfor %}
      											</select>
      										<span class="text-danger"></span>
      									</div>
      								</div> 									
      							</div>
      						</div>
      						<div class="box-footer">
      							<button type="submit" id="search" name="search" value="search" style="margin-bottom:10px;" class="btn btn-primary btn-sm  checkbox-toggle"><i class="fa fa-search"></i> Search</button> <br>
      						</div>
      					</form>
      				</div>					
      				<div class="row">					
      					<form id="attendanceForm" method="post">					
      						<div style="color:red;margin-top:20px;" class="" id="message"></div>
      						<button type="submit" id="saveAttendance" name="saveAttendance" value="Save Attendance" style="margin-bottom:10px;" class="btn btn-primary btn-sm  pull-right checkbox-toggle hidden"><i class="fa fa-save"></i> Save Attendance</button> <table id="studentList" class="table table-bordered table-striped">
      						<thead>
      							<tr>
      								<th>#</th>
      								<th>Reg No</th>
      								<th>Roll No</th>	
      								<th>Name</th>
      								<th>Attendance</th>													
      							</tr>
      						</thead>
      						<tbody>
      							{% for student in students %}
      							<tr>
      								<td>{{student.id}}</td>
      								<td>{{student.admission_no}}</td>
      								<td>{{student.roll_no}}</td>	
      								<td>{{student.name}}</td>
      								<td>
      								
      								<input type="radio" id="attendencetype1_"+{{student.id}}+" value="1" name="attendencetype_"+{{student.id}}+" autocomplete="off" '.$checked['1'].'>
      								<label for="attendencetype_"+{{student.id}}+">Present</label>
      								<input type="radio" id="attendencetype2_"+{{student.id}}+"" value="2" name="attendencetype_"+{{student.id}}+"" autocomplete="off" '.$checked['2'].'>
      								<label for="attendencetype"+{{student.id}}+">Late </label>
      								<input type="radio" id="attendencetype3_"+{{student.id}}+" value="3" name="attendencetype_"+{{student.id}}+" autocomplete="off" '.$checked['3'].'>
      								<label for="attendencetype3_"+{{student.id}}+"> Absent </label>
      								<input type="radio" id="attendencetype4_"+{{student.id}}+" value="4" name="attendencetype_"+{{student.id}}+" autocomplete="off" '.$checked['4'].'><label for="attendencetype_"+{{student.id}}+"> Half Day </label>
      								
      								</td>													
      							</tr>
      							{% endfor %}
      						</tbody>
      						</table>
      						<input type="hidden" name="action" id="action" value="updateAttendance" />
      						<input type="hidden" name="att_classid" id="att_classid" value="" />
      						<input type="hidden" name="att_sectionid" id="att_sectionid" value="" />
      					</form>
      				</div>							
      			</div>
      		</div>
      	</div>	
      </div>
      </div>
      

      10. Implement Attendance Report

      We will create route in app.js for attendance report and get details to list.

      @app.route("/report", methods =['GET', 'POST'])
      def report():
          if 'loggedin' in session:  
              cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
              
              cursor.execute('SELECT * FROM sms_classes')
              classes = cursor.fetchall() 
              
              cursor.execute('SELECT * FROM sms_section')
              sections = cursor.fetchall()
              
              return render_template("report.html", classes = classes, sections = sections)
          return redirect(url_for('login'))     
      

      We will create report.html template file and create HTML to list attendance report.

      {% include 'top_menus.html' %}
      <div class="container">        
        {% include 'left_menus.html' %}    
        <div class="content">
      	<div class="container-fluid">   	
      		<div class="row">
      			<div class="col-md-12">
      				<div class="box box-primary">
      					<div class="box-header with-border">
      						<h3 class="box-title"><i class="fa fa-search"></i> Select Criteria</h3>
      					</div>
      					<form id="form1" action="" method="post" accept-charset="utf-8">
      						<div class="box-body">						
      							<div class="row">
      								<div class="col-md-4">
      									<div class="form-group">
      										<label for="classid">Class</label><small class="req"> *</small>
      										<select id="classid" name="classid" class="form-control" required>
      											<option value="">Select</option>
      											{% for class in classes %}								
      												<option value="{{class.id}}" {% if class.id == classId %} selected {% endif %}>{{class.name}}</option>				
      											{% endfor %}												
      										</select>
      										<span class="text-danger"></span>
      									</div>
      								</div>
      								<div class="col-md-4">
      									<div class="form-group">
      										<label for="sectionid">Section</label><small class="req"> *</small>
      											<select name="sectionid" id="sectionid" class="form-control" required>
      												<option value="">Select</option>
      												{% for section in sections %}
      													<option value="{{section.section_id}}" {% if section.section_id == sectionId %} selected {% endif %}>{{section.section}}</option>	
      												{% endfor %}
      											</select>
      										<span class="text-danger"></span>
      									</div>
      								</div> 	
      								<div class="col-md-4">
      									<div class="form-group">
      										<label for="attendanceDate">Attendance Date</label><small class="req"> *</small>			
      										<input type='text' class="form-control" id="attendanceDate" name="attendanceDate" value="2019/06/22" placeholder="yyyy/mm/dd" />										
      									</div>
      								</div> 										
      							</div>
      						</div>
      						<div class="box-footer">
      							<button type="button" id="search" name="search" value="search" style="margin-bottom:10px;" class="btn btn-primary btn-sm  checkbox-toggle"><i class="fa fa-search"></i> Search</button> <br>
      						</div>
      					</form>
      				</div>
      			</div>
      		</div>
      	</div>	
      </div>
      </div>
      

      You can download the complete source code of project from the Download link below.

      Download