almost finish migrate new circumstances
This commit is contained in:
@ -1,18 +1,49 @@
|
||||
|
||||
|
||||
# 既存のインポート部分に追加
|
||||
from rest_framework.decorators import api_view
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from rog.models import NewEvent2, Entry, GpsLog
|
||||
from rog.models import NewEvent2, Entry, GpsCheckin, Team
|
||||
import logging
|
||||
from django.db.models import F, Q
|
||||
from django.conf import settings
|
||||
import os
|
||||
from urllib.parse import urljoin
|
||||
from urllib.parse import urljoin, quote
|
||||
from django.http import JsonResponse
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.views.decorators.http import require_http_methods
|
||||
import boto3
|
||||
from botocore.exceptions import ClientError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def generate_image_url(image_address, event_code, zekken_number):
|
||||
"""
|
||||
画像アドレスからS3 URLまたは適切なURLを生成
|
||||
"""
|
||||
if not image_address:
|
||||
return None
|
||||
|
||||
# 既にHTTP URLの場合はそのまま返す
|
||||
if image_address.startswith('http'):
|
||||
return image_address
|
||||
|
||||
# simulation_image.jpgなどのテスト画像の場合はS3にないのでスキップ
|
||||
if image_address in ['simulation_image.jpg', 'test_image']:
|
||||
return f"/media/{image_address}"
|
||||
|
||||
# S3パスを構築してURLを生成
|
||||
s3_key = f"{event_code}/{zekken_number}/{image_address}"
|
||||
|
||||
try:
|
||||
# S3 URLを生成
|
||||
s3_url = f"https://{settings.AWS_STORAGE_BUCKET_NAME}.s3.{settings.AWS_S3_REGION_NAME}.amazonaws.com/{quote(s3_key)}"
|
||||
return s3_url
|
||||
except Exception as e:
|
||||
# S3設定に問題がある場合はmediaパスを返す
|
||||
return f"/media/{image_address}"
|
||||
|
||||
|
||||
"""
|
||||
解説
|
||||
この実装では以下の処理を行っています:
|
||||
@ -113,7 +144,7 @@ def get_photo_list_prod(request):
|
||||
|
||||
# パスワード検証
|
||||
if not hasattr(entry, 'password') or entry.password != password:
|
||||
logger.warning(f"Invalid password for team: {entry.team_name}")
|
||||
logger.warning(f"Invalid password for team: {entry.team.team_name if entry.team else 'Unknown'}")
|
||||
return Response({
|
||||
"status": "ERROR",
|
||||
"message": "パスワードが一致しません"
|
||||
@ -128,154 +159,49 @@ def get_photo_list_prod(request):
|
||||
"message": "サーバーエラーが発生しました"
|
||||
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
def get_team_photos(zekken_number, event_code):
|
||||
def get_team_photos(request):
|
||||
"""
|
||||
チームの写真とレポートURLを取得する共通関数
|
||||
チーム別の写真データを取得するAPI
|
||||
"""
|
||||
try:
|
||||
# イベントの存在確認
|
||||
event = NewEvent2.objects.filter(event_name=event_code).first()
|
||||
if not event:
|
||||
logger.warning(f"Event not found: {event_code}")
|
||||
return Response({
|
||||
"status": "ERROR",
|
||||
"message": "指定されたイベントが見つかりません"
|
||||
}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
# チームの存在確認
|
||||
entry = Entry.objects.filter(
|
||||
event=event,
|
||||
zekken_number=zekken_number
|
||||
).first()
|
||||
|
||||
if not entry:
|
||||
logger.warning(f"Team with zekken number {zekken_number} not found in event: {event_code}")
|
||||
return Response({
|
||||
"status": "ERROR",
|
||||
"message": "指定されたゼッケン番号のチームが見つかりません"
|
||||
}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
# チームの基本情報を取得
|
||||
team_info = {
|
||||
"team_name": entry.team_name,
|
||||
"zekken_number": entry.zekken_number,
|
||||
"class_name": entry.class_name,
|
||||
"event_name": event.event_name
|
||||
}
|
||||
|
||||
# チェックポイント通過情報(写真を含む)を取得
|
||||
checkpoints = GpsLog.objects.filter(
|
||||
entry=entry
|
||||
).order_by('checkin_time')
|
||||
|
||||
# 写真リストを作成
|
||||
photos = []
|
||||
|
||||
for cp in checkpoints:
|
||||
# 写真URLがある場合のみ追加
|
||||
if hasattr(cp, 'image') and cp.image:
|
||||
photo_data = {
|
||||
"cp_number": cp.cp_number,
|
||||
"checkin_time": cp.checkin_time.strftime("%Y-%m-%d %H:%M:%S") if cp.checkin_time else None,
|
||||
"image_url": request.build_absolute_uri(cp.image.url) if hasattr(request, 'build_absolute_uri') else cp.image.url
|
||||
}
|
||||
|
||||
# サービスチェックの情報があれば追加
|
||||
if hasattr(cp, 'is_service_checked'):
|
||||
photo_data["is_service_checked"] = cp.is_service_checked
|
||||
|
||||
photos.append(photo_data)
|
||||
|
||||
# スタート写真があれば追加
|
||||
if hasattr(entry, 'start_info') and hasattr(entry.start_info, 'start_image') and entry.start_info.start_image:
|
||||
start_image = {
|
||||
"cp_number": "START",
|
||||
"checkin_time": entry.start_info.start_time.strftime("%Y-%m-%d %H:%M:%S") if entry.start_info.start_time else None,
|
||||
"image_url": request.build_absolute_uri(entry.start_info.start_image.url) if hasattr(request, 'build_absolute_uri') else entry.start_info.start_image.url
|
||||
}
|
||||
photos.insert(0, start_image) # リストの先頭に追加
|
||||
|
||||
# ゴール写真があれば追加
|
||||
if hasattr(entry, 'goal_info') and hasattr(entry.goal_info, 'goal_image') and entry.goal_info.goal_image:
|
||||
goal_image = {
|
||||
"cp_number": "GOAL",
|
||||
"checkin_time": entry.goal_info.goal_time.strftime("%Y-%m-%d %H:%M:%S") if entry.goal_info.goal_time else None,
|
||||
"image_url": request.build_absolute_uri(entry.goal_info.goal_image.url) if hasattr(request, 'build_absolute_uri') else entry.goal_info.goal_image.url
|
||||
}
|
||||
photos.append(goal_image) # リストの末尾に追加
|
||||
|
||||
# チームレポートURLを生成
|
||||
# レポートURLは「/レポートディレクトリ/イベント名/ゼッケン番号.pdf」のパターンを想定
|
||||
report_directory = getattr(settings, 'REPORT_DIRECTORY', 'reports')
|
||||
report_base_url = getattr(settings, 'REPORT_BASE_URL', '/media/reports/')
|
||||
|
||||
# レポートファイルの物理パスをチェック
|
||||
report_path = os.path.join(
|
||||
settings.MEDIA_ROOT,
|
||||
report_directory,
|
||||
event_code,
|
||||
f"{zekken_number}.pdf"
|
||||
)
|
||||
|
||||
# レポートURLを生成
|
||||
has_report = os.path.exists(report_path)
|
||||
report_url = None
|
||||
|
||||
if has_report:
|
||||
report_url = urljoin(
|
||||
report_base_url,
|
||||
f"{event_code}/{zekken_number}.pdf"
|
||||
)
|
||||
|
||||
# 絶対URLに変換
|
||||
if hasattr(request, 'build_absolute_uri'):
|
||||
report_url = request.build_absolute_uri(report_url)
|
||||
|
||||
# スコアボードURLを生成
|
||||
scoreboard_path = os.path.join(
|
||||
settings.MEDIA_ROOT,
|
||||
'scoreboards',
|
||||
event_code,
|
||||
f"scoreboard_{zekken_number}.pdf"
|
||||
)
|
||||
|
||||
has_scoreboard = os.path.exists(scoreboard_path)
|
||||
scoreboard_url = None
|
||||
|
||||
if has_scoreboard:
|
||||
scoreboard_url = urljoin(
|
||||
'/media/scoreboards/',
|
||||
f"{event_code}/scoreboard_{zekken_number}.pdf"
|
||||
)
|
||||
|
||||
# 絶対URLに変換
|
||||
if hasattr(request, 'build_absolute_uri'):
|
||||
scoreboard_url = request.build_absolute_uri(scoreboard_url)
|
||||
|
||||
# チームのスコア情報
|
||||
score = None
|
||||
if hasattr(entry, 'goal_info') and hasattr(entry.goal_info, 'score'):
|
||||
score = entry.goal_info.score
|
||||
|
||||
# レスポンスデータ
|
||||
response_data = {
|
||||
"status": "OK",
|
||||
"team": team_info,
|
||||
"photos": photos,
|
||||
"photo_count": len(photos),
|
||||
"has_report": has_report,
|
||||
"report_url": report_url,
|
||||
"has_scoreboard": has_scoreboard,
|
||||
"scoreboard_url": scoreboard_url,
|
||||
"score": score
|
||||
}
|
||||
|
||||
return Response(response_data)
|
||||
zekken = request.GET.get('zekken')
|
||||
event = request.GET.get('event')
|
||||
|
||||
if not zekken or not event:
|
||||
return JsonResponse({
|
||||
'error': 'zekken and event parameters are required'
|
||||
}, status=400)
|
||||
|
||||
try:
|
||||
# GpsCheckinからチームの画像データを取得
|
||||
gps_checkins = GpsCheckin.objects.filter(
|
||||
zekken_number=zekken,
|
||||
event_code=event
|
||||
).exclude(
|
||||
image_address__isnull=True
|
||||
).exclude(
|
||||
image_address=''
|
||||
).order_by('create_at')
|
||||
|
||||
photos = []
|
||||
for gps in gps_checkins:
|
||||
# image_addressを処理してS3 URLまたは既存URLを生成
|
||||
image_url = generate_image_url(gps.image_address, event, zekken)
|
||||
|
||||
photos.append({
|
||||
'id': gps.id,
|
||||
'image_url': image_url,
|
||||
'created_at': gps.create_at.strftime('%Y-%m-%d %H:%M:%S') if gps.create_at else None,
|
||||
'point_name': gps.checkpoint_id,
|
||||
'latitude': float(gps.lattitude) if gps.lattitude else None,
|
||||
'longitude': float(gps.longitude) if gps.longitude else None,
|
||||
})
|
||||
|
||||
return JsonResponse({
|
||||
'photos': photos,
|
||||
'count': len(photos)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in get_team_photos: {str(e)}")
|
||||
return Response({
|
||||
"status": "ERROR",
|
||||
"message": "サーバーエラーが発生しました"
|
||||
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
return JsonResponse({
|
||||
'error': f'Error retrieving photos: {str(e)}'
|
||||
}, status=500)
|
||||
|
||||
Reference in New Issue
Block a user