diff --git a/problem/tests.py b/problem/tests.py index 8ff20175..7595260e 100644 --- a/problem/tests.py +++ b/problem/tests.py @@ -11,7 +11,7 @@ from utils.api.tests import APITestCase from .models import ProblemTag from .models import Problem, ProblemRuleType -from .views.admin import TestCaseUploadAPI +from .views.admin import TestCaseAPI from contest.models import Contest from contest.tests import DEFAULT_CONTEST_DATA @@ -75,8 +75,8 @@ class ProblemTagListAPITest(APITestCase): class TestCaseUploadAPITest(APITestCase): def setUp(self): - self.api = TestCaseUploadAPI() - self.url = self.reverse("test_case_upload_api") + self.api = TestCaseAPI() + self.url = self.reverse("test_case_api") self.create_super_admin() def test_filter_file_name(self): diff --git a/problem/urls/admin.py b/problem/urls/admin.py index 7cc9afa6..5dbc4446 100644 --- a/problem/urls/admin.py +++ b/problem/urls/admin.py @@ -1,9 +1,9 @@ from django.conf.urls import url -from ..views.admin import ContestProblemAPI, ProblemAPI, TestCaseUploadAPI, MakeContestProblemPublicAPIView +from ..views.admin import ContestProblemAPI, ProblemAPI, TestCaseAPI, MakeContestProblemPublicAPIView urlpatterns = [ - url(r"^test_case/upload/?$", TestCaseUploadAPI.as_view(), name="test_case_upload_api"), + url(r"^test_case/?$", TestCaseAPI.as_view(), name="test_case_api"), url(r"^problem/?$", ProblemAPI.as_view(), name="problem_admin_api"), url(r"^contest/problem/?$", ContestProblemAPI.as_view(), name="contest_problem_admin_api"), url(r"^contest_problem/make_public/?$", MakeContestProblemPublicAPIView.as_view(), name="make_public_api"), diff --git a/problem/views/admin.py b/problem/views/admin.py index cf944474..d9ae3f2e 100644 --- a/problem/views/admin.py +++ b/problem/views/admin.py @@ -2,8 +2,10 @@ import hashlib import json import os import zipfile +from wsgiref.util import FileWrapper from django.conf import settings +from django.http import StreamingHttpResponse from account.decorators import problem_permission_required from contest.models import Contest @@ -16,7 +18,7 @@ from ..serializers import (CreateContestProblemSerializer, ContestProblemAdminSe ProblemAdminSerializer, TestCaseUploadForm, ContestProblemMakePublicSerializer) -class TestCaseUploadAPI(CSRFExemptAPIView): +class TestCaseAPI(CSRFExemptAPIView): request_parsers = () def filter_name_list(self, name_list, spj): @@ -43,6 +45,29 @@ class TestCaseUploadAPI(CSRFExemptAPIView): else: return sorted(ret, key=natural_sort_key) + @problem_permission_required + def get(self, request): + problem_id = request.GET.get("problem_id") + if not problem_id: + return self.error("Parameter error, problem_id is required") + try: + problem = Problem.objects.get(id=problem_id) + except Problem.DoesNotExist: + return self.error("Problem does not exists") + + test_case_dir = os.path.join(settings.TEST_CASE_DIR, problem.test_case_id) + if not os.path.isdir(test_case_dir): + return self.error("Test case does not exists") + name_list = self.filter_name_list(os.listdir(test_case_dir), problem.spj) + name_list.append("info") + file_name = os.path.join(test_case_dir, problem.test_case_id) + with zipfile.ZipFile(file_name, "w") as file: + for test_case in name_list: + file.write(f"{test_case_dir}/{test_case}", test_case) + response = StreamingHttpResponse(FileWrapper(open(file_name, "rb")), content_type="application/zip") + response["Content-Disposition"] = f"attachment; filename=problem_{problem.id}_test_cases.zip" + return response + @problem_permission_required def post(self, request): form = TestCaseUploadForm(request.POST, request.FILES)