Building a Modular Student Records System in Python
System Architecture and Data Model
A student information system requires a structured approach to handle academic records efficiently. The foundation relies on two primary components: an entity class representing individual students and a controller class managing the collection and persistence layer.
The entity class encapsulates student attributes:
class Learner:
def __init__(self, roll_number, full_name, years_old, sex):
self.roll_number = roll_number
self.full_name = full_name
self.years_old = years_old
self.sex = sex
def render_profile(self):
return f"ID: {self.roll_number} | Name: {self.full_name} | Age: {self.years_old} | Gender: {self.sex}"
Core Management Logic
The controller class maintains an in-memory registry and provides CRUD operations:
class RecordsManager:
def __init__(self):
self.registry = []
def enroll(self, pupil):
self.registry.append(pupil)
def unregister(self, roll_number):
for idx, pupil in enumerate(self.registry):
if pupil.roll_number == roll_number:
del self.registry[idx]
return True
return False
def update_record(self, roll_number, **kwargs):
for pupil in self.registry:
if pupil.roll_number == roll_number:
for key, value in kwargs.items():
if hasattr(pupil, key):
setattr(pupil, key, value)
return True
return False
def find(self, query):
return [p for p in self.registry if query in (p.roll_number, p.full_name)]
def list_all(self):
return self.registry
Data Persistence Implementation
File-based storage ensures data survives between sessions. The system implements pipe-delimited text format for robustness against comma-containing names:
def commit_to_disk(self, filepath):
with open(filepath, 'w', encoding='utf-8') as f:
for pupil in self.registry:
line = f"{pupil.roll_number}|{pupil.full_name}|{pupil.years_old}|{pupil.sex}\n"
f.write(line)
def restore_from_disk(self, filepath):
self.registry = []
try:
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
if line.strip():
parts = line.strip().split('|')
if len(parts) == 4:
pupil = Learner(parts[0], parts[1], int(parts[2]), parts[3])
self.registry.append(pupil)
except FileNotFoundError:
pass
Interactive Interface
The command-line interface provides a menu-driven interaction model:
def main():
db = RecordsManager()
db.restore_from_disk('academic_records.txt')
while True:
print("\nAcademic Records System")
print("1. Enroll New Student")
print("2. Remove Student")
print("3. Update Information")
print("4. Search Records")
print("5. View All Students")
print("6. Save Changes")
print("7. Exit")
choice = input("Select operation: ").strip()
if choice == '1':
rn = input("Enter Roll Number: ")
fn = input("Enter Full Name: ")
age = int(input("Enter Age: "))
gender = input("Enter Gender: ")
db.enroll(Learner(rn, fn, age, gender))
print("Enrollment successful.")
elif choice == '2':
rn = input("Enter Roll Number to remove: ")
if db.unregister(rn):
print("Student removed.")
else:
print("Record not found.")
elif choice == '3':
rn = input("Enter Roll Number to update: ")
print("Leave blank to keep current value")
name = input("New name: ") or None
age_str = input("New age: ")
age = int(age_str) if age_str else None
gender = input("New gender: ") or None
updates = {}
if name: updates['full_name'] = name
if age: updates['years_old'] = age
if gender: updates['sex'] = gender
if db.update_record(rn, **updates):
print("Record updated.")
else:
print("Student not found.")
elif choice == '4':
term = input("Enter name or ID to search: ")
results = db.find(term)
for r in results:
print(r.render_profile())
elif choice == '5':
pupils = db.list_all()
if not pupils:
print("No records found.")
else:
for p in pupils:
print(p.render_profile())
elif choice == '6':
db.commit_to_disk('academic_records.txt')
print("Data saved.")
elif choice == '7':
break
if __name__ == "__main__":
main()
This structure separates concerns between data representation, business logic, and user interaction, enabling easy extension for database backends or web interfaces.