An automated campus recruitment management system built with Flask (REST API) + Vue.js (SPA frontend), featuring role-based access control, async background tasks, and Redis caching.
- Overview
- Features
- Tech Stack
- Project Structure
- Getting Started
- Environment Setup
- Running the App
- API Endpoints
- Caching Strategy
- Async Tasks
- Milestones
The Placement Portal automates the entire campus placement lifecycle — from student registration and company onboarding to drive management, application tracking, and offer letter generation. It supports three roles:
| Role | Capabilities |
|---|---|
| Admin | Approve/reject companies and drives, manage all users, view all applications |
| Company | Post drives, manage applicants, schedule interviews, update application status |
| Student | Browse drives, apply, track application status, download offer letters |
- 🔐 Token-based authentication with role-based access (Flask-Security)
- 👤 Student profile management with resume upload (PDF / DOC / DOCX)
- 🏢 Company onboarding with admin approval workflow
- 📋 Placement drive posting with deadline enforcement
- 📨 Full application lifecycle (Applied → Shortlisted → Interview → Selected / Rejected)
- 📄 Offer letter generation and download for selected students
- 🔍 Full-text search across drives, students, and companies
- ⚡ Redis caching on all high-traffic GET endpoints
- 📤 Async CSV export via Celery (delivered by email)
- 📧 Email notifications via Flask-Mail (Gmail SMTP)
- 🚫 Blacklist and deactivate students/companies
| Technology | Purpose |
|---|---|
| Flask | Core web framework |
| Flask-RESTful | REST API resource routing |
| Flask-Security | Authentication, roles, token auth |
| SQLAlchemy | ORM for database models |
| SQLite | Relational database |
| Flask-Caching | Redis-backed response caching |
| Redis | Cache store + Celery message broker |
| Celery | Async background task queue |
| Flask-Mail | Email via Gmail SMTP |
| Flask-CORS | Cross-origin requests (Vue ↔ Flask) |
| Technology | Purpose |
|---|---|
| Vue.js 3 | Reactive SPA framework |
| Pinia | State management |
| Axios | HTTP client |
| Bootstrap 5 | Responsive UI styling |
placement-portal-v2/
├── backend/
│ ├── app.py # Flask app factory + API route registration
│ ├── celery_app.py # Celery instance configuration
│ ├── tasks.py # Background tasks (CSV export, email)
│ ├── requirements.txt # Python dependencies
│ ├── .env # Environment variables (not committed)
│ └── controllers/
│ ├── models.py # SQLAlchemy models
│ ├── database.py # db = SQLAlchemy()
│ ├── cache.py # cache = Cache()
│ ├── config.py # App configuration
│ ├── user_datastore.py # Flask-Security datastore
│ ├── student_apis.py # Student endpoints
│ ├── company_apis.py # Company endpoints
│ └── admin_apis.py # Admin endpoints
│
└── frontend/
├── src/
│ ├── main.js
│ ├── App.vue
│ ├── router/
│ ├── stores/ # Pinia stores
│ ├── views/ # Page components
│ └── components/ # Reusable components
├── public/
└── package.json
Make sure you have these installed:
- Python 3.10+
- Node.js 18+
- Redis Server
Download and run Redis for Windows or use WSL:
wsl --install
sudo apt install redis-server
sudo service redis startbrew install redis
brew services start redissudo apt install redis-server
sudo systemctl start redisVerify Redis is running:
redis-cli ping # should return PONGcd backend
# Create virtual environment
python -m venv venv
# Activate (Windows)
venv\Scripts\activate
# Activate (macOS/Linux)
source venv/bin/activate
# Install dependencies
pip install -r requirements.txtCreate a .env file in the backend/ folder:
SECRET_KEY=your-secret-key-here
SECURITY_PASSWORD_SALT=your-salt-here
# Mail (Gmail SMTP)
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-gmail-app-password
# Redis
REDIS_URL=redis://localhost:6379
# Upload folder
RESUME_FOLDER=static/resumesGmail App Password: Go to Google Account → Security → 2-Step Verification → App Passwords → Generate one for "Mail".
cd frontend
npm installYou need 4 terminals running simultaneously:
redis-servercd backend
venv\Scripts\activate # Windows
# source venv/bin/activate # macOS/Linux
python app.pyBackend runs at → http://localhost:5000
cd backend
venv\Scripts\activate
# Windows
celery -A celery_app.celery worker --loglevel=info --pool=solo
# macOS/Linux
celery -A celery_app.celery worker --loglevel=infocd frontend
npm run devFrontend runs at → http://localhost:5173
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/auth/register/student |
Register student |
| POST | /api/auth/register/company |
Register company |
| POST | /api/login |
Login → returns auth token |
| POST | /api/logout |
Logout |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/student/dashboard |
Dashboard stats |
| GET / PUT | /api/student/profile |
View / update profile |
| POST / DELETE | /api/student/resume |
Upload / delete resume |
| GET | /api/student/resume/<id> |
View resume (role-gated) |
| GET | /api/student/drives |
Browse approved drives |
| POST | /api/student/drives/<id>/apply |
Apply to drive |
| GET | /api/student/applications |
My applications |
| GET | /api/student/applications/<id>/offer |
Download offer letter |
| POST | /api/student/export |
Export CSV (async) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/company/dashboard |
Company stats |
| GET / PUT | /api/company/profile |
View / update profile |
| GET / POST | /api/company/drives |
List drives / Post new drive |
| PUT / DELETE | /api/company/drives/<id> |
Edit / delete drive |
| GET | /api/company/drives/<id>/applications |
View applicants |
| PUT | /api/company/applications/<id> |
Update application status |
| POST | /api/company/export |
Export CSV (async) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/admin/dashboard |
System stats |
| GET | /api/admin/companies |
List all companies |
| PUT / DELETE | /api/admin/companies/<id> |
Approve / blacklist / delete |
| GET | /api/admin/students |
List all students |
| PUT / DELETE | /api/admin/students/<id> |
Blacklist / activate / delete |
| GET | /api/admin/drives |
List all drives |
| PUT / DELETE | /api/admin/drives/<id> |
Approve / reject / delete |
| GET | /api/admin/applications |
All applications |
Full OpenAPI 3.0 spec available in
api.yaml
Redis caching is applied on all high-traffic GET endpoints using Flask-Caching.
| Cache Key | Timeout | Invalidated When |
|---|---|---|
student_dashboard_{id} |
2 min | Profile update, resume change, apply, status change |
student_drives_all |
10 min | Drive approved/rejected/deleted, drive edited |
company_dashboard_{id} |
2 min | New drive, application status change |
company_drives_{id} |
5 min | Drive posted, edited, deleted |
company_applications_{id}_{drive} |
2 min | Application status updated |
company_profile_{id} |
5 min | Profile updated |
admin_dashboard |
2 min | Any user/drive/company change |
admin_company_list |
5 min | Company approved, blacklisted, deleted |
admin_student_list |
5 min | Student blacklisted, activated, deleted |
admin_drive_list |
5 min | Drive approved, rejected, deleted |
admin_application_list |
2 min | Application status updated |
Important: Per-student fields (
already_applied,can_apply) are never cached — they are always computed fresh and merged into the cached base drive data.
Two background tasks run via Celery with Redis as the message broker:
| Task | Trigger | Delivers |
|---|---|---|
export_student_csv |
POST /api/student/export |
CSV of student's applications → email |
export_company_csv |
POST /api/company/export |
CSV of all applicants → email |
| # | Milestone | Status |
|---|---|---|
| 1 | User Authentication & Role-Based Access | ✅ Done |
| 2 | Student Profile & Resume Management | ✅ Done |
| 3 | Company Profile Management | ✅ Done |
| 4 | Placement Drive Management | ✅ Done |
| 5 | Application Management | ✅ Done |
| 6 | Admin Dashboard & Controls | ✅ Done |
| 7 | Async Tasks with Celery + Email | ✅ Done |
| 8 | API Performance Optimization with Redis | ✅ Done |
Gaurav Tomar IIT Madras BS Degree Program — Application Development II
This project is submitted as part of the IIT Madras BS Degree coursework.