mirror of
https://github.com/thecyberlearn/quantum-ai-v3.git
synced 2026-08-18 12:32:58 +00:00
Implement smart database auto-detection for local/Railway compatibility
**Smart Database Configuration:** - Auto-detects environment: Railway vs Local development - Tests PostgreSQL connection before using it - Falls back to SQLite if PostgreSQL unavailable - Preserves Railway DATABASE_URL when present **Environment Detection Logic:** 1. Railway: Uses Railway's DATABASE_URL (PostgreSQL) 2. Local with DATABASE_URL: Uses specified database 3. Local with PostgreSQL running: Uses PostgreSQL 4. Local without PostgreSQL: Falls back to SQLite **New Management Command:** - `check_db`: Diagnose database configuration and connection - Shows current engine, connection status, table count - Provides troubleshooting tips for PostgreSQL setup **Solves the Compatibility Problem:** - Local development: Works without PostgreSQL setup (SQLite fallback) - Railway production: Always uses PostgreSQL (via DATABASE_URL) - No more "works locally but fails on Railway" issues - No more "needs PostgreSQL locally to test Railway compatibility" **Benefits:** - Seamless development experience - Production-development parity when PostgreSQL available - Graceful degradation to SQLite when needed - Zero configuration required for basic development 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
4e7e43c436
commit
58d56c3200
108
agent_base/management/commands/check_db.py
Normal file
108
agent_base/management/commands/check_db.py
Normal file
@ -0,0 +1,108 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
from django.db import connection
|
||||
import os
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Check current database configuration and connection'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
self.stdout.write("🔍 Database Configuration Check")
|
||||
self.stdout.write("=" * 40)
|
||||
|
||||
# Environment detection
|
||||
is_railway = bool(os.environ.get('RAILWAY_ENVIRONMENT'))
|
||||
database_url = os.environ.get('DATABASE_URL', '')
|
||||
|
||||
self.stdout.write(f"Environment: {'Railway' if is_railway else 'Local Development'}")
|
||||
self.stdout.write(f"DATABASE_URL set: {'Yes' if database_url else 'No'}")
|
||||
|
||||
if database_url:
|
||||
# Mask password in URL for display
|
||||
masked_url = database_url
|
||||
if '@' in masked_url and '://' in masked_url:
|
||||
parts = masked_url.split('://')
|
||||
if len(parts) == 2:
|
||||
scheme = parts[0]
|
||||
rest = parts[1]
|
||||
if '@' in rest:
|
||||
auth_part, host_part = rest.split('@', 1)
|
||||
if ':' in auth_part:
|
||||
user, password = auth_part.split(':', 1)
|
||||
masked_url = f"{scheme}://{user}:***@{host_part}"
|
||||
self.stdout.write(f"DATABASE_URL: {masked_url}")
|
||||
|
||||
# Current Django database configuration
|
||||
db_config = settings.DATABASES['default']
|
||||
engine = db_config['ENGINE']
|
||||
|
||||
self.stdout.write(f"\\nCurrent Django Configuration:")
|
||||
self.stdout.write(f"Engine: {engine}")
|
||||
|
||||
if 'postgresql' in engine:
|
||||
self.stdout.write(f"Database: {db_config.get('NAME', 'N/A')}")
|
||||
self.stdout.write(f"Host: {db_config.get('HOST', 'N/A')}")
|
||||
self.stdout.write(f"Port: {db_config.get('PORT', 'N/A')}")
|
||||
self.stdout.write(f"User: {db_config.get('USER', 'N/A')}")
|
||||
elif 'sqlite' in engine:
|
||||
self.stdout.write(f"Database file: {db_config.get('NAME', 'N/A')}")
|
||||
|
||||
# Test connection
|
||||
self.stdout.write(f"\\n🔌 Testing Database Connection...")
|
||||
try:
|
||||
with connection.cursor() as cursor:
|
||||
if 'postgresql' in engine:
|
||||
cursor.execute("SELECT version();")
|
||||
version = cursor.fetchone()[0]
|
||||
self.stdout.write(f"✅ PostgreSQL Connection: {version}")
|
||||
elif 'sqlite' in engine:
|
||||
cursor.execute("SELECT sqlite_version();")
|
||||
version = cursor.fetchone()[0]
|
||||
self.stdout.write(f"✅ SQLite Connection: {version}")
|
||||
|
||||
# Check if tables exist
|
||||
if 'postgresql' in engine:
|
||||
cursor.execute("""
|
||||
SELECT COUNT(*) FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
""")
|
||||
else:
|
||||
cursor.execute("""
|
||||
SELECT COUNT(*) FROM sqlite_master
|
||||
WHERE type='table' AND name NOT LIKE 'sqlite_%'
|
||||
""")
|
||||
|
||||
table_count = cursor.fetchone()[0]
|
||||
self.stdout.write(f"📊 Database tables: {table_count}")
|
||||
|
||||
if table_count == 0:
|
||||
self.stdout.write("⚠️ No tables found. Run: python manage.py migrate")
|
||||
|
||||
except Exception as e:
|
||||
self.stdout.write(f"❌ Connection failed: {e}")
|
||||
|
||||
if 'postgresql' in engine:
|
||||
self.stdout.write("\\n💡 PostgreSQL Connection Tips:")
|
||||
self.stdout.write("1. Install PostgreSQL: brew install postgresql")
|
||||
self.stdout.write("2. Start PostgreSQL: brew services start postgresql")
|
||||
self.stdout.write("3. Create database: createdb netcop_hub")
|
||||
self.stdout.write("4. Create user: createuser netcop_user -P")
|
||||
self.stdout.write("5. Or use Docker: docker run --name netcop-postgres -e POSTGRES_DB=netcop_hub -e POSTGRES_USER=netcop_user -e POSTGRES_PASSWORD=netcop_pass -p 5432:5432 -d postgres:15")
|
||||
|
||||
# Module availability check
|
||||
self.stdout.write(f"\\n📦 Module Availability:")
|
||||
try:
|
||||
import psycopg2
|
||||
self.stdout.write("✅ psycopg2 (PostgreSQL driver) available")
|
||||
except ImportError:
|
||||
self.stdout.write("❌ psycopg2 not available")
|
||||
|
||||
try:
|
||||
import sqlite3
|
||||
self.stdout.write("✅ sqlite3 available")
|
||||
except ImportError:
|
||||
self.stdout.write("❌ sqlite3 not available")
|
||||
|
||||
self.stdout.write("\\n" + "=" * 40)
|
||||
self.stdout.write("Database check complete!")
|
||||
@ -89,18 +89,70 @@ WSGI_APPLICATION = 'netcop_hub.wsgi.application'
|
||||
|
||||
import dj_database_url
|
||||
|
||||
# Use DATABASE_URL if available (Railway, Heroku, etc.)
|
||||
if config('DATABASE_URL', default=''):
|
||||
# Smart database configuration: Auto-detect environment
|
||||
database_url = config('DATABASE_URL', default='')
|
||||
|
||||
if database_url:
|
||||
# Parse the provided DATABASE_URL
|
||||
DATABASES = {
|
||||
'default': dj_database_url.parse(config('DATABASE_URL'))
|
||||
'default': dj_database_url.parse(database_url)
|
||||
}
|
||||
else:
|
||||
elif config('RAILWAY_ENVIRONMENT', default=''):
|
||||
# Railway environment without DATABASE_URL (shouldn't happen, but fallback)
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': config('PGDATABASE', default='railway'),
|
||||
'USER': config('PGUSER', default='postgres'),
|
||||
'PASSWORD': config('PGPASSWORD', default=''),
|
||||
'HOST': config('PGHOST', default='localhost'),
|
||||
'PORT': config('PGPORT', default='5432'),
|
||||
}
|
||||
}
|
||||
else:
|
||||
# Local development: Try PostgreSQL first, fallback to SQLite
|
||||
try:
|
||||
import psycopg2
|
||||
# Test if PostgreSQL is actually available
|
||||
try:
|
||||
# Quick connection test
|
||||
test_conn = psycopg2.connect(
|
||||
host='localhost',
|
||||
database='netcop_hub',
|
||||
user='netcop_user',
|
||||
password='netcop_pass',
|
||||
port='5432',
|
||||
connect_timeout=3
|
||||
)
|
||||
test_conn.close()
|
||||
|
||||
# PostgreSQL works - use it
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': 'netcop_hub',
|
||||
'USER': 'netcop_user',
|
||||
'PASSWORD': 'netcop_pass',
|
||||
'HOST': 'localhost',
|
||||
'PORT': '5432',
|
||||
}
|
||||
}
|
||||
except (psycopg2.OperationalError, psycopg2.Error):
|
||||
# PostgreSQL not available - fallback to SQLite
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
}
|
||||
}
|
||||
except ImportError:
|
||||
# psycopg2 not available - use SQLite
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
|
||||
Loading…
Reference in New Issue
Block a user