Creating an advanced-level Job Portal project involves a well-structured database and comprehensive Flask application code. Below, I will outline the database structure and provide the complete code for the Flask application, including all related pages using Bootstrap 5.
Database Structure
The database for the Job Portal will consist of the following tables:
- Users: Stores user information (job seekers and employers).
- Jobs: Stores job postings.
- Applications: Stores job applications submitted by job seekers.
- Categories: Stores job categories (e.g., IT, Marketing, Finance).
- Companies: Stores company information.
Database Models
Here’s how you can define the database models using SQLAlchemy in models.py
:
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
db = SQLAlchemy()
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), unique=True, nullable=False)
email = db.Column(db.String(100), unique=True, nullable=False)
password = db.Column(db.String(200), nullable=False)
role = db.Column(db.String(20), default='seeker') # Roles: seeker, employer
jobs = db.relationship('Job', backref='employer', lazy=True)
applications = db.relationship('Application', backref='applicant', lazy=True)
class Job(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text, nullable=False)
company_id = db.Column(db.Integer, db.ForeignKey('company.id'), nullable=False)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=False)
location = db.Column(db.String(100), nullable=False)
posted_date = db.Column(db.DateTime, default=datetime.utcnow)
employer_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
applications = db.relationship('Application', backref='job', lazy=True)
class Application(db.Model):
id = db.Column(db.Integer, primary_key=True)
job_id = db.Column(db.Integer, db.ForeignKey('job.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
resume = db.Column(db.String(200), nullable=False) # Path to the uploaded resume
cover_letter = db.Column(db.Text, nullable=True)
application_date = db.Column(db.DateTime, default=datetime.utcnow)
status = db.Column(db.String(20), default='Pending') # Status: Pending, Accepted, Rejected
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
jobs = db.relationship('Job', backref='category', lazy=True)
class Company(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text, nullable=True)
jobs = db.relationship('Job', backref='company', lazy=True)
Flask Application Structure
Here’s the directory structure for the project:
online_job_portal/
│
├── app/
│ ├── __init__.py # Initialize the Flask app and database
│ ├── models.py # Database models (User , Job, Application, Category, Company)
│ ├── routes.py # Application routes and views
│ ├── forms.py # Forms for user registration, login, job posting, and applications
│ ├── static/ # Static files (CSS, JS, images)
│ │ ├── css/
│ │ │ └── styles.css # Custom CSS styles
│ │ └── js/
│ │ └── scripts.js # Custom JavaScript files
│ └── templates/ # HTML templates
│ ├── base.html # Base layout for templates
│ ├── index.html # Home page
│ ├── login.html # Login page
│ ├── register.html # Registration page
│ ├── dashboard.html # User dashboard
│ ├── post_job.html # Job posting page
│ ├── job_detail.html # Job details page
│ └── payment.html # Payment page (if applicable)
│
├── migrations/ # Database migration files (if using Flask-Migrate)
│
├── config.py # Configuration settings for the app
│
├── requirements.txt # Python package dependencies
│
└── run.py # Entry point to run the application
Flask Application Code
1. app.py
This is the main application file where you will set up your Flask app, routes, and configurations.
from flask import Flask, render_template, redirect, url_for, flash, request, session
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, login_user, logout_user, login_required, current_user
from models import db, User, Job, Application, Category, Company
from forms import RegistrationForm, LoginForm, JobForm, ApplicationForm
import os
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///job_portal.db'
app.config['UPLOAD_FOLDER'] = 'static/uploads'
db.init_app(app)
login_manager = LoginManager()
login_manager.init_app(app)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
@app.route('/')
def index():
jobs = Job.query.all()
return render_template('index.html', jobs=jobs)
@app.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
if form.validate_on_submit():
user = User(username=form.username.data, email=form.email.data, password=form.password.data)
db.session.add(user)
db.session.commit()
flash('Registration successful! Please login.', 'success')
return redirect(url_for('login'))
return render_template('register.html', form=form)
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user and user.password == form.password.data: # Use hashed passwords in production
login_user(user)
flash('Login successful!', 'success')
return redirect(url_for('dashboard'))
flash('Login failed. Check your email and password.', 'danger')
return render_template('login.html', form=form)
@app.route('/dashboard')
@login_required
def dashboard():
jobs = Job.query.filter_by(employer_id=current_user.id).all()
return render_template('dashboard.html', jobs=jobs)
@app.route('/post_job', methods=['GET', 'POST'])
@login_required
def post_job():
form = JobForm()
if form.validate_on_submit():
job = Job(title=form.title.data, description=form.description.data, company_id=form.company_id.data,
category_id=form.category_id.data, location=form.location.data, employer_id=current_user.id)
db.session.add(job)
db.session.commit()
flash('Job posted successfully!', 'success')
return redirect(url_for('dashboard'))
return render_template('post_job.html', form=form)
@app.route('/job/<int:job_id>', methods=['GET', 'POST'])
def job_detail(job_id):
job = Job.query.get_or_404(job_id)
form = ApplicationForm()
if form.validate_on_submit():
application = Application(job_id=job.id, user_id=current_user.id, resume=form.resume.data,
cover_letter=form.cover_letter.data)
db.session.add(application)
db.session.commit()
flash('Application submitted successfully!', 'success')
return redirect(url_for('index'))
return render_template('job_detail.html', job=job, form=form)
@app.route('/logout')
@login_required
def logout():
logout_user()
flash('You have been logged out.', 'info')
return redirect(url_for('index'))
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)
2. forms.py
Define the forms for user registration, login, job posting, and job application.
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, TextAreaField, SubmitField, FileField, SelectField
from wtforms.validators import DataRequired, Email, Length
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(min=2, max=50)])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired(), Length(min=6, max=200)])
submit = SubmitField('Register')
class LoginForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
submit = SubmitField('Login')
class JobForm(FlaskForm):
title = StringField('Job Title', validators=[DataRequired()])
description = TextAreaField('Job Description', validators=[DataRequired()])
company_id = SelectField('Company', coerce=int, validators=[DataRequired()])
category_id = SelectField('Category', coerce=int, validators=[DataRequired()])
location = StringField('Location', validators=[DataRequired()])
submit = SubmitField('Post Job')
class ApplicationForm(FlaskForm):
resume = FileField('Resume', validators=[DataRequired()])
cover_letter = TextAreaField('Cover Letter', validators=[DataRequired()])
submit = SubmitField('Apply')
HTML Templates
1. base.html
This is the base template that includes the common layout for all pages.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
<title>{% block title %}Job Portal{% endblock %}</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('index') }}">Job Portal</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
{% if current_user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('dashboard') }}">Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('logout') }}">Logout</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('login') }}">Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('register') }}">Register</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
<div class="container mt-4">
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert alert-info">
{% for message in messages %}
{{ message }}<br>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
2. index.html
The homepage that displays job listings.
{% extends 'base.html' %}
{% block content %}
<h1>Welcome to the Job Portal</h1>
<p>Find your dream job!</p>
<div class="row">
{% for job in jobs %}
<div class="col-md-4">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title">{{ job.title }}</h5>
<p class="card-text">{{ job.description[:100] }}...</p>
<a href="{{ url_for('job_detail', job_id=job.id) }}" class="btn btn-primary">View Details</a>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
3. register.html
User registration page.
{% extends 'base.html' %}
{% block content %}
<h2>Register</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.username.label(class="form-label") }}
{{ form.username(class="form-control") }}
</div>
<div class="mb-3">
{{ form.email.label(class="form-label") }}
{{ form.email(class="form-control") }}
</div>
<div class="mb-3">
{{ form.password.label(class="form-label") }}
{{ form.password(class="form-control") }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
{% endblock %}
4. login.html
User login page.
{% extends 'base.html' %}
{% block content %}
<h2>Login</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.email.label(class="form-label") }}
{{ form.email(class="form-control") }}
</div>
<div class="mb-3">
{{ form.password.label(class="form-label") }}
{{ form.password(class="form-control") }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
{% endblock %}
5. dashboard.html
User dashboard to manage job postings.
{% extends 'base.html' %}
{% block content %}
<h2>Your Dashboard</h2>
<a href="{{ url_for('post_job') }}" class="btn btn-primary">Post a Job</a>
<h3>Your Jobs</h3>
<table class="table">
<thead>
<tr>
<th>Job Title</th>
<th>Location</th>
<th>Posted Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for job in jobs %}
<tr>
<td>{{ job.title }}</td>
<td>{{ job.location }}</td>
<td>{{ job.posted_date.strftime('%Y-%m-%d') }}</td>
<td>
<a href="{{ url_for('job_detail', job_id=job.id) }}" class="btn btn-info">View</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
6. post_job.html
Page for posting a new job.
{% extends 'base.html' %}
{% block content %}
<h2>Post a Job</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.title.label(class="form-label") }}
{{ form.title(class="form-control") }}
</div>
<div class="mb-3">
{{ form.description.label(class="form-label") }}
{{ form.description(class="form-control") }}
</div>
<div class="mb-3">
{{ form.company_id.label(class="form-label") }}
{{ form.company_id(class="form-control") }}
</div>
<div class="mb-3">
{{ form.category_id.label(class="form-label") }}
{{ form.category_id(class="form-control") }}
</div>
<div class="mb-3">
{{ form.location.label(class="form-label") }}
{{ form.location(class="form-control") }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
{% endblock %}
7. job_detail.html
Page to view job details and apply for the job.
{% extends 'base.html' %}
{% block content %}
<h2>{{ job.title }}</h2>
<p><strong>Company:</strong> {{ job.company.name }}</p>
<p><strong>Location:</strong> {{ job.location }}</p>
<p><strong>Description:</strong> {{ job.description }}</p>
{% if current_user.is_authenticated %}
<h3>Apply for this Job</h3>
<form method="POST" enctype="multipart/form-data">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.resume.label(class="form-label") }}
{{ form.resume(class="form-control") }}
</div>
<div class="mb-3">
{{ form.cover_letter.label(class="form-label") }}
{{ form.cover_letter(class="form-control") }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
{% else %}
<p>Please <a href="{{ url_for('login') }}">login</a> to apply for this job.</p>
{% endif %}
{% endblock %}
Static Files
1. styles.css
Add custom styles in static/css/styles.css
.
body {
background-color: #f8f9fa;
}
.navbar {
margin-bottom: 20px;
}
.table {
margin-top: 20px;
}
Running the Application
Run the Application: Start your Flask application by running:
python app.py
Access the Application: Open your web browser and go to http://127.0.0.1:5000/
to see your Job Portal in action.
Conclusion
This advanced-level Job Portal project includes a robust database structure, comprehensive Flask application code, and responsive web pages using Bootstrap 5. You can further enhance this project by adding features such as user profile management, job search functionality, notifications for job applications, and more. Additionally, consider implementing password hashing for security and file upload handling for resumes.