quantum-ai-v3/data_analyzer/management/commands/cleanup_uploads.py
Claude bfdef5b658 Refactor: Complete architecture reorganization with proper separation of concerns
BREAKING CHANGES:
- Move marketplace and agent discovery views from core to agent_base app
- Transfer all wallet functionality from core to dedicated wallet app
- Move Stripe webhook handling to wallet app for better organization
- Consolidate payment system logic under single responsibility

NEW STRUCTURE:
- core app: Platform pages only (homepage, pricing)
- agent_base app: Complete agent marketplace and catalog system
- wallet app: Full payment system with Stripe integration
- Individual agent apps: Unchanged, self-contained

IMPROVEMENTS:
- Clean URL namespacing (agent_base:marketplace, wallet:wallet)
- Template organization by app responsibility
- Removed deprecated CSS files (header.css)
- Added utility classes (.hidden)
- Updated all template references to new URL structure
- Comprehensive CLAUDE.md documentation updates

TECHNICAL CHANGES:
- Templates moved: marketplace.html, agent_detail.html → agent_base/
- Templates moved: wallet*.html → wallet/
- New files: agent_base/views.py, agent_base/urls.py, wallet/urls.py
- Updated main urls.py routing configuration
- Fixed Django system checks and namespace conflicts
- Verified all functionality with test suite

This reorganization follows Django best practices with single responsibility
principle, making the codebase more maintainable and scalable.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 20:03:53 +05:30

125 lines
4.9 KiB
Python

from django.core.management.base import BaseCommand
from django.utils import timezone
from datetime import timedelta
from data_analyzer.models import DataAnalysisAgentRequest
import os
import glob
class Command(BaseCommand):
help = 'Clean up old uploaded files from data analyzer'
def add_arguments(self, parser):
parser.add_argument(
'--age-hours',
type=int,
default=24,
help='Delete files older than this many hours (default: 24)'
)
parser.add_argument(
'--dry-run',
action='store_true',
help='Show what would be deleted without actually deleting'
)
parser.add_argument(
'--force-orphaned',
action='store_true',
help='Also delete orphaned files not associated with database records'
)
def handle(self, *args, **options):
age_hours = options['age_hours']
dry_run = options['dry_run']
force_orphaned = options['force_orphaned']
cutoff_time = timezone.now() - timedelta(hours=age_hours)
self.stdout.write(f"Looking for files older than {age_hours} hours ({cutoff_time})")
if dry_run:
self.stdout.write(self.style.WARNING("DRY RUN MODE - No files will be deleted"))
# Clean up files associated with old database records
old_requests = DataAnalysisAgentRequest.objects.filter(
created_at__lt=cutoff_time
)
deleted_count = 0
error_count = 0
for request in old_requests:
if request.data_file:
try:
file_path = request.data_file.path
if os.path.exists(file_path):
if not dry_run:
os.remove(file_path)
self.stdout.write(f"Deleted: {file_path}")
else:
self.stdout.write(f"Would delete: {file_path}")
deleted_count += 1
else:
self.stdout.write(f"File already gone: {file_path}")
except Exception as e:
self.stdout.write(
self.style.ERROR(f"Error deleting {request.data_file.path}: {e}")
)
error_count += 1
# Clean up orphaned files if requested
if force_orphaned:
self.stdout.write("Checking for orphaned files...")
try:
from django.conf import settings
upload_path = os.path.join(settings.MEDIA_ROOT, 'uploads/data_analyzer/')
if os.path.exists(upload_path):
# Get all files in upload directory
all_files = glob.glob(os.path.join(upload_path, '*'))
# Get all files currently referenced in database
db_files = set()
for request in DataAnalysisAgentRequest.objects.filter(data_file__isnull=False):
if request.data_file:
try:
db_files.add(request.data_file.path)
except:
pass
# Find orphaned files
for file_path in all_files:
if os.path.isfile(file_path) and file_path not in db_files:
file_age = timezone.now() - timezone.datetime.fromtimestamp(
os.path.getctime(file_path),
tz=timezone.get_current_timezone()
)
if file_age > timedelta(hours=age_hours):
if not dry_run:
os.remove(file_path)
self.stdout.write(f"Deleted orphaned file: {file_path}")
else:
self.stdout.write(f"Would delete orphaned file: {file_path}")
deleted_count += 1
except Exception as e:
self.stdout.write(
self.style.ERROR(f"Error checking orphaned files: {e}")
)
error_count += 1
# Summary
if dry_run:
self.stdout.write(
self.style.SUCCESS(f"DRY RUN: Would delete {deleted_count} files")
)
else:
self.stdout.write(
self.style.SUCCESS(f"Successfully deleted {deleted_count} files")
)
if error_count > 0:
self.stdout.write(
self.style.ERROR(f"Encountered {error_count} errors")
)