mirror of
https://gitlab.com/megazordpobeda/DataRush.git
synced 2026-05-23 15:37:10 +00:00
add basic admin for task
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from apps.competition.models import Competition
|
from apps.competition.models import Competition
|
||||||
|
from apps.task.admin import CompetitionTaskInline
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Competition)
|
@admin.register(Competition)
|
||||||
@@ -8,3 +9,4 @@ class CompetitionAdmin(admin.ModelAdmin):
|
|||||||
list_display = ("title", "end_date", "type",)
|
list_display = ("title", "end_date", "type",)
|
||||||
search_fields = ("title", "description",)
|
search_fields = ("title", "description",)
|
||||||
list_filter = ("type", "participation_type",)
|
list_filter = ("type", "participation_type",)
|
||||||
|
inlines = [CompetitionTaskInline]
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-01 12:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('competition', '0001_initial'),
|
||||||
|
('task', '0001_initial'),
|
||||||
|
('user', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='competition',
|
||||||
|
name='tasks',
|
||||||
|
field=models.ManyToManyField(blank=True, related_name='tasks', to='task.competitiontask'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='competition',
|
||||||
|
name='participants',
|
||||||
|
field=models.ManyToManyField(blank=True, editable=False, related_name='participants', to='user.user'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='competition',
|
||||||
|
name='participation_type',
|
||||||
|
field=models.CharField(choices=[('edu', 'Образовательный'), ('competitive', 'Соревновательный')], max_length=11, verbose_name='Тип соревнования'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='competition',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(choices=[('solo', 'Индивидуальный')], max_length=10, verbose_name='Тип участия'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -4,3 +4,4 @@ from django.apps import AppConfig
|
|||||||
class CompetitionsConfig(AppConfig):
|
class CompetitionsConfig(AppConfig):
|
||||||
name = "apps.task"
|
name = "apps.task"
|
||||||
label = "task"
|
label = "task"
|
||||||
|
verbose_name = "Задания"
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-03-01 12:21
|
||||||
|
|
||||||
|
import apps.task.models
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('competition', '0002_competition_tasks_alter_competition_participants_and_more'),
|
||||||
|
('task', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='competitiontask',
|
||||||
|
options={'verbose_name': 'задание', 'verbose_name_plural': 'задания'},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='competitiontask',
|
||||||
|
name='competition',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='competition.competition', verbose_name='соревнование'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='competitiontask',
|
||||||
|
name='correct_answer_file',
|
||||||
|
field=models.FileField(blank=True, null=True, upload_to=apps.task.models.CompetitionTask.answer_file_upload_to, verbose_name='правильный ответ'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='competitiontask',
|
||||||
|
name='criteries',
|
||||||
|
field=models.JSONField(blank=True, null=True, verbose_name='критерии проверки'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='competitiontask',
|
||||||
|
name='points',
|
||||||
|
field=models.IntegerField(blank=True, null=True, verbose_name='баллы за задание'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='competitiontask',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(choices=[('input', 'Input'), ('checker', 'Checker'), ('review', 'Review')], max_length=8, verbose_name='тип задания'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -10,33 +10,49 @@ from apps.user.models import User
|
|||||||
|
|
||||||
class CompetitionTask(BaseModel):
|
class CompetitionTask(BaseModel):
|
||||||
class CompetitionTaskType(models.TextChoices):
|
class CompetitionTaskType(models.TextChoices):
|
||||||
INPUT = "input"
|
INPUT = "input", "Ввод правильного ответа"
|
||||||
CHECKER = "checker"
|
CHECKER = "checker", "Вывод кода"
|
||||||
REVIEW = "review"
|
REVIEW = "review", "Ручная"
|
||||||
|
|
||||||
def answer_file_upload_to(instance, filename) -> str:
|
def answer_file_upload_to(instance, filename) -> str:
|
||||||
return f"/tasks/{instance.id}/answer/{uuid4()}/filename"
|
return f"/tasks/{instance.id}/answer/{uuid4()}/filename"
|
||||||
|
|
||||||
competition = models.ForeignKey(Competition, on_delete=models.CASCADE)
|
competition = models.ForeignKey(Competition, on_delete=models.CASCADE)
|
||||||
title = models.TextField(verbose_name="заголовок", max_length=50)
|
title = models.CharField(verbose_name="заголовок", max_length=50)
|
||||||
description = models.TextField(verbose_name="описание", max_length=300)
|
description = models.TextField(verbose_name="описание", max_length=300)
|
||||||
type = models.CharField(choices=CompetitionTaskType, max_length=8)
|
type = models.CharField(choices=CompetitionTaskType, max_length=8,
|
||||||
|
verbose_name="тип проверки")
|
||||||
|
|
||||||
# only when "input" or "checker" type
|
# only when "input" or "checker" type
|
||||||
correct_answer_file = models.FileField(
|
correct_answer_file = models.FileField(
|
||||||
upload_to=answer_file_upload_to, null=True, blank=True
|
upload_to=answer_file_upload_to, null=True, blank=True,
|
||||||
|
verbose_name="файл с правильным ответом"
|
||||||
)
|
)
|
||||||
points = models.IntegerField(null=True, blank=True)
|
points = models.IntegerField(null=True, blank=True,
|
||||||
|
verbose_name="баллы за задание")
|
||||||
|
|
||||||
# only when "checker" type
|
# only when "checker" type
|
||||||
answer_file_path = models.TextField(null=True, blank=True)
|
answer_file_path = models.TextField(null=True, blank=True,
|
||||||
|
verbose_name="куда сохранять решения",
|
||||||
|
default="stdout")
|
||||||
|
|
||||||
# only when "review" type
|
# only when "review" type
|
||||||
criteries = models.JSONField(blank=True, null=True)
|
# todo make it more humanize
|
||||||
|
criteries = models.JSONField(blank=True, null=True,
|
||||||
|
verbose_name="критерии",
|
||||||
|
default=lambda: [{"name": "CHANGE ME", "slug": "CHANGE ME", "max_value": 0, "min_value": 0}]
|
||||||
|
)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
ContestTaskCriteriesValidator()(self)
|
ContestTaskCriteriesValidator()(self)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.title
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = "задание"
|
||||||
|
verbose_name_plural = "задания"
|
||||||
|
|
||||||
|
|
||||||
class CompetetionTaskSumbission(BaseModel):
|
class CompetetionTaskSumbission(BaseModel):
|
||||||
class StatusChoices(models.TextChoices):
|
class StatusChoices(models.TextChoices):
|
||||||
|
|||||||
Reference in New Issue
Block a user