Chat about this codebase

AI-powered code exploration

Online

Project Overview

The Student-Management system centralizes student data, course catalogs, enrollments and grading in a single, extensible platform. It exposes RESTful APIs and a web UI (or CLI) to automate administrative workflows for schools, colleges and training centers.

Key Features

  • Student CRUD: register, update, suspend and delete student records
  • Course Catalog: define courses, sections, schedules and instructors
  • Enrollment Management: enroll students, handle waitlists and capacity constraints
  • Gradebook & Reporting: record grades, generate transcripts and performance analytics
  • Authentication & Roles: secure access with administrator, instructor and student roles
  • Extensibility: plugin hooks for custom reports, notifications and data exports

Typical Use Cases

  • Onboarding new batches: bulk-import student data, assign core courses
  • Grading cycle: instructors submit grades; admin generates official transcripts
  • Real-time dashboards: monitor enrollment trends and course fill rates
  • Data integration: sync with ERP/payroll, export CSV/JSON for BI tools

Architecture Overview

  • Backend: REST API layer managing business logic and data validation
  • Database: relational (e.g., PostgreSQL/MySQL) or document store (e.g., MongoDB)
  • Frontend: web client built on React/Vue.js or CLI scripts for automation
  • Authentication: JWT/OAuth2 or session-based flows
  • Deployment: Dockerized services or cloud-native containers

Value Proposition

  • Streamlines administrative tasks, reducing manual errors
  • Provides actionable insights via built-in reporting
  • Scales with institution size through modular design
  • Offers clear extension points for custom workflows and integrations

Getting Started

Follow these steps to install dependencies, configure the environment, run migrations, create a superuser, and start the development server.

1. Clone the Repository

git clone https://github.com/MrRoy2246/Student-Management.git
cd Student-Management

2. Create & Activate Virtual Environment

python3 -m venv venv
# macOS/Linux
source venv/bin/activate
# Windows (PowerShell)
venv\Scripts\Activate.ps1

3. Install Dependencies

pip install --upgrade pip
pip install -r requirements.txt

4. Configure Environment

By default the project uses SQLite (db.sqlite3). To override settings, set environment variables before running any Django command:

export DJANGO_SECRET_KEY="your-secret-key"
export DJANGO_DEBUG=True
export DJANGO_ALLOWED_HOSTS="127.0.0.1,localhost"

On Windows (PowerShell):

$env:DJANGO_SECRET_KEY="your-secret-key"
$env:DJANGO_DEBUG="True"
$env:DJANGO_ALLOWED_HOSTS="127.0.0.1,localhost"

Adjust student_course_mgmt/settings.py if you need a different database or custom settings.

5. Apply Database Migrations

python manage.py migrate

This creates the required tables in db.sqlite3.

6. Create a Superuser

python manage.py createsuperuser

Follow the prompts to set username, email, and password. This account lets you access the Django admin at /admin/.

7. Start the Development Server

python manage.py runserver

Visit http://127.0.0.1:8000 to verify the application is running. The admin interface is available at http://127.0.0.1:8000/admin/.

Core Concepts & Architecture

This section describes how the Student-Management system organizes its custom authentication, role-based access, app boundaries, and core data relationships.

1. Custom User Model

The accounts app defines a custom User model extending AbstractBaseUser with built-in roles and a dedicated manager.

Key Elements

  • Fields: email (unique), first_name, last_name, role
  • Roles:
    • STUDENT
    • TEACHER
    • ADMIN
    • ADVISING_ADMIN
    • ACCOUNT_CREATOR_ADMIN
  • Manager: CustomUserManager handles create_user and create_superuser.

Usage Example

# accounts/models.py
from accounts.models import User

# Create a student user
student = User.objects.create_user(
    email='alice@student.edu',
    password='securePass123',
    first_name='Alice',
    last_name='Johnson',
    role=User.STUDENT
)

# Create a superuser
admin = User.objects.create_superuser(
    email='admin@school.edu',
    password='superSecure!',
    first_name='Super',
    last_name='User'
)

2. Role-Based Permissions

The accounts/permission.py file provides DRF permission classes enforcing role checks at the view and object level.

Common Permission Classes

  • IsAdmin
  • IsAdvisingAdmin
  • IsAccountCreator
  • IsStudent
  • ReadOnly

Applying Permissions

# accounts/views.py
from rest_framework import viewsets
from accounts.models import User
from accounts.serializers import UserSerializer
from accounts.permission import IsAdmin, ReadOnly

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [IsAdmin|ReadOnly]

3. App Boundaries & URL Routing

The project splits functionality into coherent Django apps:

  • accounts – authentication, user registration, roles
  • departments – department CRUD, active student counts
  • students – student profiles
  • teachers – teacher profiles
  • courses – courses and sections management

Root URL Configuration

# student_course_mgmt/urls.py
from django.urls import path, include
from django.contrib import admin

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/accounts/', include('accounts.urls')),
    path('api/departments/', include('departments.urls')),
    path('api/students/', include('students.urls')),
    path('api/teachers/', include('teachers.urls')),
    path('api/courses/', include('courses.urls')),
]

4. Data Model Relationships

User ↔ Profiles

  • One-to-one: UserStudentProfile (students/models.py)
  • One-to-one: UserTeacherProfile (teachers/models.py)

Department ↔ StudentProfile

  • Department (one) → StudentProfile (many)
  • Method: Department.active_student_count()

Course ↔ Sections ↔ Teachers

  • CourseSection (one-to-many)
  • Section.instructorTeacherProfile

Relationship Examples

# Fetch a student's department and active student count
from students.models import StudentProfile
from departments.models import Department

student_profile = StudentProfile.objects.get(user__email='alice@student.edu')
department = student_profile.department
print(department.active_student_count())

# Assign a teacher to a course section
from courses.models import Section
from teachers.models import TeacherProfile

teacher = TeacherProfile.objects.get(user__email='prof.jones@school.edu')
section = Section.objects.get(id=42)
section.instructor = teacher
section.save()

This high-level view guides you through the core building blocks of the Student-Management system, highlighting where to extend authentication, permission rules, and data interactions.

REST API Guide

This guide describes each REST endpoint, its authentication, request/response shapes, and common workflows in the Student-Management project.

Accounts API

POST /accounts/register/

Create a new user. Restricts access to admin roles.

Permission class (accounts/permission.py)

from rest_framework.permissions import BasePermission

class IsSuperAdminOrAccountCreatorAdmin(BasePermission):
    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.role in ['admin', 'account_creator_admin']
        )

View configuration (accounts/views.py)

from rest_framework.generics import CreateAPIView
from .permissions import IsSuperAdminOrAccountCreatorAdmin
from .serializers import UserRegistrationSerializer

class UserRegistrationView(CreateAPIView):
    serializer_class = UserRegistrationSerializer
    permission_classes = [IsSuperAdminOrAccountCreatorAdmin]

URL pattern (accounts/urls.py)

from django.urls import path
from .views import UserRegistrationView

urlpatterns = [
    path('register/', UserRegistrationView.as_view(), name='accounts-register'),
]

Example request

curl -X POST https://api.example.com/accounts/register/ \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "username":"jdoe",
    "password":"SecureP@ss123",
    "full_name":"John Doe",
    "role":"student"
  }'

Success response (201)

{
  "id": 42,
  "username": "jdoe",
  "full_name": "John Doe",
  "role": "student"
}

Student Profile API Endpoints

Expose student profiles; students manage their own, admins manage all.

URL configuration (students/urls.py)

from django.urls import path
from .views import (
    StudentOwnProfileView,
    StudentProfileListView,
    StudentProfileDetailView
)

urlpatterns = [
    path('profile/', StudentOwnProfileView.as_view(), name='own-profile'),
    path('all-profile/', StudentProfileListView.as_view(), name='student-list'),
    path('<int:pk>/', StudentProfileDetailView.as_view(), name='student-profile-detail'),
]

Endpoints

GET /students/profile/
• Serializer: StudentProfileSerializer
• Permission: IsStudent
• Returns the caller’s active profile.

PUT /students/profile/
• Updates address, phone_number.

GET /students/all-profile/
• Serializer: StudentProfileSerializer
• Permission: IsAdminOrAdvisingAdmin
• Lists all active profiles.

GET, PUT /students/{pk}/
• Serializer: AdminStudentProfileSerializer
• Permission: IsAdminOrAdvisingAdmin
• Operates on active profiles.

Examples

  1. Retrieve own profile
curl -H "Authorization: Bearer <token>" \
     GET https://api.example.com/students/profile/

Response (200)

{
  "id": 12,
  "user_id": 34,
  "user_name": "Jane Doe",
  "student_id": "STU2025001",
  "department_name": "Computer Science",
  "department_code": "CS",
  "date_of_birth": "2003-04-15",
  "address": "123 Main St",
  "phone_number": "+1234567890",
  "enrollment_year": 2021
}
  1. Update own profile
curl -X PUT https://api.example.com/students/profile/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"address":"456 Elm St","phone_number":"+1987654321"}'
  1. List all profiles (admin)
curl -H "Authorization: Bearer <admin-token>" \
     GET https://api.example.com/students/all-profile/
  1. Admin updates department
curl -X PUT https://api.example.com/students/12/ \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"department":3}'

Tips

  • StudentProfileSerializer marks user and student_id read-only.
  • AdminStudentProfileSerializer allows nested user_name edits.
  • Soft-delete by setting is_active=False excludes profiles from all endpoints.

Department API Endpoints

CRUD with soft-delete and role-based access.

URL configuration (departments/urls.py)

from django.urls import path
from .views import DepartmentListCreateView, DepartmentDetailView

urlpatterns = [
    path('', DepartmentListCreateView.as_view(), name='department-list-create'),
    path('<int:pk>/', DepartmentDetailView.as_view(), name='department-detail'),
]

Views (departments/views.py)

from rest_framework import generics, permissions
from .models import Department
from .serializers import DepartmentSerializer
from accounts.permission import IsSuperAdmin

class DepartmentListCreateView(generics.ListCreateAPIView):
    queryset = Department.objects.filter(is_active=True)
    serializer_class = DepartmentSerializer

    def get_permissions(self):
        if self.request.method == 'GET':
            return [permissions.IsAuthenticated()]
        return [IsSuperAdmin()]

class DepartmentDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Department.objects.filter(is_active=True)
    serializer_class = DepartmentSerializer

    def get_permissions(self):
        if self.request.method == 'GET':
            return [permissions.IsAuthenticated()]
        return [IsSuperAdmin()]

    def perform_destroy(self, instance):
        instance.is_active = False
        instance.save()

Examples

  1. List departments
GET /api/departments/ HTTP/1.1
Authorization: Token your_token_here

Response (200)

[
  { "id":1, "name":"Computer Science","code":"CS","student_count":120 },
  …
]
  1. Create department (super-admin)
POST /api/departments/ HTTP/1.1
Authorization: Token superadmin_token
Content-Type: application/json

{ "name":"Mathematics","code":"MATH" }

Response (201)

{ "id":5, "name":"Mathematics","code":"MATH","student_count":0 }
  1. Soft-delete a department
DELETE /api/departments/5/ HTTP/1.1
Authorization: Token superadmin_token

Subsequent GETs omit this record.


Section API Endpoints

Manage course sections; enforce that teacher has role “teacher.”

URL configuration (courses/urls.py)

from django.urls import path
from .views import SectionListCreateView, SectionDetailView

urlpatterns = [
    path('sections/', SectionListCreateView.as_view(), name='section-list-create'),
    path('sections/<int:pk>/', SectionDetailView.as_view(), name='section-detail'),
]

Serializer validation (courses/serializers.py)

from .models import Section
from rest_framework import serializers

class SectionSerializer(serializers.ModelSerializer):
    course_name  = serializers.CharField(source='course.name', read_only=True)
    teacher_name = serializers.CharField(source='teacher.full_name', read_only=True)

    class Meta:
        model = Section
        fields = [
            'id','course','course_name',
            'teacher','teacher_name',
            'section','schedule','room','seats'
        ]

    def validate_teacher(self, value):
        if value.role != 'teacher':
            raise serializers.ValidationError("Selected user is not a teacher.")
        return value

Examples

  1. Create a section
curl -X POST https://api.example.com/sections/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "course":5,
    "teacher":12,
    "section":"A",
    "schedule":"MWF 10:00-11:00",
    "room":"B201",
    "seats":25
  }'

Success (201)

{
  "id":8,
  "course":5,
  "course_name":"Intro to Algorithms",
  "teacher":12,
  "teacher_name":"Dr. Jane Smith",
  "section":"A",
  "schedule":"MWF 10:00-11:00",
  "room":"B201",
  "seats":25
}
  1. Validation error (non-teacher user)
{ "teacher":["Selected user is not a teacher."] }

Teacher Profile API Endpoints

Offer nested user info and controlled update semantics.

URL configuration (teachers/urls.py)

from django.urls import path
from .views import (
    TeacherProfileView,
    AdminTeacherProfileListView,
    AdminTeacherProfileDetailView
)

urlpatterns = [
    path('teachers/profile/', TeacherProfileView.as_view(), name='teacher-own-profile'),
    path('admin/teachers/', AdminTeacherProfileListView.as_view(), name='admin-teacher-list'),
    path('admin/teachers/<int:pk>/', AdminTeacherProfileDetailView.as_view(), name='admin-teacher-detail'),
]

Serializers (teachers/serializers.py)

TeacherProfileSerializer (read-only user fields)

class TeacherProfileSerializer(serializers.ModelSerializer):
    user_id   = serializers.IntegerField(source='user.id', read_only=True)
    user_name = serializers.CharField(source='user.full_name', read_only=True)

    class Meta:
        model = TeacherProfile
        fields = [
            'id','user_id','user_name','teacher_id','designation',
            'department','date_of_birth','address','phone_number',
            'qualifications','experience_years','office_room_number'
        ]
        read_only_fields = ['id','user_id']

    def update(self, instance, validated_data):
        validated_data.pop('user', None)
        return super().update(instance, validated_data)

AdminTeacherProfileSerializer (editable full_name)

class AdminTeacherProfileSerializer(serializers.ModelSerializer):
    user_id   = serializers.IntegerField(source='user.id', read_only=True)
    user_name = serializers.CharField(source='user.full_name')

    class Meta:
        model = TeacherProfile
        fields = [
            'id','user_id','user_name','teacher_id','designation',
            'department','date_of_birth','address','phone_number',
            'qualifications','experience_years','office_room_number'
        ]
        read_only_fields = ['id','user_id']

    def update(self, instance, validated_data):
        user_data = validated_data.pop('user', {})
        if 'full_name' in user_data:
            instance.user.full_name = user_data['full_name']
            instance.user.save()
        return super().update(instance, validated_data)

Examples

  1. Regular user updates profile
curl -X PATCH https://api.example.com/teachers/profile/ \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"address":"789 Oak St","phone_number":"+1122334455"}'
  1. Admin lists all teachers
curl -H "Authorization: Bearer <admin-token>" \
     GET https://api.example.com/admin/teachers/
  1. Admin updates full_name and designation
curl -X PUT https://api.example.com/admin/teachers/7/ \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "user":{ "full_name":"Dr. Emily Clark" },
    "designation":"Associate Professor"
  }'

Tips

  • Always include user_id and user_name in responses.
  • Regular flows ignore nested user data; admin flows apply them first.
  • Adjust serializers if you introduce new roles or nested updates.

Deployment & Configuration

This section covers installing project dependencies, managing environment variables, customizing production settings, and deploying the student_course_mgmt Django application via WSGI or ASGI servers.

Installing Dependencies

Use requirements.txt to install pinned packages:

# Create virtual environment
python3 -m venv venv
source venv/bin/activate

# Install dependencies
pip install --upgrade pip
pip install -r requirements.txt

Setting Environment Variables

Store sensitive or environment-specific values outside version control. Create a .env file at project root:

# .env
SECRET_KEY=your-production-secret-key
DEBUG=False
ALLOWED_HOSTS=your.domain.com,api.your.domain.com
DATABASE_URL=postgres://USER:PASSWORD@HOST:PORT/DB_NAME
JWT_ACCESS_TOKEN_LIFETIME=3600

Load these in settings.py using os.environ:

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

SECRET_KEY = os.environ['SECRET_KEY']
DEBUG = os.environ.get('DEBUG', 'False') == 'True'

ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')

import dj_database_url
DATABASES = {
    'default': dj_database_url.parse(os.environ.get('DATABASE_URL'))
}

Install dj-database-url if using DATABASE_URL:

pip install dj-database-url

Configuring Production Settings

  1. Static Files
    Serve static assets with WhiteNoise. In settings.py:

    MIDDLEWARE.insert(1, 'whitenoise.middleware.WhiteNoiseMiddleware')
    STATIC_ROOT = BASE_DIR / 'staticfiles'
    STATIC_URL = '/static/'
    

    Collect static files before deploy:

    python manage.py collectstatic --noinput
    
  2. Security Headers

    SECURE_SSL_REDIRECT = True
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True
    
  3. JWT Configuration
    Override lifetimes via env:

    from datetime import timedelta
    
    SIMPLE_JWT = {
        'ACCESS_TOKEN_LIFETIME': timedelta(seconds=int(os.environ.get('JWT_ACCESS_TOKEN_LIFETIME', 300))),
        # other JWT settings...
    }
    

WSGI Deployment

Use Gunicorn to serve the WSGI application defined in student_course_mgmt/wsgi.py:

# Bind to port 8000, use 4 worker processes
gunicorn student_course_mgmt.wsgi:application \
    --bind 0.0.0.0:8000 \
    --workers 4 \
    --log-level info

Recommended systemd unit (/etc/systemd/system/student_mgmt.service):

[Unit]
Description=Gunicorn instance for student_course_mgmt
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/path/to/project
EnvironmentFile=/path/to/project/.env
ExecStart=/path/to/venv/bin/gunicorn \
    --workers 4 \
    --bind unix:/run/student_mgmt.sock \
    student_course_mgmt.wsgi:application

[Install]
WantedBy=multi-user.target

ASGI Deployment

For asynchronous features, deploy via Daphne or Uvicorn using student_course_mgmt/asgi.py:

# Using Daphne
daphne -b 0.0.0.0 -p 8001 student_course_mgmt.asgi:application

# Or Uvicorn with auto-reload disabled
uvicorn student_course_mgmt.asgi:application \
    --host 0.0.0.0 \
    --port 8001 \
    --workers 2

Configure systemd similarly, replacing the ExecStart command.

With these steps, you deploy a secure, configurable Django application ready for production.

Contributing & Extending

This section guides you through setting up a local development workflow, running and writing tests, adding new apps or roles, customizing the Django admin, and automating workflows with signals.

1. Local Development Workflow

  1. Clone the repository and create a virtual environment

    git clone https://github.com/MrRoy2246/Student-Management.git
    cd Student-Management
    python3 -m venv venv
    source venv/bin/activate
    
  2. Install dependencies and configure environment

    pip install -r requirements.txt
    cp .env.example .env
    # Edit .env with database credentials and SECRET_KEY
    
  3. Apply migrations and create a superuser

    python manage.py migrate
    python manage.py createsuperuser
    
  4. Run the development server

    python manage.py runserver
    

2. Running Tests

Execute the full test suite with:

python manage.py test

You can run tests for a specific app:

python manage.py test accounts

3. Writing Tests

Each app includes a tests.py template. Follow these patterns:

accounts/tests.py (DRF APIClient)

from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase

class AccountTests(APITestCase):
    def test_user_registration_and_login(self):
        url = reverse('accounts:register')
        data = {'username': 'jane', 'password': 'strongpass'}
        response = self.client.post(url, data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        login_url = reverse('accounts:login')
        response = self.client.post(login_url, data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn('token', response.data)

courses/tests.py (Unit test template)

from django.test import TestCase
from .models import Course

class CourseModelTest(TestCase):
    def test_course_creation(self):
        course = Course.objects.create(name='Math 101', code='MTH101')
        self.assertEqual(str(course), 'Math 101 (MTH101)')

Copy this structure into departments/tests.py, students/tests.py, and teachers/tests.py to validate models and APIs.

4. Adding New Apps or Roles

  1. Create the app and add to INSTALLED_APPS in settings.py:

    python manage.py startapp clubs
    
    # settings.py
    INSTALLED_APPS += ['clubs']
    
  2. Define models and run migrations:

    python manage.py makemigrations clubs
    python manage.py migrate
    
  3. Register models in admin and write tests:

    # clubs/admin.py
    from django.contrib import admin
    from .models import Club
    
    @admin.register(Club)
    class ClubAdmin(admin.ModelAdmin):
        list_display = ('name', 'created_at')
        search_fields = ('name',)
    
  4. If introducing a new user role, extend the User model or add a profile model, then hook it via signals (see next section).

5. Customizing Django Admin

accounts/admin.py

Uncomment and extend to modify user fields:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User

@admin.register(User)
class CustomUserAdmin(UserAdmin):
    list_display = ('username', 'email', 'role', 'is_active')
    list_filter = ('role', 'is_staff', 'is_active')
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        ('Personal info', {'fields': ('first_name', 'last_name', 'email')}),
        ('Permissions', {'fields': ('role', 'is_active', 'is_staff')}),
    )

courses/admin.py

Uncomment registrations and customize:

from django.contrib import admin
from .models import Course, Section

@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
    list_display = ('name', 'code', 'department')
    search_fields = ('name', 'code')

@admin.register(Section)
class SectionAdmin(admin.ModelAdmin):
    list_display = ('course', 'semester', 'instructor')
    list_filter = ('semester',)

departments/admin.py, students/admin.py, teachers/admin.py

These already register models. Extend list_display, search_fields, and filters to surface critical data.

6. Signal-Based Automation

students/signals.py

Automatically generate a student_id:

import uuid
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth import get_user_model
from .models import StudentProfile

User = get_user_model()

def generate_student_id():
    return str(uuid.uuid4()).split('-')[0].upper()

@receiver(post_save, sender=User)
def create_student_profile(sender, instance, created, **kwargs):
    if created and instance.role == 'student':
        StudentProfile.objects.create(user=instance, student_id=generate_student_id())

teachers/signals.py

Automatically create TeacherProfile with teacher_id:

import uuid
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth import get_user_model
from .models import TeacherProfile

User = get_user_model()

def generate_teacher_id():
    return f"TCHR-{uuid.uuid4().hex[:6].upper()}"

@receiver(post_save, sender=User)
def create_teacher_profile(sender, instance, created, **kwargs):
    if created and instance.role == 'teacher':
        TeacherProfile.objects.create(user=instance, teacher_id=generate_teacher_id())

Hooking Signals

Ensure your app’s apps.py imports the signals on ready():

# students/apps.py
from django.apps import AppConfig

class StudentsConfig(AppConfig):
    name = 'students'
    def ready(self):
        import students.signals

Repeat for teachers/apps.py.


By following these guidelines, you can set up your local environment, ensure code quality through tests, extend the project with new features, customize the admin interface, and automate user workflows with Django signals.