Chat about this codebase

AI-powered code exploration

Online

Project Overview

The Activity Monitoring Dashboard System provides a centralized platform to ingest, store and visualize user activity events. It replaces ad-hoc scripts and spreadsheets with a consistent, role-based dashboard and API, enabling real-time insights and automated reporting across your organization.

Purpose

  • Consolidate disparate activity logs (web, mobile, external systems)
  • Offer role-based access: School Admins, Human Reviewers, Monitor Companies
  • Generate alerts and reports for compliance, performance tracking, anomaly detection

Key Capabilities

  • RESTful API for event ingestion and retrieval
  • JWT-based authentication with extended claims (role, institute, monitor_comp)
  • Role-specific dashboards and data filters
  • Extensible data models for new event types
  • Pluggable notification channels (email, webhooks)

Architecture

The project follows Django’s “two-tier” structure: a core project module and feature apps.

  • monitoring_system (core project)

    • settings.py: global configuration, middleware, installed apps
    • urls.py: root URL routing
    • wsgi.py / asgi.py: deployment entry points
  • accounts (feature app)

    • Custom User model with role, institute, monitor_comp fields
    • JWT token generation via User.tokens()
    • Registration, login and profile endpoints

Directory Structure

Activity_Monitoring_Dashboard_System/
├── manage.py
├── monitoring_system/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── wsgi.py
│   └── asgi.py
├── accounts/
│   ├── __init__.py
│   ├── models.py
│   ├── serializers.py
│   ├── views.py
│   └── urls.py
├── requirements.txt
└── README.md

Quick Start

  1. Clone the repo and install dependencies
    git clone https://github.com/MrRoy2246/Activity_Monitoring_Dashboard_System.git
    cd Activity_Monitoring_Dashboard_System
    pip install -r requirements.txt
    
  2. Configure environment
    cp .env.example .env
    # Edit .env: SECRET_KEY, DATABASE_URL, EMAIL_BACKEND, etc.
    
  3. Apply migrations and create a superuser
    python manage.py migrate
    python manage.py createsuperuser
    
  4. Run the development server
    python manage.py runserver
    

Core Settings Snippet

# monitoring_system/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    # ...
    'rest_framework',
    'accounts',
]
  
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}
  
# Load secrets from environment
from decouple import config
SECRET_KEY = config('SECRET_KEY')
DATABASES = {'default': config('DATABASE_URL', cast=db_url)}

For detailed usage patterns and API references, see README.md.

Getting Started

This guide walks you through setting up a local development instance of the Activity Monitoring Dashboard System.

Prerequisites

• Python 3.8 or higher
• PostgreSQL 12+
• Git
• Virtualenv (optional but recommended)

1. Clone the Repository

git clone https://github.com/MrRoy2246/Activity_Monitoring_Dashboard_System.git
cd Activity_Monitoring_Dashboard_System

2. Create & Activate Virtual Environment

python3 -m venv venv
source venv/bin/activate        # macOS/Linux
venv\Scripts\activate.bat       # Windows

3. Install Dependencies

pip install --upgrade pip
pip install -r requirements.txt

4. Configure Environment Variables

Create a file named .env in the project root (ensure you add .env to .gitignore):

# Django settings
DJANGO_SECRET_KEY=replace-with-your-secret-key
DJANGO_DEBUG=True

# Database
DB_ENGINE=django.db.backends.postgresql
DB_NAME=activity_monitor
DB_USER=monitor_user
DB_PASSWORD=secure_password
DB_HOST=localhost
DB_PORT=5432

# Email (for account notifications)
EMAIL_HOST=smtp.example.com
EMAIL_PORT=587
EMAIL_HOST_USER=you@example.com
EMAIL_HOST_PASSWORD=your-email-password
EMAIL_USE_TLS=True

# JWT
JWT_SECRET_KEY=replace-with-jwt-secret

In monitoring_system/settings.py, these load via os.environ[...].

5. Initialize the Database

  1. Start PostgreSQL shell:

    psql -U postgres
    
  2. Create database and user:

    CREATE DATABASE activity_monitor;
    CREATE USER monitor_user WITH PASSWORD 'secure_password';
    GRANT ALL PRIVILEGES ON DATABASE activity_monitor TO monitor_user;
    \q
    

6. Apply Migrations

python manage.py migrate

This applies the accounts app’s initial schema (models Institute, MonitorCompanies, User, MonitorCompaniesWithInstitute) and all other apps.

7. Create a Superuser

python manage.py createsuperuser \
  --username admin \
  --email admin@example.com

Follow the prompts to set a password.

8. Run the Development Server

python manage.py runserver

Open your browser at http://127.0.0.1:8000/ and log in with your superuser credentials.


You now have a full local instance. From here you can explore the Django admin, customize settings in monitoring_system/settings.py, or begin developing new features.

Configuration & Environment Variables

Centralize all configurable settings in monitoring_system/settings.py. Load values from environment to customize behavior across development, staging, and production.

Environment Variables Loading

Load .env early in settings:

# settings.py
import os
from pathlib import Path
from datetime import timedelta
from dotenv import load_dotenv

BASE_DIR = Path(__file__).resolve().parent.parent
load_dotenv(BASE_DIR / ".env")

Debug, Secret Key & Allowed Hosts

Control core Django options:

SECRET_KEY = os.getenv("SECRET_KEY")
DEBUG = os.getenv("DEBUG", "False") == "True"
ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "").split(",")

.env example:

SECRET_KEY=supersecret
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1,yourdomain.com

Database Configuration

Override default database via vars:

DATABASES = {
  "default": {
    "ENGINE": "django.db.backends.postgresql",
    "NAME": os.getenv("DB_NAME", "monitoring_db"),
    "USER": os.getenv("DB_USER"),
    "PASSWORD": os.getenv("DB_PASSWORD"),
    "HOST": os.getenv("DB_HOST", "localhost"),
    "PORT": os.getenv("DB_PORT", "5432"),
  }
}

.env example:

DB_NAME=monitoring
DB_USER=monitor_user
DB_PASSWORD=secretpass
DB_HOST=db.example.com
DB_PORT=5432

CORS Settings

Allow front-end origins via comma-separated list:

INSTALLED_APPS += ["corsheaders"]
MIDDLEWARE.insert(0, "corsheaders.middleware.CorsMiddleware")

CORS_ALLOWED_ORIGINS = os.getenv("CORS_ALLOWED_ORIGINS", "").split(",")

.env example:

CORS_ALLOWED_ORIGINS=https://app.example.com,http://localhost:3000

JWT (Simple JWT) Settings

Customize token lifetimes and algorithm:

SIMPLE_JWT = {
  "ACCESS_TOKEN_LIFETIME": timedelta(minutes=int(os.getenv("ACCESS_TOKEN_LIFETIME", "60"))),
  "REFRESH_TOKEN_LIFETIME": timedelta(minutes=int(os.getenv("REFRESH_TOKEN_LIFETIME", "1440"))),
  "ALGORITHM": os.getenv("JWT_ALGORITHM", "HS256"),
  "AUTH_HEADER_TYPES": tuple(os.getenv("JWT_AUTH_HEADER_TYPES", "Bearer").split(",")),
}
REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"] = [
  "rest_framework_simplejwt.authentication.JWTAuthentication",
]

.env example:

ACCESS_TOKEN_LIFETIME=120
REFRESH_TOKEN_LIFETIME=2880
JWT_ALGORITHM=HS256
JWT_AUTH_HEADER_TYPES=Bearer

Email Backend Configuration

Configure SMTP settings for all outgoing mail:

EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = os.getenv("EMAIL_HOST", "smtp.gmail.com")
EMAIL_PORT = int(os.getenv("EMAIL_PORT", "587"))
EMAIL_USE_TLS = os.getenv("EMAIL_USE_TLS", "True") == "True"
EMAIL_HOST_USER = os.getenv("EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = os.getenv("EMAIL_HOST_PASSWORD")
DEFAULT_FROM_EMAIL = os.getenv("DEFAULT_FROM_EMAIL", EMAIL_HOST_USER)

.env example:

EMAIL_HOST=smtp.sendgrid.net
EMAIL_PORT=587
EMAIL_USE_TLS=True
EMAIL_HOST_USER=apikey
EMAIL_HOST_PASSWORD=SG.xxxxxx
DEFAULT_FROM_EMAIL=no-reply@example.com

Logging Configuration

Set global log level via LOG_LEVEL:

LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")

LOGGING = {
  "version": 1,
  "disable_existing_loggers": False,
  "handlers": {
    "console": {
      "class": "logging.StreamHandler",
      "formatter": "verbose",
    },
  },
  "formatters": {
    "verbose": {
      "format": "[{levelname}] {asctime} {name}: {message}",
      "style": "{",
    },
  },
  "root": {
    "handlers": ["console"],
    "level": LOG_LEVEL,
  },
}

.env example:

LOG_LEVEL=DEBUG

Third-Party API Keys & Security

Pull in external keys and tighten security:

# Third-party
GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
PAYSTACK_SECRET_KEY = os.getenv("PAYSTACK_SECRET_KEY")

# Security
CSRF_TRUSTED_ORIGINS = os.getenv("CSRF_TRUSTED_ORIGINS", "").split(",")
SECURE_SSL_REDIRECT = os.getenv("SECURE_SSL_REDIRECT", "True") == "True"
SESSION_COOKIE_SECURE = os.getenv("SESSION_COOKIE_SECURE", "True") == "True"

.env example:

GOOGLE_API_KEY=AIzaSy...
PAYSTACK_SECRET_KEY=sk_test_xxx
CSRF_TRUSTED_ORIGINS=https://app.example.com
SECURE_SSL_REDIRECT=True
SESSION_COOKIE_SECURE=True

Feature Flags

Toggle features without code changes:

FEATURE_X_ENABLED = os.getenv("FEATURE_X_ENABLED", "False") == "True"
FEATURE_Y_ENABLED = os.getenv("FEATURE_Y_ENABLED", "False") == "True"

Use flags in code:

from django.conf import settings

if settings.FEATURE_X_ENABLED:
    # activate new workflow
    ...

.env example:

FEATURE_X_ENABLED=True
FEATURE_Y_ENABLED=False

Tailor each environment variable in your .env file to match your deployment requirements. Restart the application after any change to ensure settings reload.

Authentication & Permissions

This section covers how the system authenticates users via JWTs, defines roles, and protects API endpoints using custom DRF permission classes.

JWT Token Generation with Custom Claims

Every user instance exposes a .tokens() method that returns an access/refresh pair enriched with user-specific data.

# accounts/models.py
from rest_framework_simplejwt.tokens import RefreshToken
import jwt
from django.conf import settings

class User(AbstractBaseUser, PermissionsMixin):
    # … fields: id, username, email, role, institute, monitor_comp …

    def tokens(self):
        # 1. Create base tokens
        refresh = RefreshToken.for_user(self)
        access = refresh.access_token

        # 2. Decode and inject custom claims
        decoded = jwt.decode(str(access), settings.SECRET_KEY, algorithms=["HS256"])
        decoded.update({
            "id": str(self.id),
            "name": self.username,
            "email": self.email,
            "role": self.role
        })
        if self.role in (3, 4, 5):
            if self.institute:
                decoded["institute"] = str(self.institute.id)
            elif self.monitor_comp:
                decoded["monitor_comp"] = str(self.monitor_comp.id)

        # 3. Re-encode access token
        access_token = jwt.encode(decoded, settings.SECRET_KEY, algorithm="HS256")

        # 4. Mirror claims in refresh token
        decoded_refresh = jwt.decode(str(refresh), settings.SECRET_KEY, algorithms=["HS256"])
        decoded_refresh.update(decoded)
        refresh_token = jwt.encode(decoded_refresh, settings.SECRET_KEY, algorithm="HS256")

        return {"access": access_token, "refresh": refresh_token}

Practical Usage

# accounts/views.py (Login endpoint snippet)
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from django.contrib.auth import authenticate
from accounts.serializers import UserSerializer

class LoginView(APIView):
    def post(self, request):
        user = authenticate(
            username=request.data["username"],
            password=request.data["password"]
        )
        if not user:
            return Response({"detail": "Invalid credentials"}, status=status.HTTP_401_UNAUTHORIZED)

        tokens = user.tokens()
        return Response({
            "user": UserSerializer(user).data,
            "access": tokens["access"],
            "refresh": tokens["refresh"]
        })

Tips & Gotchas

  • Ensure settings.SECRET_KEY matches SimpleJWT’s signing key.
  • Keep custom claims minimal to limit token size.

Role-Based Permission Classes

The repository defines these DRF permission classes in accounts/permissions.py:

  • SystemAdminPermission
    Allows only users with role == ROLE_SYSTEM_ADMIN.
  • SchoolAdminPermission
    Allows only users with role == ROLE_SCHOOL_ADMIN and an associated institute.
  • HumanReviewerPermission
    Allows only users with role == ROLE_HUMAN_REVIEWER.
  • UserPermission
    Allows only authenticated end-users (role == ROLE_USER).
  • HasValidSecretKey
    Checks for a secret header (X-SECRET-KEY) matching settings.SECRET_KEY.
  • AnyOfPermissions
    Combines multiple classes with OR logic: grants access if any sub-permission allows it.

Basic View Protection

from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from accounts.permissions import SystemAdminPermission, HasValidSecretKey

class InstituteListView(APIView):
    authentication_classes = [JWTAuthentication]
    permission_classes = [AnyOfPermissions(SystemAdminPermission, HasValidSecretKey)]

    def get(self, request):
        institutes = Institute.objects.all()
        serializer = InstituteSerializer(institutes, many=True)
        return Response(serializer.data)

Combining Permissions: AnyOfPermissions

Use AnyOfPermissions to avoid deep nesting when multiple roles or mechanisms may grant access.

# accounts/permissions.py (simplified)
from rest_framework.permissions import BasePermission

class AnyOfPermissions(BasePermission):
    def __init__(self, *perms):
        self.perms = perms

    def has_permission(self, request, view):
        return any(perm().has_permission(request, view) for perm in self.perms)

Example: Reports Endpoint

from rest_framework.views import APIView
from accounts.permissions import (
    AnyOfPermissions, HasValidSecretKey,
    SystemAdminPermission, HumanReviewerPermission
)

class ReportsView(APIView):
    permission_classes = [
        AnyOfPermissions(
            HasValidSecretKey,
            SystemAdminPermission,
            HumanReviewerPermission
        )
    ]

    def get(self, request):
        data = generate_reports()
        return Response(data)

Protecting CRUD Endpoints

User Management

from rest_framework.viewsets import ModelViewSet
from accounts.models import User
from accounts.serializers import UserSerializer
from accounts.permissions import AnyOfPermissions, SystemAdminPermission, SchoolAdminPermission

class UserViewSet(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [
        AnyOfPermissions(SystemAdminPermission, SchoolAdminPermission)
    ]

Institute & MonitorCompany Management

from rest_framework.viewsets import ModelViewSet
from accounts.models import Institute, MonitorCompanies
from accounts.serializers import InstituteSerializer, MonitorCompanySerializer
from accounts.permissions import SystemAdminPermission

class InstituteViewSet(ModelViewSet):
    queryset = Institute.objects.all()
    serializer_class = InstituteSerializer
    permission_classes = [SystemAdminPermission]

class MonitorCompanyViewSet(ModelViewSet):
    queryset = MonitorCompanies.objects.all()
    serializer_class = MonitorCompanySerializer
    permission_classes = [SystemAdminPermission]

Summary

  • Use User.tokens() to generate JWTs with embedded user, role, and scope claims.
  • Protect endpoints with role-specific permissions and HasValidSecretKey.
  • Combine OR logic with AnyOfPermissions for flexible access control.
  • Apply permission_classes on views/viewsets to enforce these rules consistently.

Accounts API Reference

Practical guide to all publicly available REST endpoints in the accounts app. Endpoints are grouped by function, show example requests/responses and list required permissions.


1. Authentication

1.1 Obtain JWT Tokens

POST /accounts/token/
Permissions: Public
Request

POST /accounts/token/ HTTP/1.1
Content-Type: application/json

{
  "email": "alice@example.com",
  "password": "Secret123!"
}

Response (200)

{
  "refresh": "<refresh_token>",
  "access": "<access_token>",
  "email": "alice@example.com",
  "id": 42,
  "status": "success"
}

1.2 Refresh Access Token

POST /accounts/token/refresh/
Permissions: Public
Request

{ "refresh": "<your_refresh_token>" }

Response (200)

{ "access": "<new_access_token>" }

1.3 Verify Token

POST /accounts/token/verify/
Permissions: Public
Request

{ "token": "<any_jwt_token>" }

Response:

  • 200 OK (valid)
  • 401 Unauthorized / 400 Bad Request (invalid/expired)

1.4 Login (Alternate)

POST /accounts/login/
Permissions: Public
Returns user info plus tokens.
Request

{ "email": "alice@example.com", "password": "Secret123!" }

Response (200)

{
  "access": "<access_token>",
  "refresh": "<refresh_token>",
  "user": {
    "id": 42,
    "username": "alice",
    "email": "alice@example.com",
    "role": 2
  }
}

1.5 Logout

POST /accounts/logout/
Permissions: Authenticated
Headers:
Authorization: Bearer <access_token>
Response (200)

{ "detail": "Successfully logged out." }

2. Registration & Email Verification

2.1 Register a New User

POST /accounts/register/
Permissions: Public
Request

{
  "username": "jdoe",
  "email": "jdoe@example.com",
  "password": "StrongP@ssw0rd",
  "role": 3,
  "phone_number": "555-1234"
}

Response (201)

{
  "id": 99,
  "username": "jdoe",
  "email": "jdoe@example.com",
  "role": 3,
  "phone_number": "555-1234",
  "is_verified": false
}

Notes
• A verification email contains GET /accounts/verify-email/?token=<JWT>.
• Frontend should redirect user to login on success.

2.2 Verify Email

GET /accounts/verify-email/?token=
Permissions: Public
Response: HTTP 302 redirect to settings.REDIRECT_URL_LOGIN if token valid; 400 if invalid.


3. User Management (CRUD)

All under /accounts/users/ via DRF router.

Method Path Description Permissions
GET /accounts/users/ List all users System Admin, Tools Admin
POST /accounts/users/ Create new user System Admin, Tools Admin
GET /accounts/users/{id}/ Retrieve specific user System Admin, Tools Admin
PUT /accounts/users/{id}/ Update user fields System Admin, Tools Admin, Institute Admin (own institute)
DELETE /accounts/users/{id}/ Delete a user System Admin

Example: Update a user's role

curl -X PUT https://api.example.com/accounts/users/99/ \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"role": 2}'

Response (200)

{
  "id": 99,
  "username": "jdoe",
  "email": "jdoe@example.com",
  "role": 2,
  "is_verified": true
}

4. Institute & Monitor Management

4.1 Institutes

Endpoints under /accounts/institutes/ (DRF router).

Method Path Permissions
GET /accounts/institutes/ System Admin, Tools Admin
POST /accounts/institutes/ System Admin, Tools Admin
GET /accounts/institutes/{id}/ System Admin, Tools Admin
PUT /accounts/institutes/{id}/ System Admin, Tools Admin
DELETE /accounts/institutes/{id}/ System Admin

Example: Create an institute

curl -X POST https://api.example.com/accounts/institutes/ \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Health Center A", "address": "123 Main St" }'

4.2 Monitors (Partners)

Endpoints under /accounts/monitors/.

Method Path Permissions
GET /accounts/monitors/ Institute Admin, Tools Admin
POST /accounts/monitors/ Institute Admin, Tools Admin
GET /accounts/monitors/{id}/ Institute Admin, Tools Admin
PUT /accounts/monitors/{id}/ Institute Admin, Tools Admin
DELETE /accounts/monitors/{id}/ Institute Admin, Tools Admin

5. Password Reset & Change

5.1 Request Password Reset

POST /accounts/password-reset/
Permissions: Public
Request

{ "email": "jdoe@example.com" }

Response (200)

{ "detail": "Password reset link sent." }

5.2 Confirm Password Reset

POST /accounts/password-reset/confirm/
Permissions: Public
Request

{
  "token": "<reset_token>",
  "password": "NewStrongP@ss1"
}

Response (200)

{ "detail": "Password has been reset." }

5.3 Change Password

POST /accounts/password-change/
Permissions: Authenticated
Headers:
Authorization: Bearer <access_token>
Request

{
  "old_password": "OldP@ssw0rd",
  "new_password": "NewStrongP@ss1"
}

Response (200)

{ "detail": "Password updated successfully." }

Usage Patterns

  1. Signup & Verify
    • POST /accounts/register/ → user clicks emailed link → GET /accounts/verify-email/.
  2. Authenticate
    • POST /accounts/token/ → store tokens → use Authorization: Bearer <access>.
  3. Maintain Session
    • POST /accounts/token/refresh/ before expiry.
  4. Manage Users & Orgs
    • Use CRUD endpoints under /accounts/users/, /accounts/institutes/, /accounts/monitors/.
  5. Password Workflows
    • Initiate reset if forgotten, or change via authenticated endpoint.

Deployment

This section guides you through deploying the Activity Monitoring Dashboard System in production. It covers WSGI vs ASGI, environment hardening, static/media handling, and common deployment recipes (Docker, Gunicorn, Daphne).

Choosing WSGI vs ASGI

WSGI (Synchronous)

Use WSGI for standard HTTP endpoints and minimal async requirements.
Entry point: monitoring_system/wsgi.py

Basic Gunicorn command:

gunicorn monitoring_system.wsgi:application \
  --bind 0.0.0.0:8000 \
  --workers 3 \
  --log-level info

ASGI (Asynchronous)

Use ASGI if you leverage async views, WebSockets or Django Channels.
Entry point: monitoring_system/asgi.py

Basic Daphne command:

daphne \
  -b 0.0.0.0 -p 8000 \
  monitoring_system.asgi:application

Environment Variables & Security Hardening

Store secrets and runtime settings in environment variables. Example .env:

SECRET_KEY=your-secret-key
DEBUG=False
ALLOWED_HOSTS=dashboard.example.com
DATABASE_URL=postgres://user:pass@db:5432/monitoring
EMAIL_HOST=smtp.mailgun.org
EMAIL_HOST_USER=postmaster@mg.example.com
EMAIL_HOST_PASSWORD=mailgun-password

Key production settings in settings.py:

DEBUG = os.getenv("DEBUG") == "True"
SECRET_KEY = os.getenv("SECRET_KEY")
ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "").split(",")

# Security hardening
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
X_FRAME_OPTIONS = "DENY"

Static & Media Handling

In settings.py:

STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "mediafiles"
# Use WhiteNoise for simple static serving
MIDDLEWARE.insert(1, "whitenoise.middleware.WhiteNoiseMiddleware")

Before starting your server, run:

python manage.py collectstatic --noinput

Serve static/media via:

  • WhiteNoise (built-in)
  • Nginx (recommended for high scale)
  • Cloud storage (S3, GCS) using django-storages

Deployment Recipes

Docker + Gunicorn

Dockerfile:

FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN python manage.py collectstatic --noinput

EXPOSE 8000
CMD ["gunicorn", "monitoring_system.wsgi:application", \
     "--bind", "0.0.0.0:8000", \
     "--workers", "4", \
     "--log-level", "info"]

docker-compose.yml:

version: "3.8"
services:
  web:
    build: .
    env_file: .env
    ports:
      - "8000:8000"
    depends_on:
      - db
  db:
    image: postgres:15
    environment:
      POSTGRES_DB: monitoring
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass

Docker + Daphne (for ASGI)

Dockerfile:

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN python manage.py collectstatic --noinput

EXPOSE 8000
CMD ["daphne", "-b", "0.0.0.0", "-p", "8000", "monitoring_system.asgi:application"]

Direct Server Commands

Gunicorn (sync):

export $(cat .env | xargs)
python manage.py migrate
python manage.py collectstatic --noinput
gunicorn monitoring_system.wsgi:application \
  --bind 0.0.0.0:8000 \
  --workers 4

Daphne (async):

export $(cat .env | xargs)
python manage.py migrate
python manage.py collectstatic --noinput
daphne -b 0.0.0.0 -p 8000 monitoring_system.asgi:application

Nginx Reverse Proxy (example)

server {
    listen 80;
    server_name dashboard.example.com;

    location /static/ {
        alias /app/staticfiles/;
    }
    location /media/ {
        alias /app/mediafiles/;
    }
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
    }
}

With these recipes, you can deploy the Activity Monitoring Dashboard System robustly and securely in your production environment.