#!/usr/bin/env python """ Django管理コマンド: 最近のGpsLogとCheckinImagesデータを表示 docker-compose exec app python manage.py shell で実行 """ import os import sys import django from datetime import datetime, timedelta # Django設定 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') django.setup() from django.utils import timezone from rog.models import GpsLog, CheckinImages, CustomUser from django.db import connection def show_recent_data(days=7): """ 最近のチェックインデータを表示 Args: days (int): 過去何日分のデータを表示するか """ # 基準日時を計算 since_date = timezone.now() - timedelta(days=days) print(f"=== 過去{days}日間のチェックインデータ ===") print(f"検索期間: {since_date.strftime('%Y-%m-%d %H:%M:%S')} 以降") print("-" * 80) # GpsLogの最近のデータ print("\n📍 GpsLog (チェックイン記録)") print("-" * 50) recent_gpslogs = GpsLog.objects.filter( checkin_time__gte=since_date ).order_by('-checkin_time')[:20] if recent_gpslogs: print(f"件数: {len(recent_gpslogs)}件") print() print("ID | 時刻 | ゼッケン | イベント | CP | 画像URL") print("-" * 80) for log in recent_gpslogs: image_status = "✅" if log.image_address else "❌" image_url_preview = log.image_address[:40] + "..." if log.image_address and len(log.image_address) > 40 else log.image_address or "" print(f"{log.id:5d} | {log.checkin_time.strftime('%m-%d %H:%M:%S'):15s} | {log.zekken_number:8s} | {log.event_code:11s} | {log.cp_number:4s} | {image_status} {image_url_preview}") else: print("データなし") # CheckinImagesの最近のデータ print(f"\n🖼️ CheckinImages (写真記録)") print("-" * 50) recent_images = CheckinImages.objects.filter( checkintime__gte=since_date ).order_by('-checkintime')[:20] if recent_images: print(f"件数: {len(recent_images)}件") print() print("ID | 時刻 | ユーザー | チーム名 | イベント | CP | 画像ファイル") print("-" * 100) for img in recent_images: user_name = img.user.email[:12] if img.user else "Unknown" team_name = img.team_name[:12] if img.team_name else "" event_code = img.event_code[:11] if img.event_code else "" image_file = str(img.checkinimage)[:30] + "..." if len(str(img.checkinimage)) > 30 else str(img.checkinimage) print(f"{img.id:5d} | {img.checkintime.strftime('%m-%d %H:%M:%S'):15s} | {user_name:12s} | {team_name:12s} | {event_code:11s} | {img.cp_number:4d} | {image_file}") else: print("データなし") def show_summary_stats(): """ チェックインデータの統計情報を表示 """ print(f"\n📊 データベース統計") print("-" * 50) # 各テーブルの総件数 gpslog_total = GpsLog.objects.count() checkinimages_total = CheckinImages.objects.count() print(f"GpsLog 総件数: {gpslog_total:,}") print(f"CheckinImages 総件数: {checkinimages_total:,}") # 最新・最古のデータ if gpslog_total > 0: latest_gpslog = GpsLog.objects.order_by('-checkin_time').first() oldest_gpslog = GpsLog.objects.order_by('checkin_time').first() print(f"GpsLog 最新: {latest_gpslog.checkin_time.strftime('%Y-%m-%d %H:%M:%S') if latest_gpslog else 'N/A'}") print(f"GpsLog 最古: {oldest_gpslog.checkin_time.strftime('%Y-%m-%d %H:%M:%S') if oldest_gpslog else 'N/A'}") if checkinimages_total > 0: latest_image = CheckinImages.objects.order_by('-checkintime').first() oldest_image = CheckinImages.objects.order_by('checkintime').first() print(f"CheckinImages 最新: {latest_image.checkintime.strftime('%Y-%m-%d %H:%M:%S') if latest_image else 'N/A'}") print(f"CheckinImages 最古: {oldest_image.checkintime.strftime('%Y-%m-%d %H:%M:%S') if oldest_image else 'N/A'}") # 画像有りのGpsLog件数 gpslog_with_images = GpsLog.objects.exclude(image_address__isnull=True).exclude(image_address='').count() print(f"画像付きGpsLog: {gpslog_with_images:,} / {gpslog_total:,} ({gpslog_with_images/gpslog_total*100:.1f}%)" if gpslog_total > 0 else "画像付きGpsLog: 0") def show_event_breakdown(): """ イベント別のチェックイン件数を表示 """ print(f"\n🎯 イベント別チェックイン件数") print("-" * 50) # GpsLogのイベント別集計 print("GpsLog:") with connection.cursor() as cursor: cursor.execute(""" SELECT event_code, COUNT(*) as count FROM rog_gpslog GROUP BY event_code ORDER BY count DESC LIMIT 10 """) for row in cursor.fetchall(): print(f" {row[0]:15s}: {row[1]:,}件") # CheckinImagesのイベント別集計 print("\nCheckinImages:") with connection.cursor() as cursor: cursor.execute(""" SELECT event_code, COUNT(*) as count FROM rog_checkinimages GROUP BY event_code ORDER BY count DESC LIMIT 10 """) for row in cursor.fetchall(): print(f" {row[0]:15s}: {row[1]:,}件") # 引数処理 days = 7 if len(sys.argv) > 1: try: days = int(sys.argv[1]) except ValueError: print("⚠️ 日数は数値で指定してください") days = 7 print("🏃‍♂️ ロゲイニング チェックインデータ表示ツール") print("=" * 80) try: # データ表示 show_recent_data(days) show_summary_stats() show_event_breakdown() print(f"\n✅ 完了") except Exception as e: print(f"❌ エラーが発生しました: {e}") import traceback traceback.print_exc()