Finish basic API implementation

This commit is contained in:
2025-08-27 15:01:06 +09:00
parent fff9bce9e7
commit cc9edb9932
19 changed files with 3844 additions and 5 deletions

242
rog/app_version_views.py Normal file
View File

@ -0,0 +1,242 @@
"""
App Version Check API Views
アプリバージョンチェック機能
"""
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views import View
from django.http import JsonResponse
import json
import logging
from .models import AppVersion
from .serializers import AppVersionCheckSerializer, AppVersionResponseSerializer
logger = logging.getLogger(__name__)
@api_view(['POST'])
@permission_classes([AllowAny])
def app_version_check(request):
"""
アプリバージョンチェックAPI
POST /api/app/version-check
Request:
{
"current_version": "1.2.3",
"platform": "android",
"build_number": "123"
}
Response:
{
"latest_version": "1.3.0",
"update_required": false,
"update_available": true,
"update_message": "新機能が追加されました。更新をお勧めします。",
"download_url": "https://play.google.com/store/apps/details?id=com.example.app",
"release_date": "2025-08-25T00:00:00Z"
}
"""
try:
# リクエストデータの検証
serializer = AppVersionCheckSerializer(data=request.data)
if not serializer.is_valid():
return Response({
'error': 'Invalid request data',
'details': serializer.errors
}, status=status.HTTP_400_BAD_REQUEST)
current_version = serializer.validated_data['current_version']
platform = serializer.validated_data['platform']
build_number = serializer.validated_data.get('build_number')
# 最新バージョン情報を取得
latest_version_obj = AppVersion.get_latest_version(platform)
if not latest_version_obj:
return Response({
'error': 'No version information available for this platform'
}, status=status.HTTP_404_NOT_FOUND)
# バージョン比較
comparison = AppVersion.compare_versions(current_version, latest_version_obj.version)
# レスポンスデータ作成
response_data = {
'latest_version': latest_version_obj.version,
'update_required': False,
'update_available': False,
'update_message': latest_version_obj.update_message or 'アプリは最新版です',
'download_url': latest_version_obj.download_url or '',
'release_date': latest_version_obj.release_date
}
if comparison < 0: # current_version < latest_version
response_data['update_available'] = True
# 強制更新が必要かチェック
if latest_version_obj.is_required:
response_data['update_required'] = True
response_data['update_message'] = (
latest_version_obj.update_message or
'このバージョンは古すぎるため、更新が必要です。'
)
else:
response_data['update_message'] = (
latest_version_obj.update_message or
'新しいバージョンが利用可能です。更新をお勧めします。'
)
# レスポンス検証
response_serializer = AppVersionResponseSerializer(data=response_data)
if response_serializer.is_valid():
return Response(response_serializer.validated_data, status=status.HTTP_200_OK)
else:
logger.error(f"Response serialization error: {response_serializer.errors}")
return Response({
'error': 'Internal server error'
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
except Exception as e:
logger.error(f"App version check error: {e}")
return Response({
'error': 'Internal server error',
'message': str(e)
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@method_decorator(csrf_exempt, name='dispatch')
class AppVersionManagementView(View):
"""アプリバージョン管理ビュー(管理者用)"""
def get(self, request):
"""全バージョン情報取得"""
try:
platform = request.GET.get('platform')
queryset = AppVersion.objects.all().order_by('-created_at')
if platform:
queryset = queryset.filter(platform=platform)
versions = []
for version in queryset:
versions.append({
'id': version.id,
'version': version.version,
'platform': version.platform,
'build_number': version.build_number,
'is_latest': version.is_latest,
'is_required': version.is_required,
'update_message': version.update_message,
'download_url': version.download_url,
'release_date': version.release_date.isoformat(),
'created_at': version.created_at.isoformat()
})
return JsonResponse({
'versions': versions,
'total': len(versions)
})
except Exception as e:
logger.error(f"Version list error: {e}")
return JsonResponse({
'error': 'Failed to fetch versions'
}, status=500)
def post(self, request):
"""新バージョン登録"""
try:
data = json.loads(request.body)
# 必須フィールドチェック
required_fields = ['version', 'platform']
for field in required_fields:
if field not in data:
return JsonResponse({
'error': f'Missing required field: {field}'
}, status=400)
# バージョンオブジェクト作成
version_obj = AppVersion(
version=data['version'],
platform=data['platform'],
build_number=data.get('build_number'),
is_latest=data.get('is_latest', False),
is_required=data.get('is_required', False),
update_message=data.get('update_message'),
download_url=data.get('download_url')
)
version_obj.save()
return JsonResponse({
'message': 'Version created successfully',
'id': version_obj.id,
'version': version_obj.version,
'platform': version_obj.platform
}, status=201)
except json.JSONDecodeError:
return JsonResponse({
'error': 'Invalid JSON data'
}, status=400)
except Exception as e:
logger.error(f"Version creation error: {e}")
return JsonResponse({
'error': 'Failed to create version'
}, status=500)
def put(self, request):
"""バージョン情報更新"""
try:
data = json.loads(request.body)
version_id = data.get('id')
if not version_id:
return JsonResponse({
'error': 'Version ID is required'
}, status=400)
try:
version_obj = AppVersion.objects.get(id=version_id)
except AppVersion.DoesNotExist:
return JsonResponse({
'error': 'Version not found'
}, status=404)
# フィールド更新
updateable_fields = [
'build_number', 'is_latest', 'is_required',
'update_message', 'download_url'
]
for field in updateable_fields:
if field in data:
setattr(version_obj, field, data[field])
version_obj.save()
return JsonResponse({
'message': 'Version updated successfully',
'id': version_obj.id,
'version': version_obj.version
})
except json.JSONDecodeError:
return JsonResponse({
'error': 'Invalid JSON data'
}, status=400)
except Exception as e:
logger.error(f"Version update error: {e}")
return JsonResponse({
'error': 'Failed to update version'
}, status=500)