from rest_framework import viewsets, status from rest_framework.decorators import action from rest_framework.response import Response from .models import CrawlTask, CrawlRun from .serializers import CrawlTaskSerializer, CrawlRunSerializer class CrawlTaskViewSet(viewsets.ModelViewSet): """ ViewSet for CrawlTask models. Supports CRUD and custom trigger/runs actions. """ queryset = CrawlTask.objects.all().order_by('-created_at') serializer_class = CrawlTaskSerializer @action(detail=True, methods=['post'], url_path='trigger') def trigger(self, request, pk=None): task = self.get_object() # Create a new CrawlRun with status RUNNING run = CrawlRun.objects.create( crawl_task=task, status='RUNNING' ) # Check if tasks can be imported. # This will integrate with crawlers/tasks.py once it is written in a later step. try: from crawler.tasks import run_crawl_pipeline # run asynchronously run_crawl_pipeline.delay(str(run.id)) is_queued = True except ImportError: # Fallback if tasks.py doesn't exist yet or run_crawl_pipeline is not defined is_queued = False return Response({ "status": "queued" if is_queued else "queued_stub", "run_id": str(run.id) }, status=status.HTTP_202_ACCEPTED) @action(detail=True, methods=['get'], url_path='runs') def runs(self, request, pk=None): task = self.get_object() runs = task.runs.all().order_by('-started_at') page = self.paginate_queryset(runs) if page is not None: serializer = CrawlRunSerializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = CrawlRunSerializer(runs, many=True) return Response(serializer.data)