Merge branch 'main' of https://git.intra.yksa.space/afanasyev.aa/api-drf-1
This commit is contained in:
commit
2ec289f3c7
3 changed files with 85 additions and 75 deletions
38
api/urls.py
38
api/urls.py
|
|
@ -1,23 +1,32 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from .views import (PredictionCreateView, PredictionListView,
|
from rest_framework.routers import DefaultRouter
|
||||||
PredictionHistoryListView,
|
from rest_framework.authtoken.views import obtain_auth_token
|
||||||
PredictionHistoryDetailView,
|
from .views import (
|
||||||
PredictionHistoryDeleteView,
|
PredictionViewSet,
|
||||||
SessionView,
|
|
||||||
WhoAmIView,
|
|
||||||
SavedPointViewset,
|
SavedPointViewset,
|
||||||
|
TelemetryListCreateView,
|
||||||
get_csrf,
|
get_csrf,
|
||||||
login_view,
|
login_view,
|
||||||
logout_view)
|
logout_view,
|
||||||
from rest_framework.authtoken.views import obtain_auth_token
|
SessionView,
|
||||||
from .views import TelemetryListCreateView
|
WhoAmIView
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
router = DefaultRouter()
|
||||||
|
router.register(r'predictions', PredictionViewSet, basename='predictions')
|
||||||
|
router.register(r'saved-points', SavedPointViewset, basename='saved-points')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('predictions', PredictionCreateView.as_view(), name='create_prediction'),
|
path("csrf/", get_csrf, name='api-csrf'),
|
||||||
path('predictions/list/', PredictionListView.as_view(), name='get_predictions'),
|
|
||||||
path('token', obtain_auth_token, name = 'get_token'),
|
path('token', obtain_auth_token, name = 'get_token'),
|
||||||
path("history", PredictionHistoryListView.as_view(), name='view_history_list'),
|
path("login/", login_view, name='api-login'),
|
||||||
path("history/<uuid:pk>/", PredictionHistoryDetailView.as_view(), name='view_history_detail'),
|
path("logout/", logout_view, name='api-logout'),
|
||||||
path("history/<uuid:pk>/delete/", PredictionHistoryDeleteView.as_view(), name='delete_history'),
|
path("session/", SessionView.as_view(), name='api-session'),
|
||||||
|
path("whoami/", WhoAmIView.as_view(), name='api-whoami'),
|
||||||
path("<uuid:pk>/telemetry/", TelemetryListCreateView.as_view(), name="create_telemetry"),
|
path("<uuid:pk>/telemetry/", TelemetryListCreateView.as_view(), name="create_telemetry"),
|
||||||
path('saved-points/', SavedPointViewset.as_view({'get': 'list', 'post': 'create'}), name='saved_points'),
|
path('saved-points/', SavedPointViewset.as_view({'get': 'list', 'post': 'create'}), name='saved_points'),
|
||||||
path('saved-points/<int:pk>/', SavedPointViewset.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}), name='saved_point_detail'),
|
path('saved-points/<int:pk>/', SavedPointViewset.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}), name='saved_point_detail'),
|
||||||
|
|
@ -27,3 +36,4 @@ urlpatterns = [
|
||||||
path('session/', SessionView.as_view(), name='api-session'), # new
|
path('session/', SessionView.as_view(), name='api-session'), # new
|
||||||
path('whoami/', WhoAmIView.as_view(), name='api-whoami'), # new
|
path('whoami/', WhoAmIView.as_view(), name='api-whoami'), # new
|
||||||
]
|
]
|
||||||
|
urlpatterns += router.urls
|
||||||
|
|
|
||||||
121
api/views.py
121
api/views.py
|
|
@ -1,34 +1,34 @@
|
||||||
|
import requests
|
||||||
|
import time
|
||||||
|
import json
|
||||||
from rest_framework import status, generics, permissions
|
from rest_framework import status, generics, permissions
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.viewsets import ModelViewSet, ViewSet
|
||||||
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||||
|
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
|
||||||
|
from rest_framework.decorators import api_view, permission_classes, authentication_classes, action
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from .models import Prediction, User, Satellite, SavedPoint, SavedRateProfile, PreditctionTemplate
|
|
||||||
from .serializers import PredictionSerializer, PredictionRequestSerializer, PredictionListSerializer, PredictionDetailSerializer, SavedPointSerializer, SavedRateProfileSerializer, PreditctionTemplateSerializer
|
|
||||||
from rest_framework.permissions import IsAuthenticated
|
|
||||||
import requests
|
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from rest_framework.permissions import AllowAny
|
|
||||||
from .services.tawhiri import TawhiriClient
|
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
from .models import Satellite, TelemetryPacket
|
|
||||||
from .serializers import TelemetryPacketSerializer
|
|
||||||
from .permissions import ReadOnlyOrAuthenticated, IsOwner
|
|
||||||
import time
|
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
|
from django.contrib.auth import authenticate, login, logout, get_user_model
|
||||||
from django.contrib.auth import authenticate, login, logout
|
|
||||||
import json
|
|
||||||
from django.middleware.csrf import get_token
|
from django.middleware.csrf import get_token
|
||||||
from rest_framework.decorators import api_view, permission_classes, authentication_classes
|
|
||||||
from drf_spectacular.utils import extend_schema
|
|
||||||
from django.utils.dateparse import parse_datetime
|
from django.utils.dateparse import parse_datetime
|
||||||
|
from .models import Prediction, User, Satellite, SavedPoint, SavedRateProfile, PreditctionTemplate, TelemetryPacket
|
||||||
|
from .serializers import PredictionSerializer, TelemetryPacketSerializer, PredictionRequestSerializer, PredictionListSerializer, PredictionDetailSerializer, SavedPointSerializer, SavedRateProfileSerializer, PreditctionTemplateSerializer
|
||||||
|
from .services.tawhiri import TawhiriClient
|
||||||
|
from drf_spectacular.utils import extend_schema
|
||||||
|
from .permissions import ReadOnlyOrAuthenticated, IsOwner
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_prediction_from_tawhiri(params):
|
def get_prediction_from_tawhiri(params):
|
||||||
|
|
||||||
base_url = "https://fly.stratonautica.ru/api/v2"
|
base_url = "https://fly.stratonautica.ru/api/v2"
|
||||||
response = requests.get(base_url, params=params)
|
response = requests.get(base_url, params=params)
|
||||||
|
|
||||||
|
|
@ -39,14 +39,14 @@ def get_prediction_from_tawhiri(params):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PredictionCreateView(APIView):
|
class PredictionViewSet(ViewSet):
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
def post(self, request):
|
|
||||||
print("DEBUG: request.user =", request.user)
|
|
||||||
print("DEBUG: request.user.id =", request.user.id)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def create(self, request):
|
||||||
serializer = PredictionRequestSerializer(data=request.data)
|
serializer = PredictionRequestSerializer(data=request.data)
|
||||||
|
|
||||||
if not serializer.is_valid():
|
if not serializer.is_valid():
|
||||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
@ -54,11 +54,12 @@ class PredictionCreateView(APIView):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
prediction_result = TawhiriClient.get_prediction(validated_data)
|
prediction_result = TawhiriClient.get_prediction(validated_data)
|
||||||
|
|
||||||
except requests.RequestException as e:
|
except requests.RequestException as e:
|
||||||
print("Tawhiri error:", str(e), e.response.text if e.response else "no response")
|
|
||||||
return Response({"error": f"Tawhiri error: {str(e)}"}, status=status.HTTP_502_BAD_GATEWAY)
|
return Response({"error": f"Tawhiri error: {str(e)}"}, status=status.HTTP_502_BAD_GATEWAY)
|
||||||
|
|
||||||
prediction = Prediction.objects.create(result=prediction_result, user=request.user, request=request.data)
|
prediction = Prediction.objects.create(result=prediction_result, user=request.user, request=request.data)
|
||||||
|
|
||||||
return Response({
|
return Response({
|
||||||
"id": prediction.id,
|
"id": prediction.id,
|
||||||
"created_at": prediction.created_at,
|
"created_at": prediction.created_at,
|
||||||
|
|
@ -66,66 +67,60 @@ class PredictionCreateView(APIView):
|
||||||
}, status=status.HTTP_201_CREATED)
|
}, status=status.HTTP_201_CREATED)
|
||||||
|
|
||||||
|
|
||||||
class PredictionListView(APIView):
|
|
||||||
permission_classes = [IsAuthenticated]
|
|
||||||
|
|
||||||
def get(self, request):
|
@action(detail=False, methods=['get'])
|
||||||
|
def list_user(self, request):
|
||||||
user = request.user
|
user = request.user
|
||||||
satellite_id = request.query_params.get('satellite_id')
|
satellite_id = request.query_params.get('satellite_id')
|
||||||
created_from = request.query_params.get('created_from')
|
created_from = request.query_params.get('created_from')
|
||||||
created_till = request.query_params.get('created_till')
|
created_till = request.query_params.get('created_till')
|
||||||
|
|
||||||
# Проверка доступа к спутнику
|
|
||||||
if satellite_id and not user.satellites.filter(id=satellite_id).exists():
|
|
||||||
return Response({'detail': 'Access to this satellite is forbidden.'}, status=403)
|
|
||||||
|
|
||||||
filters = {
|
filters = {
|
||||||
'id__in': Prediction.objects.filter(user=user).values_list('prediction_id', flat=True),
|
'user': user,
|
||||||
'deleted_at__isnull': True
|
'deleted_at__isnull': True
|
||||||
}
|
}
|
||||||
print(filters)
|
|
||||||
print(Prediction.objects.filter(**filters))
|
|
||||||
if created_from:
|
if created_from:
|
||||||
filters['created_at__gte'] = parse_datetime(created_from)
|
filters['created_at__gte'] = parse_datetime(created_from)
|
||||||
|
|
||||||
if created_till:
|
if created_till:
|
||||||
filters['created_at__lte'] = parse_datetime(created_till)
|
filters['created_at__lte'] = parse_datetime(created_till)
|
||||||
|
|
||||||
if satellite_id:
|
if satellite_id:
|
||||||
|
if not user.satellites.filter(id=satellite_id).exists():
|
||||||
|
return Response({'detail': 'Access denied'}, status=403)
|
||||||
|
|
||||||
filters['satellite_id'] = satellite_id
|
filters['satellite_id'] = satellite_id
|
||||||
|
|
||||||
predictions = Prediction.objects.filter(**filters)
|
queryset = Prediction.objects.filter(**filters)
|
||||||
return Response(PredictionSerializer(predictions, many=True).data)
|
return Response(PredictionSerializer(queryset, many=True).data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PredictionHistoryListView(generics.ListAPIView):
|
|
||||||
permission_classes = [permissions.IsAuthenticated]
|
|
||||||
serializer_class = PredictionListSerializer
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return Prediction.objects.filter(
|
|
||||||
user=self.request.user,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PredictionHistoryDetailView(generics.RetrieveAPIView):
|
@action(detail=False, methods=["get"])
|
||||||
permission_classes = [permissions.IsAuthenticated]
|
def history(self, request):
|
||||||
serializer_class = PredictionDetailSerializer
|
queryset = Prediction.objects.filter(user=request.user)
|
||||||
|
return Response(PredictionListSerializer(queryset, many=True).data)
|
||||||
def get_queryset(self):
|
|
||||||
return Prediction.objects.filter(
|
|
||||||
user=self.request.user,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PredictionHistoryDeleteView(generics.DestroyAPIView):
|
@action(detail=True, methods=["get"])
|
||||||
permission_classes = [permissions.IsAuthenticated]
|
def detail(self, request, pk=None):
|
||||||
|
prediction = Prediction.objects.filter(user=request.user, pk=pk).first()
|
||||||
|
if not prediction:
|
||||||
|
return Response({'detail': 'Not found'}, status=404)
|
||||||
|
return Response(PredictionDetailSerializer(prediction).data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@action(detail=True, methods=["delete"])
|
||||||
|
def delete(self, request, pk=None):
|
||||||
|
prediction = Prediction.objects.filter(user=request.user, pk=pk).first()
|
||||||
|
if not prediction:
|
||||||
|
return Response({'detail': 'Not found'}, status=404)
|
||||||
|
prediction.delete()
|
||||||
|
return Response(status=204)
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return Prediction.objects.filter(
|
|
||||||
user=self.request.user,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TelemetryListCreateView(generics.ListCreateAPIView):
|
class TelemetryListCreateView(generics.ListCreateAPIView):
|
||||||
|
|
@ -164,6 +159,7 @@ class TelemetryListCreateView(generics.ListCreateAPIView):
|
||||||
return Response(serializer.errors, status=status.HTTP_201_CREATED)
|
return Response(serializer.errors, status=status.HTTP_201_CREATED)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SessionView(APIView):
|
class SessionView(APIView):
|
||||||
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
@ -173,6 +169,7 @@ class SessionView(APIView):
|
||||||
return JsonResponse({'isAuthenticated': True})
|
return JsonResponse({'isAuthenticated': True})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WhoAmIView(APIView):
|
class WhoAmIView(APIView):
|
||||||
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
@ -182,6 +179,7 @@ class WhoAmIView(APIView):
|
||||||
return JsonResponse({'username': request.user.username})
|
return JsonResponse({'username': request.user.username})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@extend_schema(methods=["GET"], description="Get CSRF token")
|
@extend_schema(methods=["GET"], description="Get CSRF token")
|
||||||
@api_view(["GET"])
|
@api_view(["GET"])
|
||||||
@permission_classes([AllowAny])
|
@permission_classes([AllowAny])
|
||||||
|
|
@ -191,6 +189,7 @@ def get_csrf(request):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@extend_schema(methods=["POST"], description="Login user")
|
@extend_schema(methods=["POST"], description="Login user")
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
@api_view(["POST"])
|
@api_view(["POST"])
|
||||||
|
|
@ -212,6 +211,7 @@ def login_view(request):
|
||||||
return JsonResponse({'detail': 'Successfully logged in.'})
|
return JsonResponse({'detail': 'Successfully logged in.'})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@extend_schema(methods=["POST"], description="Logout user")
|
@extend_schema(methods=["POST"], description="Logout user")
|
||||||
@api_view(["POST"])
|
@api_view(["POST"])
|
||||||
@permission_classes([AllowAny])
|
@permission_classes([AllowAny])
|
||||||
|
|
@ -223,6 +223,7 @@ def logout_view(request):
|
||||||
return JsonResponse({'detail': 'Successfully logged out.'})
|
return JsonResponse({'detail': 'Successfully logged out.'})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SavedPointViewset(ModelViewSet):
|
class SavedPointViewset(ModelViewSet):
|
||||||
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
||||||
permission_classes = [IsOwner]
|
permission_classes = [IsOwner]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue