A robust, full-stack web application built with Django designed to model and manage a modern metropolitan rail network. The system provides core functionalities for user authentication, dynamic route calculation, ticket purchasing, and interactive network visualization, all deployed efficiently using a Dockerized, multi-container architecture.
The system's strength lies in its ability to handle complex network data and present it in an accessible format:
| Feature Category | Description | Technical Implementation |
|---|---|---|
| Network Data Modeling | Manages Stations, Lines, and the relationships between them (Neighbors) within a relational database. | Django Models (Station, Line, etc.) with prefetch_related for optimized data retrieval. |
| Efficient Route Calculation | Calculates the shortest or most efficient path between any two active stations in the network. | NetworkX integration in utils.py, using the Breadth-First Search (BFS) algorithm to find paths through the graph structure defined by station neighbors. |
| Dynamic Network Mapping | Generates a visually interactive, force-directed graph of the entire operational rail network, cached for performance. | Pyvis (a wrapper for Vis.js) used by create_map in utils.py to convert the NetworkX graph into an embedded, navigable HTML visualization. |
| Database Population | Provides a custom management command (populate_data) to quickly seed the entire database with initial metro line, station, and connection data. |
Custom Django management command: populate_data. |
| User Authentication | Provides secure, comprehensive workflows for user registration, login, and profile management. | django-allauth integrated for a professional and secure authentication experience. |
The system is deployed using a standard three-tier service architecture defined in compose.prod.yaml:
| Service Name | Docker Image | Role in System |
|---|---|---|
db |
postgres:14-alpine |
Database server. |
web |
Custom Image (built from Dockerfile.prod) |
Application server running Gunicorn. Configured to wait for the database before launching. |
nginx |
nginx:alpine |
Reverse Proxy and Static/Media File Server. Handles all external traffic and serves assets directly from volumes. |
All critical data is stored outside the application containers using named Docker Volumes, which are shared between services.
postgres_data: Persists all database files.static_volume: Stores files generated bycollectstatic, shared read-only with Nginx.media_volume: Stores dynamically generated files (like the map HTML), shared read-only with Nginx.
Prerequisites: Docker, Docker Compose, and a working internet connection.
-
Clone the Repository:
git clone [https://github.com/DE41H/django-metro-ticketing-system.git](https://github.com/DE41H/django-metro-ticketing-system.git) cd django-metro-ticketing-system -
Configure Environment Variables: Create a file named
.env.prodin the root directory. This file centralizes all secrets and configuration parameters required bysettings.py.# .env.prod: REQUIRED PARAMETERS DEBUG=0 DJANGO_SECRET_KEY={your-django-secret-key} ALLOWED_HOSTS=localhost web nginx 127.0.0.0 CLIENT_SECRET={your-google-auth-client-secret} CLIENT_ID={your-google-auth-client-id} EMAIL_HOST_USER={your-email-host-email-id} EMAIL_HOST_PASSWORD={your-email-host-app-password} POSTGRES_DB=metro_prod_db POSTGRES_PASSWORD={your-db-password} POSTGRES_USER=metro_prod_user
-
Build and Start All Services: The containers are configured to ensure services start in the correct order, with the
webcontainer waiting for thedbto be healthy.docker compose -f compose.prod.yaml up --build -d
-
One-Time Setup (Minimal Manual Commands):
-
Populate Initial Data: Seed the database with the core metro structure (Stations, Lines).
docker compose -f compose.prod.yaml exec web python manage.py populate_data -
Create Superuser: Create an administrative account.
docker compose -f compose.prod.yaml exec web python manage.py createsuperuser -
Access: The application is now running at
http://localhost/.
-
For local development, we use Docker Compose to create a consistent environment, leveraging bind mounts so that code changes are instantly reflected without rebuilding the container.
- Docker and Docker Compose.
-
Configure Environment Variables: Create a
.env.devfile for local, non-sensitive credentials.# .env.dev DEBUG=1 DJANGO_SECRET_KEY={your-django-secret-key} ALLOWED_HOSTS=localhost CLIENT_SECRET={your-google-auth-client-secret} CLIENT_ID={your-google-auth-client-id} EMAIL_HOST_USER={your-email-host-email-id} EMAIL_HOST_PASSWORD={your-email-host-app-password} POSTGRES_DB=metro_dev_db POSTGRES_PASSWORD={your-db-password} POSTGRES_USER=metro_dev_user
-
Build and Start Containers:
docker compose -f compose.dev.yaml up --build -d
-
One-Time Setup: Execute the necessary commands against the running
webcontainer:# Create superuser (optional) docker compose exec web python manage.py createsuperuser
-
Access: The development server is typically accessible at
http://localhost/. Changes to your code on your local machine will trigger the server to reload inside the container.