diff --git a/api/__pycache__/models.cpython-313.pyc b/api/__pycache__/models.cpython-313.pyc index 1468336..23cd358 100644 Binary files a/api/__pycache__/models.cpython-313.pyc and b/api/__pycache__/models.cpython-313.pyc differ diff --git a/api/__pycache__/serializers.cpython-313.pyc b/api/__pycache__/serializers.cpython-313.pyc index 72dde88..5099a66 100644 Binary files a/api/__pycache__/serializers.cpython-313.pyc and b/api/__pycache__/serializers.cpython-313.pyc differ diff --git a/api/__pycache__/urls.cpython-313.pyc b/api/__pycache__/urls.cpython-313.pyc index 516fdbd..7ace33c 100644 Binary files a/api/__pycache__/urls.cpython-313.pyc and b/api/__pycache__/urls.cpython-313.pyc differ diff --git a/api/__pycache__/views.cpython-313.pyc b/api/__pycache__/views.cpython-313.pyc index edba6dd..a7c45b3 100644 Binary files a/api/__pycache__/views.cpython-313.pyc and b/api/__pycache__/views.cpython-313.pyc differ diff --git a/api/migrations/0003_alter_userprediction_unique_together_and_more.py b/api/migrations/0003_alter_userprediction_unique_together_and_more.py new file mode 100644 index 0000000..332ea40 --- /dev/null +++ b/api/migrations/0003_alter_userprediction_unique_together_and_more.py @@ -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), + ), + ] diff --git a/api/migrations/__pycache__/0003_alter_userprediction_unique_together_and_more.cpython-313.pyc b/api/migrations/__pycache__/0003_alter_userprediction_unique_together_and_more.cpython-313.pyc new file mode 100644 index 0000000..e13512f Binary files /dev/null and b/api/migrations/__pycache__/0003_alter_userprediction_unique_together_and_more.cpython-313.pyc differ diff --git a/api/models.py b/api/models.py index a66861d..61621af 100644 --- a/api/models.py +++ b/api/models.py @@ -1,6 +1,6 @@ import uuid from django.db import models - +from django.contrib.auth import get_user_model class User(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) @@ -11,10 +11,10 @@ class Prediction(models.Model): result = models.JSONField() 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() + diff --git a/api/serializers.py b/api/serializers.py index 45d61c9..4823d4f 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -71,3 +71,16 @@ class PredictionRequestSerializer(serializers.Serializer): data['descent_rate'] = rate_clip(data['descent_rate']) 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"] diff --git a/api/services/__pycache__/tawhiri.cpython-313.pyc b/api/services/__pycache__/tawhiri.cpython-313.pyc index 5e3eb87..4e13d6e 100644 Binary files a/api/services/__pycache__/tawhiri.cpython-313.pyc and b/api/services/__pycache__/tawhiri.cpython-313.pyc differ diff --git a/api/services/tawhiri.py b/api/services/tawhiri.py index dbaf7e8..44d1fb0 100644 --- a/api/services/tawhiri.py +++ b/api/services/tawhiri.py @@ -36,7 +36,7 @@ class TawhiriClient: query["burst_altitude"] = params.get("burst_altitude") query["descent_rate"] = params.get("descent_rate") 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["pred_type"] = "single" # <-- в конце diff --git a/api/urls.py b/api/urls.py index c256ed2..eaff5cb 100644 --- a/api/urls.py +++ b/api/urls.py @@ -1,5 +1,8 @@ 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 urlpatterns = [ @@ -7,4 +10,7 @@ urlpatterns = [ path('predictions', PredictionListView.as_view(), name='get_predictions'), path('predictions/', PredictionDeleteView.as_view(), name='delete_prediction'), path('token/', obtain_auth_token), + path("history/", PredictionHistoryListView.as_view()), + path("history//", PredictionHistoryDetailView.as_view()), + path("history//delete/", PredictionHistoryDeleteView.as_view()), ] diff --git a/api/views.py b/api/views.py index 5255069..a4420fc 100644 --- a/api/views.py +++ b/api/views.py @@ -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.views import APIView from django.utils import timezone from .models import Prediction, User, UserPrediction -from .serializers import PredictionSerializer, PredictionRequestSerializer +from .serializers import PredictionSerializer, PredictionRequestSerializer, PredictionListSerializer, PredictionDetailSerializer from rest_framework.permissions import IsAuthenticated import requests from django.views.decorators.csrf import csrf_exempt 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 + +User = get_user_model() 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}") class PredictionCreateView(APIView): - permission_classes = [AllowAny] - + permission_classes = [IsAuthenticated] + def post(self, request): + print("DEBUG: request.user =", request.user) + print("DEBUG: request.user.id =", request.user.id) + serializer = PredictionRequestSerializer(data=request.data) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @@ -70,5 +76,43 @@ class PredictionDeleteView(APIView): except Prediction.DoesNotExist: 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): #permission_classes = [IsAuthenticated] \ No newline at end of file diff --git a/db.sqlite3 b/db.sqlite3 index 6e40345..41a74d0 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/testapi/__pycache__/settings.cpython-313.pyc b/testapi/__pycache__/settings.cpython-313.pyc index 9f7596d..b7622bf 100644 Binary files a/testapi/__pycache__/settings.cpython-313.pyc and b/testapi/__pycache__/settings.cpython-313.pyc differ diff --git a/testapi/settings.py b/testapi/settings.py index 5014536..9409c61 100644 --- a/testapi/settings.py +++ b/testapi/settings.py @@ -142,11 +142,10 @@ REST_FRAMEWORK = { # ВАШИ НАСТРОЙКИ 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', 'DEFAULT_AUTHENTICATION_CLASSES': [ - # 'rest_framework.authentication.TokenAuthentication', - # 'rest_framework.permissions.AllowAny', + 'rest_framework.authentication.TokenAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ - #'rest_framework.permissions.IsAuthenticated', - 'rest_framework.permissions.AllowAny', + 'rest_framework.permissions.IsAuthenticated', + #'rest_framework.permissions.AllowAny', ] }