From 00a2b2c0b09ef439f4705af9e504b6a21f67eccb Mon Sep 17 00:00:00 2001 From: PouyaKhajavi Date: Sun, 9 Aug 2026 10:22:38 +0330 Subject: [PATCH] feat(api): add DELETE endpoints for ad evaluations and crawl run history --- backend/ads/tests.py | 7 +++++++ backend/ads/views.py | 4 ++-- backend/crawler/tests.py | 11 +++++++++++ backend/crawler/urls.py | 4 +++- backend/crawler/views.py | 9 +++++++++ 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/backend/ads/tests.py b/backend/ads/tests.py index e269de0..f3506c0 100644 --- a/backend/ads/tests.py +++ b/backend/ads/tests.py @@ -95,3 +95,10 @@ class AdEvaluationAPITests(APITestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['id'], str(self.eval1.id)) self.assertEqual(response.data['ad']['title'], self.ad1.title) + + def test_delete_ad_evaluation(self): + detail_url = f"{self.list_url}{self.eval1.id}/" + response = self.client.delete(detail_url) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertFalse(AdEvaluation.objects.filter(id=self.eval1.id).exists()) + diff --git a/backend/ads/views.py b/backend/ads/views.py index d43c9ce..b3433b3 100644 --- a/backend/ads/views.py +++ b/backend/ads/views.py @@ -2,9 +2,9 @@ from rest_framework import viewsets from .models import AdEvaluation from .serializers import AdEvaluationSerializer -class AdEvaluationViewSet(viewsets.ReadOnlyModelViewSet): +class AdEvaluationViewSet(viewsets.ModelViewSet): """ - ViewSet for listing and viewing Ad Evaluations. + ViewSet for listing, viewing, and deleting Ad Evaluations. Supports filtering by crawl_task (UUID) and is_flagged (boolean). """ serializer_class = AdEvaluationSerializer diff --git a/backend/crawler/tests.py b/backend/crawler/tests.py index 3792b4c..1bf5666 100644 --- a/backend/crawler/tests.py +++ b/backend/crawler/tests.py @@ -128,6 +128,17 @@ class CrawlTaskAPITests(APITestCase): self.assertEqual(response.data[0]['id'], str(run.id)) self.assertEqual(response.data[0]['status'], 'SUCCESS') + def test_delete_crawl_run(self): + run = CrawlRun.objects.create( + crawl_task=self.task, + status='SUCCESS' + ) + delete_url = f"/api/crawlers/runs/{run.id}/" + response = self.client.delete(delete_url) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertFalse(CrawlRun.objects.filter(id=run.id).exists()) + + class CrawlTaskCeleryTests(APITestCase): def setUp(self): self.task = CrawlTask.objects.create( diff --git a/backend/crawler/urls.py b/backend/crawler/urls.py index 50668c6..77e9a7e 100644 --- a/backend/crawler/urls.py +++ b/backend/crawler/urls.py @@ -1,11 +1,13 @@ from django.urls import path, include from rest_framework.routers import DefaultRouter -from .views import CrawlTaskViewSet +from .views import CrawlTaskViewSet, CrawlRunViewSet router = DefaultRouter() +router.register(r'runs', CrawlRunViewSet, basename='runs') router.register(r'', CrawlTaskViewSet, basename='crawlers') urlpatterns = [ path('', include(router.urls)), ] + diff --git a/backend/crawler/views.py b/backend/crawler/views.py index 323c6bf..86608a8 100644 --- a/backend/crawler/views.py +++ b/backend/crawler/views.py @@ -47,3 +47,12 @@ class CrawlTaskViewSet(viewsets.ModelViewSet): serializer = CrawlRunSerializer(runs, many=True) return Response(serializer.data) + + +class CrawlRunViewSet(viewsets.ModelViewSet): + """ + ViewSet for CrawlRun models. Supports CRUD (including DELETE). + """ + queryset = CrawlRun.objects.all().order_by('-started_at') + serializer_class = CrawlRunSerializer +