From 88a322b248d1d4956e47237670729b13489bf5c7 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Sat, 29 Jun 2024 21:33:22 +0800 Subject: [PATCH] add message and comment --- announcement/migrations/0006_message.py | 122 +++++++++--------- .../migrations/0007_delete_message.py | 16 +++ announcement/models.py | 13 -- announcement/serializers.py | 18 +-- announcement/urls/oj.py | 3 +- announcement/views/oj.py | 37 +----- comment/__init__.py | 0 comment/migrations/0001_initial.py | 40 ++++++ comment/migrations/__init__.py | 0 comment/models.py | 47 +++++++ comment/serializers.py | 19 +++ comment/urls/__init__.py | 0 comment/urls/oj.py | 8 ++ comment/views/__init__.py | 0 comment/views/oj.py | 64 +++++++++ message/__init__.py | 0 message/migrations/0001_initial.py | 34 +++++ message/migrations/__init__.py | 0 message/models.py | 18 +++ message/serializers.py | 19 +++ message/urls/__init__.py | 0 message/urls/oj.py | 7 + message/views/__init__.py | 0 message/views/oj.py | 40 ++++++ oj/settings.py | 2 + oj/urls.py | 2 + problem/models.py | 6 +- problem/views/oj.py | 60 ++++++--- 28 files changed, 431 insertions(+), 144 deletions(-) create mode 100644 announcement/migrations/0007_delete_message.py create mode 100644 comment/__init__.py create mode 100644 comment/migrations/0001_initial.py create mode 100644 comment/migrations/__init__.py create mode 100644 comment/models.py create mode 100644 comment/serializers.py create mode 100644 comment/urls/__init__.py create mode 100644 comment/urls/oj.py create mode 100644 comment/views/__init__.py create mode 100644 comment/views/oj.py create mode 100644 message/__init__.py create mode 100644 message/migrations/0001_initial.py create mode 100644 message/migrations/__init__.py create mode 100644 message/models.py create mode 100644 message/serializers.py create mode 100644 message/urls/__init__.py create mode 100644 message/urls/oj.py create mode 100644 message/views/__init__.py create mode 100644 message/views/oj.py diff --git a/announcement/migrations/0006_message.py b/announcement/migrations/0006_message.py index 89414cb..4960562 100644 --- a/announcement/migrations/0006_message.py +++ b/announcement/migrations/0006_message.py @@ -1,61 +1,61 @@ -# Generated by Django 5.0.6 on 2024-06-25 11:47 - -import django.db.models.deletion -import utils.models -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("announcement", "0005_alter_announcement_options_announcement_top"), - ("submission", "0013_alter_submission_info_and_more"), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name="Message", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("message", utils.models.RichTextField()), - ("create_time", models.DateTimeField(auto_now_add=True)), - ( - "recipient", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="recipient", - to=settings.AUTH_USER_MODEL, - ), - ), - ( - "sender", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="sender", - to=settings.AUTH_USER_MODEL, - ), - ), - ( - "submission", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - to="submission.submission", - ), - ), - ], - options={ - "db_table": "message", - "ordering": ("-create_time",), - }, - ), - ] +# Generated by Django 5.0.6 on 2024-06-25 11:47 + +import django.db.models.deletion +import utils.models +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("announcement", "0005_alter_announcement_options_announcement_top"), + ("submission", "0013_alter_submission_info_and_more"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="Message", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("message", utils.models.RichTextField()), + ("create_time", models.DateTimeField(auto_now_add=True)), + ( + "recipient", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="recipient", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "sender", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="sender", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "submission", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="submission.submission", + ), + ), + ], + options={ + "db_table": "message", + "ordering": ("-create_time",), + }, + ), + ] diff --git a/announcement/migrations/0007_delete_message.py b/announcement/migrations/0007_delete_message.py new file mode 100644 index 0000000..de1f4cb --- /dev/null +++ b/announcement/migrations/0007_delete_message.py @@ -0,0 +1,16 @@ +# Generated by Django 5.0.6 on 2024-06-29 15:38 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('announcement', '0006_message'), + ] + + operations = [ + migrations.DeleteModel( + name='Message', + ), + ] diff --git a/announcement/models.py b/announcement/models.py index 810d6f0..68b9ede 100644 --- a/announcement/models.py +++ b/announcement/models.py @@ -1,7 +1,6 @@ from django.db import models from account.models import User -from submission.models import Submission from utils.models import RichTextField @@ -19,15 +18,3 @@ class Announcement(models.Model): class Meta: db_table = "announcement" ordering = ("-top", "-create_time",) - - -class Message(models.Model): - sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="sender") - recipient = models.ForeignKey(User, on_delete=models.CASCADE, related_name="recipient") - submission = models.ForeignKey(Submission, on_delete=models.CASCADE) - message = RichTextField() - create_time = models.DateTimeField(auto_now_add=True) - - class Meta: - db_table = "message" - ordering = ("-create_time",) diff --git a/announcement/serializers.py b/announcement/serializers.py index c20915e..cc7b0fe 100644 --- a/announcement/serializers.py +++ b/announcement/serializers.py @@ -1,8 +1,7 @@ -from submission.serializers import SubmissionSafeModelSerializer from utils.api import serializers from utils.api._serializers import UsernameSerializer -from .models import Announcement, Message +from .models import Announcement class CreateAnnouncementSerializer(serializers.Serializer): @@ -36,18 +35,3 @@ class EditAnnouncementSerializer(serializers.Serializer): content = serializers.CharField(max_length=1024 * 1024 * 8) visible = serializers.BooleanField() top = serializers.BooleanField() - - -class MessageSerializer(serializers.ModelSerializer): - sender = UsernameSerializer() - submission = SubmissionSafeModelSerializer() - - class Meta: - model = Message - exclude = ["recipient"] - - -class CreateMessageSerializer(serializers.Serializer): - recipient = serializers.IntegerField() - submission = serializers.CharField() - message = serializers.CharField() diff --git a/announcement/urls/oj.py b/announcement/urls/oj.py index 1a463e4..2cdc923 100644 --- a/announcement/urls/oj.py +++ b/announcement/urls/oj.py @@ -1,8 +1,7 @@ from django.urls import re_path as url -from ..views.oj import AnnouncementAPI, MessageAPI +from ..views.oj import AnnouncementAPI urlpatterns = [ url(r"^announcement/?$", AnnouncementAPI.as_view(), name="announcement_api"), - url(r"^message/?$", MessageAPI.as_view(), name="message_api"), ] diff --git a/announcement/views/oj.py b/announcement/views/oj.py index 3768fb1..ec814eb 100644 --- a/announcement/views/oj.py +++ b/announcement/views/oj.py @@ -1,14 +1,8 @@ -from account.decorators import super_admin_required, login_required -from account.models import User -from submission.models import Submission from utils.api import APIView -from announcement.models import Announcement, Message +from announcement.models import Announcement from announcement.serializers import (AnnouncementSerializer, - AnnouncementListSerializer, - CreateMessageSerializer, - MessageSerializer) -from utils.api.api import validate_serializer + AnnouncementListSerializer) class AnnouncementAPI(APIView): @@ -23,30 +17,3 @@ class AnnouncementAPI(APIView): announcements = Announcement.objects.filter(visible=True) return self.success(self.paginate_data(request, announcements, AnnouncementListSerializer)) - - -class MessageAPI(APIView): - @login_required - def get(self, request): - messages = Message.objects.select_related("recipient","sender", "submission").filter(recipient=request.user) - return self.success(self.paginate_data(request, messages, MessageSerializer)) - - @validate_serializer(CreateMessageSerializer) - @super_admin_required - def post(self, request): - data = request.data - if data["recipient"] == request.user.id: - return self.error("Can not send a message to youself") - try: - recipient = User.objects.get(id=data["recipient"], is_disabled=False) - except User.DoesNotExist: - return self.error("User does not exist") - try: - submission = Submission.objects.get(id=data["submission"]) - except Submission.DoesNotExist: - return self.error("Submission does not exist") - Message.objects.create(submission=submission, - message=data["message"], - sender=request.user, - recipient=recipient) - return self.success() diff --git a/comment/__init__.py b/comment/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/comment/migrations/0001_initial.py b/comment/migrations/0001_initial.py new file mode 100644 index 0000000..0b79baa --- /dev/null +++ b/comment/migrations/0001_initial.py @@ -0,0 +1,40 @@ +# Generated by Django 5.0.6 on 2024-06-29 13:32 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('problem', '0015_alter_problem_io_mode_alter_problem_languages_and_more'), + ('submission', '0013_alter_submission_info_and_more'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Comment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('problem_solved', models.BooleanField()), + ('language', models.CharField(blank=True, choices=[('Python', 'Python'), ('C', 'C'), ('C++', 'C++'), ('Java', 'Java')], max_length=10, null=True, verbose_name='解决这道题使用的语言')), + ('description_rating', models.PositiveSmallIntegerField(default=5, verbose_name='题目描述的分数')), + ('difficulty_rating', models.PositiveSmallIntegerField(default=5, verbose_name='题目难度的分数')), + ('comprehensive_rating', models.PositiveSmallIntegerField(default=5, verbose_name='综合的分数')), + ('content', models.TextField(blank=True, null=True)), + ('visible', models.BooleanField(default=True)), + ('create_time', models.DateTimeField(auto_now_add=True)), + ('problem', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='problem.problem')), + ('submission', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='submission.submission')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'db_table': 'comment', + 'ordering': ('create_time',), + }, + ), + ] diff --git a/comment/migrations/__init__.py b/comment/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/comment/models.py b/comment/models.py new file mode 100644 index 0000000..3fe0add --- /dev/null +++ b/comment/models.py @@ -0,0 +1,47 @@ +from django.db import models + +from account.models import User +from problem.models import Problem +from submission.models import Submission + + +class Languages(models.TextChoices): + Python = "Python", "Python" + C = "C", "C" + Cpp = "C++", "C++" + Java = "Java", "Java" + + +class Comment(models.Model): + problem = models.ForeignKey(Problem, on_delete=models.CASCADE) + user = models.ForeignKey(User, on_delete=models.CASCADE) + submission = models.ForeignKey(Submission, null=True, blank=True, on_delete=models.SET_NULL) + problem_solved = models.BooleanField() + language = models.CharField( + max_length=10, + choices=Languages.choices, + null=True, + blank=True, + verbose_name="解决这道题使用的语言", + ) + description_rating = models.PositiveSmallIntegerField( + default=5, + verbose_name="题目描述的分数", + ) + difficulty_rating = models.PositiveSmallIntegerField( + default=5, + verbose_name="题目难度的分数", + ) + comprehensive_rating = models.PositiveSmallIntegerField( + default=5, + verbose_name="综合的分数", + ) + content = models.TextField(null=True, blank=True) + visible = models.BooleanField(default=True) + create_time = models.DateTimeField(auto_now_add=True) + + class Meta: + db_table = "comment" + ordering = ("create_time",) + + diff --git a/comment/serializers.py b/comment/serializers.py new file mode 100644 index 0000000..3c774e8 --- /dev/null +++ b/comment/serializers.py @@ -0,0 +1,19 @@ +from comment.models import Comment +from utils.api import serializers + + +class CreateCommentSerializer(serializers.Serializer): + problem_id = serializers.IntegerField() + submission_id = serializers.CharField(max_length=32, allow_null=True) + problem_solved = serializers.BooleanField() + language = serializers.CharField(max_length=10, allow_null=True) + description_rating = serializers.IntegerField() + difficulty_rating = serializers.IntegerField() + comprehensive_rating = serializers.IntegerField() + content = serializers.CharField() + + +class CommentSerializer(serializers.ModelSerializer): + class Meta: + model = Comment + fields = "__all__" diff --git a/comment/urls/__init__.py b/comment/urls/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/comment/urls/oj.py b/comment/urls/oj.py new file mode 100644 index 0000000..6f12edb --- /dev/null +++ b/comment/urls/oj.py @@ -0,0 +1,8 @@ +from django.urls import re_path as url + +from ..views.oj import CommentAPI + + +urlpatterns = [ + url(r"^comment/?$", CommentAPI.as_view(), name="comment_api"), +] diff --git a/comment/views/__init__.py b/comment/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/comment/views/oj.py b/comment/views/oj.py new file mode 100644 index 0000000..9973e77 --- /dev/null +++ b/comment/views/oj.py @@ -0,0 +1,64 @@ +from django.db.models import Avg +from comment.models import Comment +from problem.models import Problem +from utils.api import APIView +from account.decorators import login_required +from utils.api.api import validate_serializer +from comment.serializers import CreateCommentSerializer +from submission.models import Submission, JudgeStatus + + +class CommentAPI(APIView): + @validate_serializer(CreateCommentSerializer) + @login_required + def post(self, request): + data = request.data + try: + problem = Problem.objects.get(id=data.problem_id, visible=True) + except Problem.DoesNotExist: + self.error("problem is not exists") + + submission = None + if data.problem_solved and data.submission_id: + try: + data.submission_id + submission = Submission.objects.select_related("problem").get( + id=data.submission_id, + problem_id=data.problem_id, + result=JudgeStatus.ACCEPTED, + ) + except Submission.DoesNotExist: + self.error("submission is not exists or not accepted") + + if not data.problem_solved: + data.language = None + + Comment.objects.create( + user=request.user, + problem=problem, + submission=submission, + problem_solved=data.problem_solved, + language=data.language, + description_rating=data.description_rating, + difficulty_rating=data.difficulty_rating, + comprehensive_rating=data.comprehensive_rating, + content=data.content, + ) + return self.success() + + def get(self, request): + problem_id = request.GET.get("problem_id") + comments = Comment.objects.select_related("problem").filter( + problem_id=problem_id, visible=True + ) + if comments.count() == 0: + return self.success() + rating = comments.aggregate( + description=Avg("description_rating"), + difficulty=Avg("difficulty_rating"), + comprehensive=Avg("comprehensive_rating"), + ) + contents = comments.filter(content__isnull=False).values_list( + "content", flat=True + ) + return self.success({rating: rating, contents: contents}) diff --git a/message/__init__.py b/message/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/message/migrations/0001_initial.py b/message/migrations/0001_initial.py new file mode 100644 index 0000000..76cda10 --- /dev/null +++ b/message/migrations/0001_initial.py @@ -0,0 +1,34 @@ +# Generated by Django 5.0.6 on 2024-06-29 15:38 + +import django.db.models.deletion +import utils.models +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('submission', '0013_alter_submission_info_and_more'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Message', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('message', utils.models.RichTextField()), + ('create_time', models.DateTimeField(auto_now_add=True)), + ('recipient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='recipient', to=settings.AUTH_USER_MODEL)), + ('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sender', to=settings.AUTH_USER_MODEL)), + ('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='submission.submission')), + ], + options={ + 'db_table': 'message', + 'ordering': ('-create_time',), + }, + ), + ] diff --git a/message/migrations/__init__.py b/message/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/message/models.py b/message/models.py new file mode 100644 index 0000000..7f90350 --- /dev/null +++ b/message/models.py @@ -0,0 +1,18 @@ +from django.db import models +from account.models import User +from submission.models import Submission +from utils.models import RichTextField + + +class Message(models.Model): + sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="sender") + recipient = models.ForeignKey( + User, on_delete=models.CASCADE, related_name="recipient" + ) + submission = models.ForeignKey(Submission, on_delete=models.CASCADE) + message = RichTextField() + create_time = models.DateTimeField(auto_now_add=True) + + class Meta: + db_table = "message" + ordering = ("-create_time",) diff --git a/message/serializers.py b/message/serializers.py new file mode 100644 index 0000000..93b8bc2 --- /dev/null +++ b/message/serializers.py @@ -0,0 +1,19 @@ +from submission.serializers import SubmissionSafeModelSerializer +from utils.api import UsernameSerializer, serializers +from .models import Message + + + +class MessageSerializer(serializers.ModelSerializer): + sender = UsernameSerializer() + submission = SubmissionSafeModelSerializer() + + class Meta: + model = Message + exclude = ["recipient"] + + +class CreateMessageSerializer(serializers.Serializer): + recipient = serializers.IntegerField() + submission = serializers.CharField() + message = serializers.CharField() diff --git a/message/urls/__init__.py b/message/urls/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/message/urls/oj.py b/message/urls/oj.py new file mode 100644 index 0000000..2875cd9 --- /dev/null +++ b/message/urls/oj.py @@ -0,0 +1,7 @@ +from django.urls import re_path as url + +from ..views.oj import MessageAPI + +urlpatterns = [ + url(r"^message/?$", MessageAPI.as_view(), name="message_api"), +] diff --git a/message/views/__init__.py b/message/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/message/views/oj.py b/message/views/oj.py new file mode 100644 index 0000000..5b5b831 --- /dev/null +++ b/message/views/oj.py @@ -0,0 +1,40 @@ +from account.decorators import super_admin_required, login_required +from account.models import User +from message.serializers import CreateMessageSerializer, MessageSerializer +from submission.models import Submission +from utils.api import APIView + +from message.models import Message + +from utils.api.api import validate_serializer + + +class MessageAPI(APIView): + @login_required + def get(self, request): + messages = Message.objects.select_related( + "recipient", "sender", "submission" + ).filter(recipient=request.user) + return self.success(self.paginate_data(request, messages, MessageSerializer)) + + @validate_serializer(CreateMessageSerializer) + @super_admin_required + def post(self, request): + data = request.data + if data["recipient"] == request.user.id: + return self.error("Can not send a message to youself") + try: + recipient = User.objects.get(id=data["recipient"], is_disabled=False) + except User.DoesNotExist: + return self.error("User does not exist") + try: + submission = Submission.objects.get(id=data["submission"]) + except Submission.DoesNotExist: + return self.error("Submission does not exist") + Message.objects.create( + submission=submission, + message=data["message"], + sender=request.user, + recipient=recipient, + ) + return self.success() diff --git a/oj/settings.py b/oj/settings.py index 74c559b..7f48afe 100644 --- a/oj/settings.py +++ b/oj/settings.py @@ -51,6 +51,8 @@ LOCAL_APPS = [ 'submission', 'options', 'judge', + 'message', + 'comment' ] INSTALLED_APPS = VENDOR_APPS + LOCAL_APPS diff --git a/oj/urls.py b/oj/urls.py index d0e3523..9834589 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -14,4 +14,6 @@ urlpatterns = [ url(r"^api/", include("submission.urls.oj")), url(r"^api/admin/", include("submission.urls.admin")), url(r"^api/admin/", include("utils.urls")), + url(r"^api/", include("message.urls.oj")), + url(r"^api/", include("comment.urls.oj")), ] diff --git a/problem/models.py b/problem/models.py index c16aead..e3c7c4c 100644 --- a/problem/models.py +++ b/problem/models.py @@ -31,7 +31,11 @@ class ProblemIOMode(Choices): def _default_io_mode(): - return {"io_mode": ProblemIOMode.standard, "input": "input.txt", "output": "output.txt"} + return { + "io_mode": ProblemIOMode.standard, + "input": "input.txt", + "output": "output.txt", + } class Problem(models.Model): diff --git a/problem/views/oj.py b/problem/views/oj.py index dbc49a9..6938405 100644 --- a/problem/views/oj.py +++ b/problem/views/oj.py @@ -3,8 +3,14 @@ from django.db.models import Q, Count from utils.api import APIView from account.decorators import check_contest_permission from ..models import ProblemTag, Problem, ProblemRuleType -from ..serializers import ProblemSerializer, TagSerializer, ProblemSafeSerializer, ProblemListSerializer +from ..serializers import ( + ProblemSerializer, + TagSerializer, + ProblemSafeSerializer, + ProblemListSerializer, +) from contest.models import ContestRuleType +from submission.models import JudgeStatus class ProblemTagAPI(APIView): @@ -38,20 +44,27 @@ class ProblemAPI(APIView): if results is not None: problems = results else: - problems = [queryset_values, ] + problems = [ + queryset_values, + ] for problem in problems: if problem["rule_type"] == ProblemRuleType.ACM: - problem["my_status"] = acm_problems_status.get(str(problem["id"]), {}).get("status") + problem["my_status"] = acm_problems_status.get( + str(problem["id"]), {} + ).get("status") else: - problem["my_status"] = oi_problems_status.get(str(problem["id"]), {}).get("status") + problem["my_status"] = oi_problems_status.get( + str(problem["id"]), {} + ).get("status") def get(self, request): # 问题详情页 problem_id = request.GET.get("problem_id") if problem_id: try: - problem = Problem.objects.select_related("created_by") \ - .get(_id=problem_id, contest_id__isnull=True, visible=True) + problem = Problem.objects.select_related("created_by").get( + _id=problem_id, contest_id__isnull=True, visible=True + ) problem_data = ProblemSerializer(problem).data self._add_problem_status(request, problem_data) return self.success(problem_data) @@ -62,7 +75,11 @@ class ProblemAPI(APIView): if not limit: return self.error("Limit is needed") - problems = Problem.objects.select_related("created_by").filter(contest_id__isnull=True, visible=True).order_by("-create_time") + problems = ( + Problem.objects.select_related("created_by") + .filter(contest_id__isnull=True, visible=True) + .order_by("-create_time") + ) # 按照标签筛选 tag_text = request.GET.get("tag") if tag_text: @@ -71,7 +88,9 @@ class ProblemAPI(APIView): # 搜索的情况 keyword = request.GET.get("keyword", "").strip() if keyword: - problems = problems.filter(Q(title__icontains=keyword) | Q(_id__icontains=keyword)) + problems = problems.filter( + Q(title__icontains=keyword) | Q(_id__icontains=keyword) + ) # 难度筛选 difficulty = request.GET.get("difficulty") @@ -88,30 +107,41 @@ class ContestProblemAPI(APIView): if request.user.is_authenticated: profile = request.user.userprofile if self.contest.rule_type == ContestRuleType.ACM: - problems_status = profile.acm_problems_status.get("contest_problems", {}) + problems_status = profile.acm_problems_status.get( + "contest_problems", {} + ) else: problems_status = profile.oi_problems_status.get("contest_problems", {}) for problem in queryset_values: - problem["my_status"] = problems_status.get(str(problem["id"]), {}).get("status") + problem["my_status"] = problems_status.get(str(problem["id"]), {}).get( + "status" + ) @check_contest_permission(check_type="problems") def get(self, request): problem_id = request.GET.get("problem_id") if problem_id: try: - problem = Problem.objects.select_related("created_by").get(_id=problem_id, - contest=self.contest, - visible=True) + problem = Problem.objects.select_related("created_by").get( + _id=problem_id, contest=self.contest, visible=True + ) except Problem.DoesNotExist: return self.error("Problem does not exist.") if self.contest.problem_details_permission(request.user): problem_data = ProblemSerializer(problem).data - self._add_problem_status(request, [problem_data, ]) + self._add_problem_status( + request, + [ + problem_data, + ], + ) else: problem_data = ProblemSafeSerializer(problem).data return self.success(problem_data) - contest_problems = Problem.objects.select_related("created_by").filter(contest=self.contest, visible=True) + contest_problems = Problem.objects.select_related("created_by").filter( + contest=self.contest, visible=True + ) if self.contest.problem_details_permission(request.user): data = ProblemListSerializer(contest_problems, many=True).data self._add_problem_status(request, data)