A complete, production-ready Django web application for academic analytics with role-based access control, interactive Google Charts dashboards, CSV/Excel import, PDF reports, and email notifications.
- Python 3.10+ installed
- pip (Python package manager)
cd edupulse/# Windows
python -m venv venv
venv\Scripts\activate
# macOS / Linux
python3 -m venv venv
source venv/bin/activatepip install -r requirements.txtpython manage.py migratepython manage.py create_demo_dataThis creates:
| Role | Username | Password |
|---|---|---|
| Admin | admin | admin123 |
| Faculty | faculty1 | faculty123 |
| HOD | hod1 | hod123 |
| Student | alice21 | student123 |
| Student | bob21 | student123 |
| Student | carol21 | student123 |
python manage.py collectstatic --noinputpython manage.py runserverOpen http://127.0.0.1:8000 in your browser.
edupulse/
│
├── edupulse/ # Django project config
│ ├── settings.py # All settings (DB, email, static, etc.)
│ ├── urls.py # Root URL dispatcher
│ └── wsgi.py
│
├── accounts/ # Authentication + RBAC
│ ├── models.py # Profile model (extends User)
│ ├── views.py # Login, logout, user CRUD
│ ├── forms.py # Login, register, profile forms
│ ├── decorators.py # @role_required, @admin_required, etc.
│ └── urls.py
│
├── results/ # Core academic data
│ ├── models.py # Batch, Subject, Result, UploadLog
│ ├── views.py # Upload, list, edit, export (CSV/PDF)
│ ├── forms.py # Upload form, filter form, manual entry
│ ├── utils.py # CSV/Excel parser + validator
│ └── urls.py
│
├── analytics/ # Charts and dashboards
│ ├── views.py # Dashboard views + JSON chart endpoints
│ └── urls.py
│
├── core/ # Shared utilities
│ ├── views.py # Role-based dashboard router
│ ├── signals.py # Email alert on low performance
│ ├── apps.py # Registers signals
│ └── management/
│ └── commands/
│ └── create_demo_data.py
│
├── templates/ # All HTML templates
│ ├── base.html # Master layout with sidebar
│ ├── accounts/
│ ├── results/
│ ├── analytics/
│ └── core/
│
├── static/
│ ├── css/main.css # Custom design system
│ ├── js/main.js # Google Charts loader + sidebar JS
│ └── sample_results.csv # Sample upload file
│
├── media/ # Uploaded files (runtime)
├── manage.py
└── requirements.txt
| Feature | Admin | Faculty | HOD | Student |
|---|---|---|---|---|
| Upload CSV/Excel | ✅ | ✅ | ❌ | ❌ |
| Add result manually | ✅ | ✅ | ❌ | ❌ |
| View all results | ✅ | ✅ | ✅ | ❌ |
| Delete results | ✅ | ❌ | ❌ | ❌ |
| Institution analytics | ✅ | ✅ | ✅ | ❌ |
| Subject analysis | ✅ | ✅ | ✅ | ❌ |
| View own results only | ❌ | ❌ | ❌ | ✅ |
| Download personal PDF | ❌ | ❌ | ❌ | ✅ |
| Manage users | ✅ | ❌ | ❌ | ❌ |
| Manage subjects/batches | ✅ | ❌ | ❌ | ❌ |
| Upload logs | ✅ | ❌ | ❌ | ❌ |
| Export CSV (all results) | ✅ | ✅ | ✅ | ❌ |
| Export PDF (all results) | ✅ | ✅ | ✅ | ❌ |
Your file must contain these exact column headers (row 1):
roll_number, subject_code, semester, batch_name, marks_obtained, remarks
roll_number— must match a student profile's roll numbersubject_code— must match an existing subject code (e.g. CS301)semester— integer 1–10batch_name— must match an existing batch name (e.g. 2021-2025)marks_obtained— float 0–100remarks— optional free text
A sample file is available at /static/sample_results.csv.
- File is parsed row by row
- Each row is validated (missing fields, invalid marks, unknown roll numbers, duplicates)
- Valid rows are saved; errors are displayed in a detailed error report
- An
UploadLogaudit entry is created for every upload - If a student fails, an email alert is sent automatically (if email is configured)
All charts are live and filterable via AJAX — no page reload needed.
| Chart Type | Data Shown | Filters Available |
|---|---|---|
| Pie Chart | Overall Pass vs Fail | Semester, Batch |
| Column Chart | Grade distribution (O/A+/A/…/F) | Semester, Subject |
| Line Chart | Average marks per semester | Batch, Subject |
| Bar Chart | Average marks per subject | Semester, Batch |
| Scatter Plot | Individual student performance | Semester, Subject |
| Line Chart | Personal semester trend (student) | — (auto-filtered by user) |
Email uses Django's console backend by default (prints to terminal).
To send real emails, update edupulse/settings.py:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'your-gmail@gmail.com'
EMAIL_HOST_PASSWORD = 'your-app-password' # Gmail App Password (not regular password)Email alerts fire automatically when:
- A student result is uploaded with
is_pass = False
- URL:
/results/export/csv/ - Supports filter query params:
?semester=3&batch=1&subject=2 - Downloads instantly as
results_export.csv
- URL:
/results/export/pdf/ - Generated with ReportLab
- Students get their own results only
- Staff get full institution report
- Downloads as
edupulse_report.pdf
Custom decorators in accounts/decorators.py:
from accounts.decorators import (
role_required, # @role_required('admin', 'hod')
admin_required, # @admin_required
faculty_required, # @faculty_required (admin + faculty)
hod_required, # @hod_required (admin + hod)
staff_required, # @staff_required (admin + faculty + hod)
student_required, # @student_required
)Usage:
@staff_required
def my_view(request):
...role: admin | faculty | hod | studentdepartment,phone,roll_number,bio- Auto-created via
post_savesignal on User
name,department,start_year,end_year- Unique constraint:
(name, department)
code(unique),name,department,semestermax_marks(default 100),pass_marks(default 40),credits
- FK to:
student(User),subject,batch marks_obtained,semester- Auto-calculated:
grade(O/A+/A/B+/B/C/F),is_pass - Unique constraint:
(student, subject, semester, batch)— no duplicates
- Audit trail: file name, uploader, total/success/error rows, status, timestamp
After running create_demo_data:
- Admin view: Login as
admin/admin123→ full dashboard with all 4 charts - Upload test: Go to Results → Upload → upload
static/sample_results.csv - Filter test: Results list → apply semester/batch/grade filters
- Analytics: Analytics → Institution → use dropdown filters to refresh charts live
- Student view: Login as
alice21/student123→ personal trend chart + results table - PDF report: Any role → Results → Export PDF
- Add to
Profile.ROLE_CHOICESinaccounts/models.py - Add a decorator in
accounts/decorators.py - Add a case in
core/views.py → dashboard() - Create a template:
templates/core/dashboard_<role>.html - Update sidebar in
templates/base.html
Edit Subject.pass_marks default in results/models.py.
Or update per-subject via Admin or the Subjects management page.
Edit Result.calculate_grade() in results/models.py.
# Create demo data (first time setup)
python manage.py create_demo_data
# Create a superuser manually
python manage.py createsuperuser
# Make + apply migrations after model changes
python manage.py makemigrations
python manage.py migrate
# Open Django shell
python manage.py shell
# Collect static files for production
python manage.py collectstatic- Set
DEBUG = Falseinsettings.py - Set a strong
SECRET_KEY - Configure
ALLOWED_HOSTS - Use PostgreSQL instead of SQLite for production
- Use Gunicorn + Nginx
- Set
EMAIL_BACKENDto SMTP - Run
collectstaticand serve/staticfiles/via Nginx
| Package | Version | Purpose |
|---|---|---|
| Django | ≥ 4.2 | Web framework |
| openpyxl | ≥ 3.1 | Excel (.xlsx) file parsing |
| reportlab | ≥ 4.0 | PDF report generation |
| Pillow | ≥ 10.0 | Image handling (avatars) |
- SQLite3: Zero-config default — swap to PostgreSQL for production
- Class vs Function views: Functions used throughout for simplicity and decorator clarity
- Google Charts via AJAX: All chart data served as JSON from dedicated endpoints — decoupled from page renders
- Signal-based emails: Low-performance alerts fire via Django signals — no manual calls in views
- Two-stage upload: Parse → show errors → save atomically — prevents partial bad data
- Auto-grade calculation:
Result.save()computes grade and pass/fail — never stored manually
Built with Django 4.2, Bootstrap 5, Google Charts — EduPulse © 2024