This commit is contained in:
2025-10-22 20:29:12 +08:00
parent 07aaff69f2
commit c87022793e
7 changed files with 128 additions and 32 deletions

View File

@@ -0,0 +1,17 @@
# Generated by Django 5.2.3 on 2025-10-22 11:04
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('problemset', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='problemset',
name='is_public',
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 5.2.3 on 2025-10-22 12:04
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('problemset', '0002_remove_is_public_field'),
]
operations = [
migrations.RemoveField(
model_name='problemsetbadge',
name='level',
),
]

View File

@@ -20,8 +20,6 @@ class ProblemSet(models.Model):
last_update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
# 是否可见
visible = models.BooleanField(default=True, verbose_name="是否可见")
# 是否公开(所有用户都可以看到)
is_public = models.BooleanField(default=True, verbose_name="是否公开")
# 题单难度等级
difficulty = models.TextField(default="Easy", verbose_name="难度等级")
# 题单状态
@@ -81,8 +79,6 @@ class ProblemSetBadge(models.Model):
verbose_name="获得条件类型"
) # all_problems, problem_count, score
condition_value = models.IntegerField(default=0, verbose_name="条件值")
# 奖章等级
level = models.IntegerField(default=1, verbose_name="奖章等级")
class Meta:
db_table = "problemset_badge"

View File

@@ -56,6 +56,7 @@ class ProblemSetListSerializer(serializers.ModelSerializer):
"status",
"problems_count",
"user_progress",
"visible",
]
def get_problems_count(self, obj):
@@ -100,7 +101,6 @@ class CreateProblemSetSerializer(serializers.Serializer):
title = serializers.CharField(max_length=200)
description = serializers.CharField()
difficulty = serializers.CharField(default="Easy")
is_public = serializers.BooleanField(default=True)
status = serializers.CharField(default="active")
@@ -111,7 +111,6 @@ class EditProblemSetSerializer(serializers.Serializer):
title = serializers.CharField(max_length=200, required=False)
description = serializers.CharField(required=False)
difficulty = serializers.CharField(required=False)
is_public = serializers.BooleanField(required=False)
status = serializers.CharField(required=False)
visible = serializers.BooleanField(required=False)
@@ -135,14 +134,22 @@ class ProblemSetProblemSerializer(serializers.ModelSerializer):
class AddProblemToSetSerializer(serializers.Serializer):
"""添加题目到题单序列化器"""
problemset_id = serializers.IntegerField()
problem_id = serializers.IntegerField()
problem_id = serializers.CharField()
order = serializers.IntegerField(default=0)
is_required = serializers.BooleanField(default=True)
score = serializers.IntegerField(default=0)
hint = serializers.CharField(required=False, allow_blank=True)
class EditProblemInSetSerializer(serializers.Serializer):
"""编辑题单中的题目序列化器"""
order = serializers.IntegerField(required=False)
is_required = serializers.BooleanField(required=False)
score = serializers.IntegerField(required=False)
hint = serializers.CharField(required=False, allow_blank=True)
class ProblemSetBadgeSerializer(serializers.ModelSerializer):
"""题单奖章序列化器"""
@@ -153,14 +160,20 @@ class ProblemSetBadgeSerializer(serializers.ModelSerializer):
class CreateProblemSetBadgeSerializer(serializers.Serializer):
"""创建题单奖章序列化器"""
problemset_id = serializers.IntegerField()
name = serializers.CharField(max_length=100)
description = serializers.CharField()
icon = serializers.CharField()
condition_type = serializers.CharField() # all_problems, problem_count, score
condition_value = serializers.IntegerField()
level = serializers.IntegerField(default=1)
class EditProblemSetBadgeSerializer(serializers.Serializer):
"""编辑题单奖章序列化器"""
name = serializers.CharField(max_length=100, required=False)
description = serializers.CharField(required=False)
icon = serializers.CharField(required=False)
condition_type = serializers.CharField(required=False) # all_problems, problem_count, score
condition_value = serializers.IntegerField(required=False)
class ProblemSetProgressSerializer(serializers.ModelSerializer):

View File

@@ -24,7 +24,7 @@ urlpatterns = [
name="admin_problemset_problems_api",
),
path(
"problemset/<int:problem_set_id>/problems/<int:problem_id>/",
"problemset/<int:problem_set_id>/problems/<int:problem_set_problem_id>/",
ProblemSetProblemAdminAPI.as_view(),
name="admin_problemset_problem_detail_api",
),

View File

@@ -16,8 +16,10 @@ from problemset.serializers import (
EditProblemSetSerializer,
ProblemSetProblemSerializer,
AddProblemToSetSerializer,
EditProblemInSetSerializer,
ProblemSetBadgeSerializer,
CreateProblemSetBadgeSerializer,
EditProblemSetBadgeSerializer,
ProblemSetProgressSerializer,
)
from problem.models import Problem
@@ -152,7 +154,7 @@ class ProblemSetProblemAdminAPI(APIView):
data = request.data
try:
problem = Problem.objects.get(id=data["problem_id"])
problem = Problem.objects.get(_id=data["problem_id"])
except Problem.DoesNotExist:
return self.error("题目不存在")
@@ -174,7 +176,38 @@ class ProblemSetProblemAdminAPI(APIView):
return self.success("题目已添加到题单")
@super_admin_required
def delete(self, request, problem_set_id, problem_id):
@validate_serializer(EditProblemInSetSerializer)
def put(self, request, problem_set_id, problem_set_problem_id):
"""编辑题单中的题目(管理员)"""
try:
problem_set = ProblemSet.objects.get(id=problem_set_id)
ensure_created_by(problem_set, request.user)
except ProblemSet.DoesNotExist:
return self.error("题单不存在")
try:
problem_set_problem = ProblemSetProblem.objects.get(
id=problem_set_problem_id, problemset=problem_set
)
except ProblemSetProblem.DoesNotExist:
return self.error("题目不在该题单中")
data = request.data
# 更新题目属性
if 'order' in data:
problem_set_problem.order = data['order']
if 'is_required' in data:
problem_set_problem.is_required = data['is_required']
if 'score' in data:
problem_set_problem.score = data['score']
if 'hint' in data:
problem_set_problem.hint = data['hint']
problem_set_problem.save()
return self.success("题目已更新")
@super_admin_required
def delete(self, request, problem_set_id, problem_set_problem_id):
"""从题单中移除题目(管理员)"""
try:
problem_set = ProblemSet.objects.get(id=problem_set_id)
@@ -184,7 +217,7 @@ class ProblemSetProblemAdminAPI(APIView):
try:
problem_set_problem = ProblemSetProblem.objects.get(
problemset=problem_set, problem_id=problem_id
id=problem_set_problem_id, problemset=problem_set
)
problem_set_problem.delete()
return self.success("题目已从题单中移除")
@@ -224,6 +257,39 @@ class ProblemSetBadgeAdminAPI(APIView):
return self.success(ProblemSetBadgeSerializer(badge).data)
@super_admin_required
@validate_serializer(EditProblemSetBadgeSerializer)
def put(self, request, problem_set_id, badge_id):
"""编辑题单奖章(管理员)"""
try:
problem_set = ProblemSet.objects.get(id=problem_set_id)
ensure_created_by(problem_set, request.user)
except ProblemSet.DoesNotExist:
return self.error("题单不存在")
try:
badge = ProblemSetBadge.objects.get(id=badge_id, problemset=problem_set)
except ProblemSetBadge.DoesNotExist:
return self.error("奖章不存在")
data = request.data
# 更新奖章属性
if 'name' in data:
badge.name = data['name']
if 'description' in data:
badge.description = data['description']
if 'icon' in data:
badge.icon = data['icon']
if 'condition_type' in data:
badge.condition_type = data['condition_type']
if 'condition_value' in data:
badge.condition_value = data['condition_value']
if 'level' in data:
badge.level = data['level']
badge.save()
return self.success("奖章已更新")
@super_admin_required
def delete(self, request, problem_set_id, badge_id):
"""删除题单奖章(管理员)"""

View File

@@ -50,9 +50,7 @@ class ProblemSetAPI(APIView):
if status_filter:
problem_sets = problem_sets.filter(status=status_filter)
# 只显示公开的题单,除非是管理员
if not request.user.is_authenticated or not request.user.is_admin_role():
problem_sets = problem_sets.filter(is_public=True)
# 所有用户都可以看到可见的题单
# 排序
sort = request.GET.get("sort")
@@ -83,12 +81,7 @@ class ProblemSetDetailAPI(APIView):
except ProblemSet.DoesNotExist:
return self.error("题单不存在")
# 检查权限
if not problem_set.is_public and not (
request.user.is_authenticated and request.user.is_admin_role()
):
return self.error("无权限访问该题单")
# 题单可见即可访问
serializer = ProblemSetSerializer(problem_set, context={"request": request})
return self.success(serializer.data)
@@ -139,11 +132,7 @@ class ProblemSetProblemAPI(APIView):
except ProblemSet.DoesNotExist:
return self.error("题单不存在")
# 检查权限
if not problem_set.is_public and not (
request.user.is_authenticated and request.user.is_admin_role()
):
return self.error("无权限访问该题单")
# 题单可见即可访问
problems = ProblemSetProblem.objects.filter(problemset=problem_set).order_by(
"order"
@@ -221,9 +210,7 @@ class ProblemSetProgressAPI(APIView):
except ProblemSet.DoesNotExist:
return self.error("题单不存在")
# 检查权限
if not problem_set.is_public and not request.user.is_admin_role():
return self.error("无权限加入该题单")
# 题单可见即可加入
# 检查是否已经加入
if ProblemSetProgress.objects.filter(