diff --git a/task/challenge.py b/task/challenge.py index e751274..1292fab 100644 --- a/task/challenge.py +++ b/task/challenge.py @@ -15,7 +15,7 @@ def challenge(request): """ 后台显示所有的列表 """ - return Challenge.objects.all() + return Challenge.objects.select_related("author").all() @router.get("/display", response=List[ChallengeDisplay]) @@ -23,7 +23,11 @@ def get_all_public_display(request): """ 前台显示所有公开的挑战 """ - challenges = list(Challenge.objects.filter(is_public=True).order_by("-display")) + challenges = list( + Challenge.objects.select_related("author") + .filter(is_public=True) + .order_by("-display") + ) if request.user.is_authenticated: task_ids = [c.task_ptr_id for c in challenges] submitted_ids = set( @@ -41,6 +45,7 @@ def get_all_public_display(request): score=c.score, pass_score=c.pass_score, is_public=c.is_public, + author_name=c.author_name, submitted=c.task_ptr_id in submitted_ids, ) for c in challenges @@ -49,7 +54,9 @@ def get_all_public_display(request): @router.get("/{display}", response=ChallengeAll) def get(request, display: int): - return get_object_or_404(Challenge, display=display) + return get_object_or_404( + Challenge.objects.select_related("author"), display=display + ) @router.post("/") @@ -61,10 +68,12 @@ def create_or_update(request, payload: ChallengeIn): item.content = payload.content item.score = payload.score item.is_public = payload.is_public + if item.author_id is None and request.user.is_authenticated: + item.author = request.user item.save() return {"message": "更新成功"} except Challenge.DoesNotExist: - Challenge.objects.create(**payload.dict()) + Challenge.objects.create(**payload.dict(), author=request.user) return {"message": "创建成功"} diff --git a/task/migrations/0008_challenge_author.py b/task/migrations/0008_challenge_author.py new file mode 100644 index 0000000..4d25ae4 --- /dev/null +++ b/task/migrations/0008_challenge_author.py @@ -0,0 +1,28 @@ +# Generated by Codex on 2026-05-06 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("task", "0007_taskasset"), + ] + + operations = [ + migrations.AddField( + model_name="challenge", + name="author", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="authored_challenges", + to=settings.AUTH_USER_MODEL, + verbose_name="出题人", + ), + ), + ] diff --git a/task/models.py b/task/models.py index 649e029..8d4e889 100644 --- a/task/models.py +++ b/task/models.py @@ -1,4 +1,5 @@ from django.db import models +from django.conf import settings from django_extensions.db.models import TimeStampedModel @@ -41,6 +42,18 @@ class Tutorial(Task): class Challenge(Task): score = models.IntegerField(default=0) pass_score = models.FloatField(null=True, blank=True, verbose_name="通过分数线") + author = models.ForeignKey( + settings.AUTH_USER_MODEL, + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name="authored_challenges", + verbose_name="出题人", + ) + + @property + def author_name(self): + return self.author.username if self.author_id else "" def __str__(self): return self.title diff --git a/task/schemas.py b/task/schemas.py index ea02c8a..b7139fb 100644 --- a/task/schemas.py +++ b/task/schemas.py @@ -28,6 +28,7 @@ class ChallengeSlim(Schema): score: int pass_score: Optional[float] = None is_public: bool + author_name: Optional[str] = None class ChallengeDisplay(ChallengeSlim): @@ -35,6 +36,8 @@ class ChallengeDisplay(ChallengeSlim): class ChallengeAll(ModelSchema): + author_name: Optional[str] = None + class Meta: model = Challenge fields = "__all__"