feat(v1): add basic backend and frontend

This commit is contained in:
2026-07-09 00:37:41 +03:30
parent d9eedb3d8e
commit ae240e7ac1
54 changed files with 5829 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
from rest_framework import serializers, status
from rest_framework.response import Response
from rest_framework.views import APIView
from .algorithms import ProcessingError
from .selectors import image_session_get, processing_job_get
from .services import batch_job_create, image_session_create, image_session_process, processing_job_payload
def error_response(message, code=status.HTTP_400_BAD_REQUEST):
return Response({"detail": message}, status=code)
class ImageUploadView(APIView):
class InputSerializer(serializers.Serializer):
image = serializers.ImageField(required=False)
image_base64 = serializers.CharField(required=False, allow_blank=False)
def validate(self, attrs):
if not attrs.get("image") and not attrs.get("image_base64"):
raise serializers.ValidationError("Provide image or image_base64.")
return attrs
def post(self, request):
serializer = self.InputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
try:
payload = image_session_create(
uploaded_file=serializer.validated_data.get("image"),
image_base64=serializer.validated_data.get("image_base64"),
)
return Response(payload, status=status.HTTP_201_CREATED)
except ProcessingError as exc:
return error_response(str(exc))
class ProcessView(APIView):
class InputSerializer(serializers.Serializer):
session_id = serializers.UUIDField()
operation = serializers.CharField()
params = serializers.DictField(required=False, default=dict)
def post(self, request):
serializer = self.InputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
session = image_session_get(session_id=serializer.validated_data["session_id"])
if session is None:
return error_response("Image session does not exist.", status.HTTP_404_NOT_FOUND)
try:
payload = image_session_process(
session=session,
operation=serializer.validated_data["operation"],
params=serializer.validated_data.get("params", {}),
)
return Response(payload)
except ProcessingError as exc:
code = status.HTTP_410_GONE if str(exc) == "Image session has expired." else status.HTTP_400_BAD_REQUEST
return error_response(str(exc), code)
class BatchView(APIView):
class InputSerializer(serializers.Serializer):
operation = serializers.ChoiceField(choices=["average", "subtract"])
session_ids = serializers.ListField(child=serializers.UUIDField(), min_length=2)
params = serializers.DictField(required=False, default=dict)
def post(self, request):
serializer = self.InputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
job = batch_job_create(
operation=serializer.validated_data["operation"],
session_ids=serializer.validated_data["session_ids"],
params=serializer.validated_data.get("params", {}),
)
return Response({"job_id": str(job.id), "status": job.status}, status=status.HTTP_202_ACCEPTED)
class JobDetailView(APIView):
def get(self, request, job_id):
job = processing_job_get(job_id=job_id)
if job is None:
return error_response("Job does not exist.", status.HTTP_404_NOT_FOUND)
return Response(processing_job_payload(job=job))
class HealthView(APIView):
def get(self, request):
return Response({"status": "ok"})