diff --git a/account/urls/admin.py b/account/urls/admin.py index b2d88d1..f37053f 100644 --- a/account/urls/admin.py +++ b/account/urls/admin.py @@ -1,9 +1,8 @@ from django.urls import path -from ..views.admin import GenerateUserAPI, ResetUserPasswordAPI, UserAdminAPI +from ..views.admin import ResetUserPasswordAPI, UserAdminAPI urlpatterns = [ path("user", UserAdminAPI.as_view()), - path("generate_user", GenerateUserAPI.as_view()), # DEPRECATED: 前端未调用 path("reset_password", ResetUserPasswordAPI.as_view()), ] diff --git a/account/urls/oj.py b/account/urls/oj.py index 067bc44..d1a103c 100644 --- a/account/urls/oj.py +++ b/account/urls/oj.py @@ -1,18 +1,12 @@ from django.urls import path from ..views.oj import ( - SSOAPI, AvatarUploadAPI, Metrics, - OpenAPIAppkeyAPI, ProfileProblemDisplayIDRefreshAPI, - SessionManagementAPI, UserActivityRankAPI, - UserChangeEmailAPI, - UserChangePasswordAPI, UserLoginAPI, UserLogoutAPI, - UsernameOrEmailCheck, UserProblemRankAPI, UserProfileAPI, UserRankAPI, @@ -23,9 +17,6 @@ urlpatterns = [ path("login", UserLoginAPI.as_view()), path("logout", UserLogoutAPI.as_view()), path("register", UserRegisterAPI.as_view()), - path("change_password", UserChangePasswordAPI.as_view()), # DEPRECATED: 前端未调用 - path("change_email", UserChangeEmailAPI.as_view()), # DEPRECATED: 前端未调用 - path("check_username_or_email", UsernameOrEmailCheck.as_view()), # DEPRECATED: 前端未调用 path("profile", UserProfileAPI.as_view(), name="user_profile_api"), path("profile/fresh_display_id", ProfileProblemDisplayIDRefreshAPI.as_view()), path("metrics", Metrics.as_view()), @@ -33,10 +24,4 @@ urlpatterns = [ path("user_rank", UserRankAPI.as_view()), path("user_activity_rank", UserActivityRankAPI.as_view()), path("user_problem_rank", UserProblemRankAPI.as_view()), - path("sessions", SessionManagementAPI.as_view()), # DEPRECATED: 前端未调用 - path( - "open_api_appkey", # DEPRECATED: 前端未调用 - OpenAPIAppkeyAPI.as_view(), - ), - path("sso", SSOAPI.as_view()), # DEPRECATED: 前端未调用 ] diff --git a/account/views/admin.py b/account/views/admin.py index 1f9b590..1c33a59 100644 --- a/account/views/admin.py +++ b/account/views/admin.py @@ -1,11 +1,8 @@ -import os import re -import xlsxwriter from django.contrib.auth.hashers import make_password from django.db import IntegrityError, transaction from django.db.models import F, Q -from django.http import HttpResponse from django.utils.crypto import get_random_string from submission.models import Submission @@ -16,7 +13,6 @@ from ..decorators import super_admin_required from ..models import AdminType, ProblemPermission, User, UserProfile from ..serializers import ( EditUserSerializer, - GenerateUserSerializer, ImportUserSerializer, UserAdminSerializer, ) @@ -168,78 +164,6 @@ class UserAdminAPI(APIView): return self.success() -# DEPRECATED: 前端未调用 (2026-05-26) -class GenerateUserAPI(APIView): - @super_admin_required - def get(self, request): - """ - download users excel - """ - file_id = request.GET.get("file_id") - if not file_id: - return self.error("Invalid Parameter, file_id is required") - if not re.match(r"^[a-zA-Z0-9]+$", file_id): - return self.error("Illegal file_id") - file_path = f"/tmp/{file_id}.xlsx" - if not os.path.isfile(file_path): - return self.error("File does not exist") - with open(file_path, "rb") as f: - raw_data = f.read() - os.remove(file_path) - response = HttpResponse(raw_data) - response["Content-Disposition"] = "attachment; filename=users.xlsx" - response["Content-Type"] = "application/xlsx" - return response - - @validate_serializer(GenerateUserSerializer) - @super_admin_required - def post(self, request): - """ - Generate User - """ - data = request.data - number_max_length = max(len(str(data["number_from"])), len(str(data["number_to"]))) - if number_max_length + len(data["prefix"]) + len(data["suffix"]) > 32: - return self.error("Username should not more than 32 characters") - if data["number_from"] > data["number_to"]: - return self.error("Start number must be lower than end number") - - file_id = rand_str(8) - filename = f"/tmp/{file_id}.xlsx" - workbook = xlsxwriter.Workbook(filename) - worksheet = workbook.add_worksheet() - worksheet.set_column("A:B", 20) - worksheet.write("A1", "Username") - worksheet.write("B1", "Password") - i = 1 - - user_list = [] - for number in range(data["number_from"], data["number_to"] + 1): - raw_password = rand_str(data["password_length"]) - user = User( - username=f"{data['prefix']}{number}{data['suffix']}", - password=make_password(raw_password), - ) - user.raw_password = raw_password - user_list.append(user) - - try: - with transaction.atomic(): - ret = User.objects.bulk_create(user_list) - UserProfile.objects.bulk_create([UserProfile(user=user) for user in ret]) - for item in user_list: - worksheet.write_string(i, 0, item.username) - worksheet.write_string(i, 1, item.raw_password) - i += 1 - workbook.close() - return self.success({"file_id": file_id}) - except IntegrityError as e: - # Extract detail from exception message - # duplicate key value violates unique constraint "user_username_key" - # DETAIL: Key (username)=(root11) already exists. - return self.error(str(e).split("\n")[1]) - - class ResetUserPasswordAPI(APIView): @super_admin_required def post(self, request): diff --git a/account/views/oj.py b/account/views/oj.py index 3c5922e..4926688 100644 --- a/account/views/oj.py +++ b/account/views/oj.py @@ -1,18 +1,17 @@ import asyncio import os -from importlib import import_module from django.conf import settings from django.contrib import auth from django.db.models import Count, Q from django.utils import timezone from django.utils.decorators import method_decorator -from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie +from django.views.decorators.csrf import ensure_csrf_cookie from options.options import SysOptions from problem.models import Problem from submission.models import JudgeStatus, Submission -from utils.api import APIView, AsyncAPIView, CSRFExemptAPIView, validate_serializer +from utils.api import AsyncAPIView, validate_serializer from utils.async_helpers import async_cache_get, async_cache_set from utils.constants import CacheKey from utils.shortcuts import datetime2str, rand_str @@ -23,11 +22,7 @@ from ..serializers import ( EditUserProfileSerializer, ImageUploadForm, RankInfoSerializer, - SSOSerializer, - UserChangeEmailSerializer, - UserChangePasswordSerializer, UserLoginSerializer, - UsernameOrEmailCheckSerializer, UserProfileSerializer, UserRegisterSerializer, ) @@ -132,23 +127,6 @@ class UserLogoutAPI(AsyncAPIView): return self.success() -# DEPRECATED: 前端未调用 (2026-05-26) -class UsernameOrEmailCheck(APIView): - @validate_serializer(UsernameOrEmailCheckSerializer) - def post(self, request): - """ - check username or email is duplicate - """ - data = request.data - # True means already exist. - result = {"username": False, "email": False} - if data.get("username"): - result["username"] = User.objects.filter(username=data["username"].lower()).exists() - if data.get("email"): - result["email"] = User.objects.filter(email=data["email"].lower()).exists() - return self.success(result) - - class UserRegisterAPI(AsyncAPIView): @validate_serializer(UserRegisterSerializer) async def post(self, request): @@ -169,87 +147,6 @@ class UserRegisterAPI(AsyncAPIView): return self.success("Succeeded") -# DEPRECATED: 前端未调用 (2026-05-26) -class UserChangeEmailAPI(APIView): - @validate_serializer(UserChangeEmailSerializer) - @login_required - def post(self, request): - data = request.data - user = auth.authenticate(username=request.user.username, password=data["password"]) - if user: - data["new_email"] = data["new_email"].lower() - if User.objects.filter(email=data["new_email"]).exists(): - return self.error("The email is owned by other account") - user.email = data["new_email"] - user.save() - return self.success("Succeeded") - else: - return self.error("Wrong password") - - -# DEPRECATED: 前端未调用 (2026-05-26) -class UserChangePasswordAPI(APIView): - @validate_serializer(UserChangePasswordSerializer) - @login_required - def post(self, request): - """ - User change password api - """ - data = request.data - username = request.user.username - user = auth.authenticate(username=username, password=data["old_password"]) - if user: - user.set_password(data["new_password"]) - user.save() - return self.success("Succeeded") - else: - return self.error("Invalid old password") - - -# DEPRECATED: 前端未调用 (2026-05-26) -class SessionManagementAPI(APIView): - @login_required - def get(self, request): - engine = import_module(settings.SESSION_ENGINE) - session_store = engine.SessionStore - current_session = request.session.session_key - session_keys = request.user.session_keys - result = [] - modified = False - for key in session_keys[:]: - session = session_store(key) - # session does not exist or is expiry - if not session._session: - session_keys.remove(key) - modified = True - continue - - s = {} - if current_session == key: - s["current_session"] = True - s["ip"] = session["ip"] - s["user_agent"] = session["user_agent"] - s["last_activity"] = datetime2str(session["last_activity"]) - s["session_key"] = key - result.append(s) - if modified: - request.user.save() - return self.success(result) - - @login_required - def delete(self, request): - session_key = request.GET.get("session_key") - if not session_key: - return self.error("Parameter Error") - request.session.delete(session_key) - if session_key in request.user.session_keys: - request.user.session_keys.remove(session_key) - request.user.save() - return self.success("Succeeded") - else: - return self.error("Invalid session_key") - - class UserRankAPI(AsyncAPIView): async def get(self, request): username = request.GET.get("username", "") @@ -354,40 +251,3 @@ class ProfileProblemDisplayIDRefreshAPI(AsyncAPIView): await profile.asave(update_fields=["acm_problems_status"]) return self.success() - -# DEPRECATED: 前端未调用 (2026-05-26) -class OpenAPIAppkeyAPI(APIView): - @login_required - def post(self, request): - user = request.user - if not user.open_api: - return self.error("OpenAPI function is truned off for you") - api_appkey = rand_str() - user.open_api_appkey = api_appkey - user.save() - return self.success({"appkey": api_appkey}) - - -# DEPRECATED: 前端未调用 (2026-05-26) -class SSOAPI(CSRFExemptAPIView): - @login_required - def get(self, request): - token = rand_str() - request.user.auth_token = token - request.user.save() - return self.success({"token": token}) - - @method_decorator(csrf_exempt) - @validate_serializer(SSOSerializer) - def post(self, request): - try: - user = User.objects.get(auth_token=request.data["token"]) - except User.DoesNotExist: - return self.error("User does not exist") - return self.success( - { - "username": user.username, - "avatar": user.userprofile.avatar, - "admin_type": user.admin_type, - } - ) diff --git a/conf/urls/oj.py b/conf/urls/oj.py index dfe01ad..208059e 100644 --- a/conf/urls/oj.py +++ b/conf/urls/oj.py @@ -4,7 +4,6 @@ from ..views import ( ClassUsernamesAPI, HitokotoAPI, JudgeServerHeartbeatAPI, - LanguagesAPI, WebsiteConfigAPI, ) @@ -12,7 +11,6 @@ urlpatterns = [ path("website", WebsiteConfigAPI.as_view()), # 这里必须要有 / path("judge_server_heartbeat/", JudgeServerHeartbeatAPI.as_view()), - path("languages", LanguagesAPI.as_view()), # DEPRECATED: 前端未调用 path("hitokoto", HitokotoAPI.as_view()), path("class_usernames", ClassUsernamesAPI.as_view()), ] diff --git a/conf/views.py b/conf/views.py index bc812fa..dee8c3c 100644 --- a/conf/views.py +++ b/conf/views.py @@ -134,16 +134,6 @@ class JudgeServerHeartbeatAPI(CSRFExemptAPIView): return self.success() -# DEPRECATED: 前端未调用 (2026-05-26) -class LanguagesAPI(APIView): - def get(self, request): - return self.success( - { - "languages": SysOptions.languages, - } - ) - - class TestCasePruneAPI(APIView): @super_admin_required def get(self, request): diff --git a/contest/urls/admin.py b/contest/urls/admin.py index 21e8aca..84cb564 100644 --- a/contest/urls/admin.py +++ b/contest/urls/admin.py @@ -1,11 +1,9 @@ from django.urls import path -from ..views.admin import ACMContestHelper, ContestAnnouncementAPI, ContestAPI, ContestCloneAPI, DownloadContestSubmissions +from ..views.admin import ACMContestHelper, ContestAPI, ContestCloneAPI urlpatterns = [ path("contest", ContestAPI.as_view()), path("contest/clone", ContestCloneAPI.as_view()), - path("contest/announcement", ContestAnnouncementAPI.as_view()), # DEPRECATED: 前端未调用 path("contest/acm_helper", ACMContestHelper.as_view()), - path("download_submissions", DownloadContestSubmissions.as_view()), # DEPRECATED: 前端未调用 ] diff --git a/contest/urls/oj.py b/contest/urls/oj.py index b20ba45..c419aa4 100644 --- a/contest/urls/oj.py +++ b/contest/urls/oj.py @@ -1,12 +1,11 @@ from django.urls import path -from ..views.oj import ContestAccessAPI, ContestAnnouncementListAPI, ContestAPI, ContestListAPI, ContestPasswordVerifyAPI, ContestRankAPI +from ..views.oj import ContestAccessAPI, ContestAPI, ContestListAPI, ContestPasswordVerifyAPI, ContestRankAPI urlpatterns = [ path("contests", ContestListAPI.as_view()), path("contest", ContestAPI.as_view()), path("contest/password", ContestPasswordVerifyAPI.as_view()), - path("contest/announcement", ContestAnnouncementListAPI.as_view()), # DEPRECATED: 前端未调用 path("contest/access", ContestAccessAPI.as_view()), path("contest_rank", ContestRankAPI.as_view()), ] diff --git a/contest/views/admin.py b/contest/views/admin.py index ab695f8..702ecb1 100644 --- a/contest/views/admin.py +++ b/contest/views/admin.py @@ -1,30 +1,19 @@ -import copy -import os -import zipfile from datetime import datetime, timedelta from ipaddress import ip_network -from django.http import FileResponse from django.utils.timezone import now -from account.decorators import ensure_created_by, super_admin_required, teacher_admin_required -from account.models import User +from account.decorators import ensure_created_by, teacher_admin_required from problem.models import Problem -from submission.models import JudgeStatus, Submission from utils.api import APIView, validate_serializer -from utils.shortcuts import rand_str -from utils.tasks import delete_files -from ..models import ACMContestRank, Contest, ContestAnnouncement +from ..models import ACMContestRank, Contest from ..serializers import ( ACMContesHelperSerializer, ContestAdminSerializer, - ContestAnnouncementSerializer, ContestCloneSerializer, CreateConetestSeriaizer, - CreateContestAnnouncementSerializer, EditConetestSeriaizer, - EditContestAnnouncementSerializer, ) @@ -96,73 +85,6 @@ class ContestAPI(APIView): return self.success(self.paginate_data(request, contests, ContestAdminSerializer)) -# DEPRECATED: 前端未调用 (2026-05-26) -class ContestAnnouncementAPI(APIView): - @validate_serializer(CreateContestAnnouncementSerializer) - @super_admin_required - def post(self, request): - """ - Create one contest_announcement. - """ - data = request.data - try: - contest = Contest.objects.get(id=data.pop("contest_id")) - data["contest"] = contest - data["created_by"] = request.user - except Contest.DoesNotExist: - return self.error("Contest does not exist") - announcement = ContestAnnouncement.objects.create(**data) - return self.success(ContestAnnouncementSerializer(announcement).data) - - @validate_serializer(EditContestAnnouncementSerializer) - @super_admin_required - def put(self, request): - """ - update contest_announcement - """ - data = request.data - try: - contest_announcement = ContestAnnouncement.objects.get(id=data.pop("id")) - except ContestAnnouncement.DoesNotExist: - return self.error("Contest announcement does not exist") - for k, v in data.items(): - setattr(contest_announcement, k, v) - contest_announcement.save() - return self.success() - - @super_admin_required - def delete(self, request): - """ - Delete one contest_announcement. - """ - contest_announcement_id = request.GET.get("id") - if contest_announcement_id: - ContestAnnouncement.objects.filter(id=contest_announcement_id).delete() - return self.success() - - @super_admin_required - def get(self, request): - """ - Get one contest_announcement or contest_announcement list. - """ - contest_announcement_id = request.GET.get("id") - if contest_announcement_id: - try: - contest_announcement = ContestAnnouncement.objects.get(id=contest_announcement_id) - return self.success(ContestAnnouncementSerializer(contest_announcement).data) - except ContestAnnouncement.DoesNotExist: - return self.error("Contest announcement does not exist") - - contest_id = request.GET.get("contest_id") - if not contest_id: - return self.error("Parameter error") - contest_announcements = ContestAnnouncement.objects.filter(contest_id=contest_id) - keyword = request.GET.get("keyword") - if keyword: - contest_announcements = contest_announcements.filter(title__contains=keyword) - return self.success(ContestAnnouncementSerializer(contest_announcements, many=True).data) - - class ACMContestHelper(APIView): @teacher_admin_required def get(self, request): @@ -217,55 +139,6 @@ class ACMContestHelper(APIView): return self.success() -# DEPRECATED: 前端未调用 (2026-05-26) -class DownloadContestSubmissions(APIView): - def _dump_submissions(self, contest, exclude_admin=True): - problem_ids = contest.problem_set.all().values_list("id", "_id") - id2display_id = {k[0]: k[1] for k in problem_ids} - ac_map = {k[0]: False for k in problem_ids} - submissions = Submission.objects.filter(contest=contest, result__in=[JudgeStatus.ACCEPTED, JudgeStatus.AST_CHECK_FAILED]).order_by("-create_time") - user_ids = submissions.values_list("user_id", flat=True) - users = User.objects.filter(id__in=user_ids) - path = f"/tmp/{rand_str()}.zip" - with zipfile.ZipFile(path, "w") as zip_file: - for user in users: - if user.is_admin_role() and exclude_admin: - continue - user_ac_map = copy.deepcopy(ac_map) - user_submissions = submissions.filter(user_id=user.id) - for submission in user_submissions: - problem_id = submission.problem_id - if user_ac_map[problem_id]: - continue - file_name = f"{user.username}_{id2display_id[submission.problem_id]}.txt" - compression = zipfile.ZIP_DEFLATED - zip_file.writestr( - zinfo_or_arcname=f"{file_name}", - data=submission.code, - compress_type=compression, - ) - user_ac_map[problem_id] = True - return path - - @super_admin_required - def get(self, request): - contest_id = request.GET.get("contest_id") - if not contest_id: - return self.error("Parameter error") - try: - contest = Contest.objects.get(id=contest_id) - except Contest.DoesNotExist: - return self.error("Contest does not exist") - - exclude_admin = request.GET.get("exclude_admin") == "1" - zip_path = self._dump_submissions(contest, exclude_admin) - delete_files.send_with_options(args=(zip_path,), delay=300_000) - resp = FileResponse(open(zip_path, "rb")) - resp["Content-Type"] = "application/zip" - resp["Content-Disposition"] = f"attachment;filename={os.path.basename(zip_path)}" - return resp - - class ContestCloneAPI(APIView): @validate_serializer(ContestCloneSerializer) @teacher_admin_required diff --git a/contest/views/oj.py b/contest/views/oj.py index ed98f8f..bb9c756 100644 --- a/contest/views/oj.py +++ b/contest/views/oj.py @@ -16,23 +16,8 @@ from utils.api import AsyncAPIView, validate_serializer from utils.constants import CONTEST_PASSWORD_SESSION_KEY, ContestStatus from utils.shortcuts import check_is_id, datetime2str -from ..models import ACMContestRank, Contest, ContestAnnouncement -from ..serializers import ACMContestRankSerializer, ContestAnnouncementSerializer, ContestPasswordVerifySerializer, ContestSerializer - - -# DEPRECATED: 前端未调用 (2026-05-26) -class ContestAnnouncementListAPI(AsyncAPIView): - @check_contest_permission(check_type="announcements") - async def get(self, request): - contest_id = request.GET.get("contest_id") - if not contest_id: - return self.error("Invalid parameter, contest_id is required") - qs = ContestAnnouncement.objects.select_related("created_by").filter(contest_id=contest_id, visible=True) - max_id = request.GET.get("max_id") - if max_id: - qs = qs.filter(id__gt=max_id) - data = await self.async_serialize_data(ContestAnnouncementSerializer, [item async for item in qs], many=True) - return self.success(data) +from ..models import ACMContestRank, Contest +from ..serializers import ACMContestRankSerializer, ContestPasswordVerifySerializer, ContestSerializer class ContestAPI(AsyncAPIView): diff --git a/problemset/urls/admin.py b/problemset/urls/admin.py index 77726eb..c55877d 100644 --- a/problemset/urls/admin.py +++ b/problemset/urls/admin.py @@ -7,7 +7,6 @@ from problemset.views.admin import ( ProblemSetProblemAdminAPI, ProblemSetProgressAdminAPI, ProblemSetStatusAPI, - ProblemSetSyncAPI, ProblemSetVisibleAPI, ) @@ -63,9 +62,4 @@ urlpatterns = [ name="admin_problemset_progress_detail_api", ), # 题单同步管理API - path( # DEPRECATED: 前端未调用 - "problemset//sync", - ProblemSetSyncAPI.as_view(), - name="admin_problemset_sync_api", - ), ] diff --git a/problemset/urls/oj.py b/problemset/urls/oj.py index 7d1b5de..b7b1e97 100644 --- a/problemset/urls/oj.py +++ b/problemset/urls/oj.py @@ -8,7 +8,6 @@ from problemset.views.oj import ( ProblemSetProgressAPI, ProblemSetUserProgressAPI, UserBadgeAPI, - UserProgressAPI, ) urlpatterns = [ @@ -24,23 +23,12 @@ urlpatterns = [ ProblemSetProblemAPI.as_view(), name="problemset_problems_api", ), - path( # DEPRECATED: 前端未调用 - "problemset//problems/", - ProblemSetProblemAPI.as_view(), - name="problemset_problem_detail_api", - ), # 进度相关API path( "problemset/progress", ProblemSetProgressAPI.as_view(), name="problemset_progress_api", ), - path( # DEPRECATED: 前端未调用 - "problemset//progress", - ProblemSetProgressAPI.as_view(), - name="problemset_progress_detail_api", - ), - path("user/progress", UserProgressAPI.as_view(), name="user_progress_api"), # DEPRECATED: 前端未调用 # 奖章相关API path("user/badges", UserBadgeAPI.as_view(), name="user_badges_api"), path( diff --git a/problemset/views/admin.py b/problemset/views/admin.py index a193380..d69e3d3 100644 --- a/problemset/views/admin.py +++ b/problemset/views/admin.py @@ -347,25 +347,6 @@ class ProblemSetProgressAdminAPI(APIView): return self.error("用户未加入该题单") -# DEPRECATED: 前端未调用 (2026-05-26) -class ProblemSetSyncAPI(APIView): - """题单同步管理API""" - - @teacher_admin_required - def post(self, request, problem_set_id): - """手动同步题单的所有用户进度(管理员)""" - try: - problem_set = ProblemSet.objects.get(id=problem_set_id) - ensure_created_by(problem_set, request.user) - except ProblemSet.DoesNotExist: - return self.error("题单不存在") - - # 同步所有用户的进度 - synced_count = ProblemSetProgress.sync_all_progress_for_problemset(problem_set) - - return self.success(f"已同步 {synced_count} 个用户的进度") - - class ProblemSetVisibleAPI(APIView): """题单可见性管理API""" diff --git a/problemset/views/oj.py b/problemset/views/oj.py index 85d3475..8525824 100644 --- a/problemset/views/oj.py +++ b/problemset/views/oj.py @@ -259,18 +259,6 @@ class ProblemSetProgressAPI(APIView): notify_badges(progress.user_id, earned) -# DEPRECATED: 前端未调用 (2026-05-26) -class UserProgressAPI(APIView): - """用户进度API""" - - @login_required - def get(self, request): - """获取用户的题单进度列表""" - progress_list = ProblemSetProgress.objects.filter(user=request.user).order_by("-join_time") - serializer = ProblemSetProgressSerializer(progress_list, many=True) - return self.success(serializer.data) - - class UserBadgeAPI(AsyncAPIView): """用户奖章API""" diff --git a/submission/urls/oj.py b/submission/urls/oj.py index 47c3328..faaab38 100644 --- a/submission/urls/oj.py +++ b/submission/urls/oj.py @@ -4,7 +4,6 @@ from ..views.oj import ( ContestSubmissionListAPI, FormatCodeAPI, SubmissionAPI, - SubmissionExistsAPI, SubmissionListAPI, SubmissionsTodayCount, ) @@ -13,7 +12,6 @@ urlpatterns = [ path("submission", SubmissionAPI.as_view()), path("submissions", SubmissionListAPI.as_view()), path("submissions/today_count", SubmissionsTodayCount.as_view()), - path("submission_exists", SubmissionExistsAPI.as_view()), # DEPRECATED: 前端未调用 path("contest_submissions", ContestSubmissionListAPI.as_view()), path("format_code", FormatCodeAPI.as_view()), ] diff --git a/submission/views/oj.py b/submission/views/oj.py index 6fd4a15..842bcf1 100644 --- a/submission/views/oj.py +++ b/submission/views/oj.py @@ -219,15 +219,6 @@ class ContestSubmissionListAPI(AsyncAPIView): return self.success(data) -# DEPRECATED: 前端未调用 (2026-05-26) -class SubmissionExistsAPI(AsyncAPIView): - async def get(self, request): - if not request.GET.get("problem_id"): - return self.error("Parameter error, problem_id is required") - exists = request.user.is_authenticated and await Submission.objects.filter(problem_id=request.GET["problem_id"], user_id=request.user.id).aexists() - return self.success(exists) - - class SubmissionsTodayCount(AsyncAPIView): async def get(self, request): now = timezone.now() diff --git a/utils/urls.py b/utils/urls.py index 10b3bd7..3551d1e 100644 --- a/utils/urls.py +++ b/utils/urls.py @@ -1,8 +1,7 @@ from django.urls import path -from .views import SimditorFileUploadAPIView, SimditorImageUploadAPIView +from .views import SimditorImageUploadAPIView urlpatterns = [ path("upload_image", SimditorImageUploadAPIView.as_view()), - path("upload_file", SimditorFileUploadAPIView.as_view()), # DEPRECATED: 前端未调用 ] diff --git a/utils/views.py b/utils/views.py index 51e2c04..dfbf41b 100644 --- a/utils/views.py +++ b/utils/views.py @@ -3,7 +3,7 @@ import os from django.conf import settings -from account.serializers import FileUploadForm, ImageUploadForm +from account.serializers import ImageUploadForm from utils.api import CSRFExemptAPIView from utils.shortcuts import rand_str @@ -33,25 +33,3 @@ class SimditorImageUploadAPIView(CSRFExemptAPIView): return self.response({"success": False, "msg": "Upload Error", "file_path": ""}) return self.response({"success": True, "msg": "Success", "file_path": f"{settings.UPLOAD_PREFIX}/{img_name}"}) - -# DEPRECATED: 前端未调用 (2026-05-26) -class SimditorFileUploadAPIView(CSRFExemptAPIView): - request_parsers = () - - def post(self, request): - form = FileUploadForm(request.POST, request.FILES) - if form.is_valid(): - file = form.cleaned_data["file"] - else: - return self.response({"success": False, "msg": "Upload failed"}) - - suffix = os.path.splitext(file.name)[-1].lower() - file_name = rand_str(10) + suffix - try: - with open(os.path.join(settings.UPLOAD_DIR, file_name), "wb") as f: - for chunk in file: - f.write(chunk) - except IOError as e: - logger.error(e) - return self.response({"success": False, "msg": "Upload Error"}) - return self.response({"success": True, "msg": "Success", "file_path": f"{settings.UPLOAD_PREFIX}/{file_name}", "file_name": file.name})