added api/history

This commit is contained in:
afanasyev.aa 2025-04-05 20:50:54 +09:00
parent 2aef4d4756
commit cc5187c3a1
15 changed files with 109 additions and 17 deletions

Binary file not shown.

View file

@ -0,0 +1,30 @@
# Generated by Django 5.1.7 on 2025-04-05 10:40
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0002_prediction_user_userprediction_delete_todo'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AlterUniqueTogether(
name='userprediction',
unique_together=set(),
),
migrations.AlterField(
model_name='userprediction',
name='created_at',
field=models.DateTimeField(),
),
migrations.AlterField(
model_name='userprediction',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]

View file

@ -1,6 +1,6 @@
import uuid import uuid
from django.db import models from django.db import models
from django.contrib.auth import get_user_model
class User(models.Model): class User(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
@ -11,10 +11,10 @@ class Prediction(models.Model):
result = models.JSONField() result = models.JSONField()
deleted_at = models.DateTimeField(null=True, blank=True) deleted_at = models.DateTimeField(null=True, blank=True)
class UserPrediction(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
prediction = models.ForeignKey(Prediction, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = ('user', 'prediction') class UserPrediction(models.Model):
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
prediction = models.ForeignKey("Prediction", on_delete=models.CASCADE)
created_at = models.DateTimeField()

View file

@ -71,3 +71,16 @@ class PredictionRequestSerializer(serializers.Serializer):
data['descent_rate'] = rate_clip(data['descent_rate']) data['descent_rate'] = rate_clip(data['descent_rate'])
return data return data
class PredictionListSerializer(serializers.ModelSerializer):
class Meta:
model = Prediction
fields = ["id", "created_at", "updated_at"]
class PredictionDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Prediction
fields = ["id", "created_at", "updated_at", "result"]

View file

@ -36,7 +36,7 @@ class TawhiriClient:
query["burst_altitude"] = params.get("burst_altitude") query["burst_altitude"] = params.get("burst_altitude")
query["descent_rate"] = params.get("descent_rate") query["descent_rate"] = params.get("descent_rate")
query["interpolate"] = str(params.get("interpolate", False)).lower() query["interpolate"] = str(params.get("interpolate", False)).lower()
query["dataset"] = cls._convert_value(params.get("dataset")) #query["dataset"] = cls._convert_value(params.get("dataset"))
query["format"] = params.get("format", "json") query["format"] = params.get("format", "json")
query["pred_type"] = "single" # <-- в конце query["pred_type"] = "single" # <-- в конце

View file

@ -1,5 +1,8 @@
from django.urls import path from django.urls import path
from .views import PredictionCreateView, PredictionListView, PredictionDeleteView from .views import (PredictionCreateView, PredictionListView, PredictionDeleteView,
PredictionHistoryListView,
PredictionHistoryDetailView,
PredictionHistoryDeleteView,)
from rest_framework.authtoken.views import obtain_auth_token from rest_framework.authtoken.views import obtain_auth_token
urlpatterns = [ urlpatterns = [
@ -7,4 +10,7 @@ urlpatterns = [
path('predictions', PredictionListView.as_view(), name='get_predictions'), path('predictions', PredictionListView.as_view(), name='get_predictions'),
path('predictions/<uuid:pk>', PredictionDeleteView.as_view(), name='delete_prediction'), path('predictions/<uuid:pk>', PredictionDeleteView.as_view(), name='delete_prediction'),
path('token/', obtain_auth_token), path('token/', obtain_auth_token),
path("history/", PredictionHistoryListView.as_view()),
path("history/<uuid:pk>/", PredictionHistoryDetailView.as_view()),
path("history/<uuid:pk>/delete/", PredictionHistoryDeleteView.as_view()),
] ]

View file

@ -1,15 +1,18 @@
from rest_framework import status, generics 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 django.utils import timezone from django.utils import timezone
from .models import Prediction, User, UserPrediction from .models import Prediction, User, UserPrediction
from .serializers import PredictionSerializer, PredictionRequestSerializer from .serializers import PredictionSerializer, PredictionRequestSerializer, PredictionListSerializer, PredictionDetailSerializer
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
import requests 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 rest_framework.permissions import AllowAny
from .services.tawhiri import TawhiriClient from .services.tawhiri import TawhiriClient
from django.contrib.auth import get_user_model
User = get_user_model()
def get_prediction_from_tawhiri(params): def get_prediction_from_tawhiri(params):
@ -22,9 +25,12 @@ def get_prediction_from_tawhiri(params):
raise Exception(f"Tawhiri error: {response.status_code} {response.text}") raise Exception(f"Tawhiri error: {response.status_code} {response.text}")
class PredictionCreateView(APIView): class PredictionCreateView(APIView):
permission_classes = [AllowAny] permission_classes = [IsAuthenticated]
def post(self, request): def post(self, request):
print("DEBUG: request.user =", request.user)
print("DEBUG: request.user.id =", request.user.id)
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)
@ -70,5 +76,43 @@ class PredictionDeleteView(APIView):
except Prediction.DoesNotExist: except Prediction.DoesNotExist:
return Response({"error": "Not found"}, status=404) return Response({"error": "Not found"}, status=404)
class PredictionHistoryListView(generics.ListAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = PredictionListSerializer
def get_queryset(self):
return Prediction.objects.filter(
id__in=UserPrediction.objects.filter(user=self.request.user).values_list('prediction_id', flat=True),
deleted_at__isnull=True
)
class PredictionHistoryDetailView(generics.RetrieveAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = PredictionDetailSerializer
def get_queryset(self):
return Prediction.objects.filter(
id__in=UserPrediction.objects.filter(user=self.request.user).values_list('prediction_id', flat=True),
deleted_at__isnull=True
)
class PredictionHistoryDeleteView(generics.DestroyAPIView):
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return Prediction.objects.filter(
id__in=UserPrediction.objects.filter(user=self.request.user).values_list('prediction_id', flat=True),
deleted_at__isnull=True
)
def perform_destroy(self, instance):
instance.deleted_at = timezone.now()
instance.save()
#class PredictionCreateView(APIView): #class PredictionCreateView(APIView):
#permission_classes = [IsAuthenticated] #permission_classes = [IsAuthenticated]

Binary file not shown.

View file

@ -142,11 +142,10 @@ REST_FRAMEWORK = {
# ВАШИ НАСТРОЙКИ # ВАШИ НАСТРОЙКИ
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
'DEFAULT_AUTHENTICATION_CLASSES': [ 'DEFAULT_AUTHENTICATION_CLASSES': [
# 'rest_framework.authentication.TokenAuthentication', 'rest_framework.authentication.TokenAuthentication',
# 'rest_framework.permissions.AllowAny',
], ],
'DEFAULT_PERMISSION_CLASSES': [ 'DEFAULT_PERMISSION_CLASSES': [
#'rest_framework.permissions.IsAuthenticated', 'rest_framework.permissions.IsAuthenticated',
'rest_framework.permissions.AllowAny', #'rest_framework.permissions.AllowAny',
] ]
} }