Full-Stack Web Application for Airport Operations#
Github Repository#
AeroTrack - Aviation Traffic Management System#
Full-Stack Web Application for Airport Operations#
Project Overview#
AeroTrack is a comprehensive Aviation Traffic Management System developed during my 1st year Bachelor in Computer Science and Networking as part of the SAE 2.03 curriculum. This project provided an exciting opportunity to build a complete solution for managing airport operations, including runway scheduling, flight coordination, and aircraft tracking.
This was one of my most rewarding projects as it allowed me to truly understand how databases and web systems work together, while learning valuable teamwork and collaboration skills in a group development environment.
Key Features#
🛫 Flight Management#
- Complete flight scheduling and tracking
- Real-time runway availability checking (10-minute occupancy rule)
- Automated conflict detection with alternative time suggestions
- CSV bulk import for multiple flights with validation
✈️ Aircraft & Airport Management#
- Aircraft registry with technical specifications
- Airline company database
- Airport and runway management with capacity constraints
- Image upload system for aircraft types
📊 Reporting & Analytics#
- Flight schedule generation for specific airports and date ranges
- PDF export capabilities
- Advanced search and filtering options
Technical Architecture & Infrastructure#
Multi-VM Deployment Architecture#
The project uses a two-VM architecture for production-ready deployment. Each running Debian12. One runs the database, the other runs the web server (Django, nginx and gunicorn).
Database Setup (MariaDB)#
# MariaDB Installation and Configuration
sudo apt update
sudo apt install mariadb-server mariadb-client
# Configure database to listen on internal network
nano /etc/mysql/mariadb.conf.d/50-server.cnf
# Set bind-address to 192.168.0.1
sudo systemctl restart mariadb
Web Server Deployment#
Django Environment Setup
# System Dependencies
apt install python3 python3-venv python3-pip nginx git
apt install pkg-config default-libmysqlclient-dev mariadb-client
apt install python3-full
# Project Deployment
cd /var/www/
sudo git clone https://github.com/wipeey/gestion-trafic-aerien.git
cd gestion-trafic-aerien
# Virtual Environment
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python manage.py migrate --fake-initial
python manage.py collectstatic --noinput
Gunicorn Service Configuration
# /etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
Type=notify
User=toto
Group=toto
RuntimeDirectory=gunicorn
WorkingDirectory=/var/www/gestion-trafic-aerien
ExecStart=/var/www/gestion-trafic-aerien/venv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn/gunicorn.sock \
trafic_aerien.wsgi:application
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Nginx Configuration
# /etc/nginx/sites-available/gestion-trafic-aerien
server {
listen 80;
server_name _;
location = /favicon.ico {
access_log off;
log_not_found off;
}
location /static/ {
root /var/www/gestion-trafic-aerien;
expires 30d;
add_header Cache-Control "public, immutable";
}
location /media/ {
root /var/www/gestion-trafic-aerien;
expires 30d;
add_header Cache-Control "public, immutable";
}
location / {
proxy_pass http://unix:/run/gunicorn/gunicorn.sock;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Django Application Architecture#
URL Configuration#
# urls.py - Main routing system
from django.urls import path
from . import views
urlpatterns = [
# Flight Management
path('', views.index, name='index'),
path('vols/', views.vol_list, name='vol_list'),
path('vols/create/', views.vol_create, name='vol_create'),
path('vols/<int:pk>/edit/', views.vol_edit, name='vol_edit'),
path('vols/<int:pk>/delete/', views.vol_delete, name='vol_delete'),
path('vols/import-csv/', views.vol_import, name='vol_import_csv'),
# Airport Management
path('aeroports/', views.aeroport_list, name='aeroport_list'),
path('aeroports/create/', views.aeroport_create, name='aeroport_create'),
path('aeroports/<int:pk>/edit/', views.aeroport_edit, name='aeroport_edit'),
# Aircraft Management
path('avions/', views.avion_list, name='avion_list'),
path('avions/create/', views.avion_create, name='avion_create'),
path('types-avion/', views.type_avion_list, name='type_avion_list'),
]
Forms with Advanced Validation#
# forms.py - Complex form validation with runway scheduling
class VolForm(forms.ModelForm):
class Meta:
model = Vol
fields = ['avion', 'pilote', 'aeroport_depart', 'date_heure_depart',
'aeroport_arrivee', 'date_heure_arrivee']
widgets = {
'date_heure_depart': forms.DateTimeInput(attrs={
'class': 'form-control',
'type': 'datetime-local'
}),
'date_heure_arrivee': forms.DateTimeInput(attrs={
'class': 'form-control',
'type': 'datetime-local'
}),
}
def is_piste_available(self, aeroport, heure_cible, avion):
"""Check if runway is available for 10-minute window"""
pistes_compatibles = aeroport.pistes.filter(
longueur__gte=avion.type_avion.longueur_piste_necessaire
)
if not pistes_compatibles.exists():
return False, None
# Check for conflicts with existing flights
date_cible = heure_cible.date()
vols_existants = Vol.objects.filter(
Q(aeroport_depart=aeroport, date_heure_depart__date=date_cible) |
Q(aeroport_arrivee=aeroport, date_heure_arrivee__date=date_cible)
)
# 10-minute occupancy validation logic
heure_fin_utilisation = heure_cible + timedelta(minutes=10)
for vol in vols_existants:
if vol.aeroport_depart == aeroport:
debut = vol.date_heure_depart
fin = debut + timedelta(minutes=10)
if not (heure_fin_utilisation <= debut or heure_cible >= fin):
return False, fin
return True, None
def clean(self):
cleaned_data = super().clean()
# Complex validation with runway availability checking
if avion and aeroport_arrivee and date_heure_arrivee:
disponible, _ = self.is_piste_available(aeroport_arrivee, date_heure_arrivee, avion)
if not disponible:
heure_proposee = self.suggest_next_available_time(aeroport_arrivee, date_heure_arrivee, avion)
if heure_proposee:
raise forms.ValidationError(
f"Runway unavailable at {date_heure_arrivee.strftime('%d/%m/%Y %H:%M')}. "
f"Next available slot: {heure_proposee.strftime('%d/%m/%Y %H:%M')}"
)
return cleaned_data
Views with Business Logic#
# views.py - Flight management with CSV import
def vol_create(request):
"""Create new flight with runway validation"""
if request.method == 'POST':
form = VolForm(request.POST)
if form.is_valid():
vol = form.save()
messages.success(request, 'Flight successfully created!')
return redirect('vol_list')
else:
form = VolForm()
return render(request, 'trafic_aerien/vol/form.html', {
'form': form,
'title': 'Create Flight'
})
def vol_import(request):
"""Bulk CSV import with validation"""
if request.method == 'POST':
form = CSVUploadForm(request.POST, request.FILES)
if form.is_valid():
csv_file = request.FILES['csv_file']
try:
# Parse CSV data
file_data = csv_file.read().decode('utf-8')
reader = csv.DictReader(io.StringIO(file_data))
# Validate all flights before creating any
validator = VolCSVValidator()
vols_valides = []
for i, vol_data in enumerate(list(reader)):
ligne_numero = i + 2
if validator.validate_vol_data(vol_data, ligne_numero, vols_data):
vols_valides.append(vol_data)
# Display validation errors
if validator.errors:
for error in validator.errors:
messages.error(request, error)
return render(request, 'trafic_aerien/vol/importer.html', {'form': form})
# Create flights atomically
with transaction.atomic():
for vol_data in vols_valides:
Vol.objects.create(
avion_id=vol_data['avion_id'],
pilote=vol_data['pilote'],
aeroport_depart_id=vol_data['aeroport_depart_id'],
date_heure_depart=datetime.strptime(vol_data['date_heure_depart'], '%Y-%m-%d %H:%M:%S'),
aeroport_arrivee_id=vol_data['aeroport_arrivee_id'],
date_heure_arrivee=datetime.strptime(vol_data['date_heure_arrivee'], '%Y-%m-%d %H:%M:%S')
)
messages.success(request, f'{len(vols_valides)} flights imported successfully!')
return redirect('vol_list')
except Exception as e:
messages.error(request, f'Import error: {str(e)}')
else:
form = CSVUploadForm()
return render(request, 'trafic_aerien/vol/importer.html', {'form': form})
def aeroport_list(request):
"""Display airports with search functionality"""
aeroports = Aeroport.objects.all().order_by('nom')
return render(request, 'trafic_aerien/aeroport/list.html', {
'aeroports': aeroports
})
CSV Validation System#
# utils.py - CSV validation with runway scheduling
class VolCSVValidator:
def __init__(self):
self.errors = []
def validate_vol_data(self, vol_data, ligne_numero, vols_existants=None):
"""Validate flight data with business rules"""
try:
# Object validation
avion = Avion.objects.get(id=vol_data['avion_id'])
aeroport_depart = Aeroport.objects.get(id=vol_data['aeroport_depart_id'])
aeroport_arrivee = Aeroport.objects.get(id=vol_data['aeroport_arrivee_id'])
# Date parsing
date_heure_depart = datetime.strptime(vol_data['date_heure_depart'], '%Y-%m-%d %H:%M:%S')
date_heure_arrivee = datetime.strptime(vol_data['date_heure_arrivee'], '%Y-%m-%d %H:%M:%S')
except (Avion.DoesNotExist, Aeroport.DoesNotExist, ValueError) as e:
self.errors.append(f"Line {ligne_numero}: {str(e)}")
return False
# Business logic validation
if aeroport_depart == aeroport_arrivee:
self.errors.append(f"Line {ligne_numero}: Departure and arrival airports cannot be identical")
return False
if date_heure_arrivee <= date_heure_depart:
self.errors.append(f"Line {ligne_numero}: Arrival time must be after departure time")
return False
# Runway compatibility check
pistes_adequates = aeroport_depart.pistes.filter(
longueur__gte=avion.type_avion.longueur_piste_necessaire
)
if not pistes_adequates.exists():
self.errors.append(
f"Line {ligne_numero}: No suitable runway at {aeroport_depart.nom} "
f"for aircraft {avion.nom} (requires {avion.type_avion.longueur_piste_necessaire}m)"
)
return False
return True
Database Schema#
The system manages six core entities:
Airports (id, name, country)
├── Runways (number, airport_ref, length)
├── Flights (aircraft, pilot, departure/arrival data)
Airlines (id, name, description, country)
├── Aircraft (id, name, company_ref, type_ref)
Aircraft Types (id, brand, model, image, runway_requirements)
Advanced Business Logic#
Runway Scheduling Algorithm#
- 10-minute runway occupancy enforcement
- Real-time conflict detection for departures and arrivals
- Intelligent time slot suggestions
- Cross-validation between CSV imports and existing flights
Data Validation System#
- Runway length compatibility checking
- Time sequence validation (arrival > departure)
- Airport constraint verification
- Bulk data processing with detailed error reporting
Skills Demonstrated (BUT Competencies)#
AC0311 - System Administration#
- Linux server configuration and maintenance
- Network setup with multiple VMs
- Service management (systemd, nginx, gunicorn)
AC0312-AC0313 - Programming Excellence#
- Complex Django application development
- Algorithm implementation for scheduling conflicts
- Data validation and error handling
- CSV processing with business rule enforcement
AC0314 - Web Architecture#
- MVC pattern implementation
- RESTful design principles
- Static file management and media handling
- Responsive UI development
AC0315 - Database Management#
- Relational database design and optimization
- Complex query optimization
- Data integrity enforcement
- Migration management
AC0316 - Collaborative Development#
- Git version control workflow
- Modular code architecture
- Documentation and deployment procedures
- Multi-environment configuration
Personal Learning Experience#
Working on AeroTrack was incredibly rewarding and transformative for my understanding of software development. This project taught me:
Deep Database Understanding#
Rather than just writing SQL queries, I truly grasped how relational databases work at a fundamental level - from foreign key relationships to query optimization and data integrity. Setting up MariaDB from scratch and configuring it for multi-server architecture gave me hands-on experience with real-world database administration.
Team Collaboration Skills#
This group project significantly improved my ability to work effectively in a development team. I learned valuable lessons about:
- Code collaboration using Git workflows
- Task distribution and project planning
- Communication and problem-solving with teammates
- Code review and quality assurance processes
Systems Integration#
Configuring the multi-VM architecture taught me how different system components communicate and depend on each other, providing invaluable insight into production deployment scenarios.
Development Challenges Solved#
- Complex Time Validation: Implemented sophisticated runway scheduling logic that considers both existing database entries and pending CSV imports
- File Upload Management: Created secure image upload system with validation and storage optimization
- Multi-VM Deployment: Configured secure network communication between database and web servers
- User Experience: Developed intuitive forms with real-time validation and helpful error messages
Project Impact#
AeroTrack demonstrates real-world application development skills applicable to aviation industry needs. The project showcases:
- Scalability: Multi-server architecture ready for production
- Reliability: Comprehensive validation and error handling
- Usability: Intuitive interface designed for airport operations staff
- Maintainability: Clean code architecture with proper documentation
Technical Innovation#
The runway scheduling algorithm represents a novel approach to resource management, automatically detecting conflicts and suggesting optimal alternatives. This feature could significantly improve airport operational efficiency in real-world applications.
Technologies Used: Django, MariaDB, Nginx, Gunicorn, Linux (Debian), Python, HTML/CSS, JavaScript
Academic Context: 1st Year Bachelor in Computer Science and Networking - SAE 2.03
Repository: Available on GitHub with complete deployment documentation