Skip to content

Commit c7b510e

Browse files
committed
Длина поля ответа увеличена до 150 символов; Организована сортировка предлагаемых ответов по ID при обращении к ручке single-correct
1 parent 71350dc commit c7b510e

3 files changed

Lines changed: 114 additions & 41 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.0.3 on 2025-06-30 10:18
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("questions", "0014_alter_questionconnect_attempts_after_hint_and_more"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="answersingle",
15+
name="text",
16+
field=models.CharField(max_length=150),
17+
),
18+
]

apps/questions/models/answers.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33

44
from files.models import FileModel
55
from progress.models import UserProfile
6-
from questions.models.questions import (QuestionConnect, QuestionSingleAnswer,
7-
QuestionWrite)
6+
from questions.models.questions import (
7+
QuestionConnect,
8+
QuestionSingleAnswer,
9+
QuestionWrite,
10+
)
811

912

1013
class AnswerSingle(models.Model):
11-
text = models.CharField(max_length=100, null=False)
14+
# Task изменить максимальную длину строки до 200 символов
15+
text = models.CharField(max_length=150, null=False)
1216
is_correct = models.BooleanField(default=False)
1317
question = models.ForeignKey(
1418
QuestionSingleAnswer,
@@ -22,8 +26,12 @@ class Meta:
2226

2327

2428
class AnswerConnect(models.Model):
25-
connect_left = models.TextField(max_length=450, null=True, blank=True, verbose_name="Вопрос (текст)")
26-
connect_right = models.TextField(max_length=450, null=True, blank=True, verbose_name="Ответ (текст)")
29+
connect_left = models.TextField(
30+
max_length=450, null=True, blank=True, verbose_name="Вопрос (текст)"
31+
)
32+
connect_right = models.TextField(
33+
max_length=450, null=True, blank=True, verbose_name="Ответ (текст)"
34+
)
2735
file_left = models.ForeignKey(
2836
FileModel,
2937
on_delete=models.PROTECT,
@@ -53,11 +61,17 @@ class Meta:
5361
def clean(self):
5462
"""Проверка на заполненность полей."""
5563
if not (self.connect_left or self.file_left):
56-
raise ValidationError("Необходимо заполнить хотя бы одно из полей 'Вопрос'.")
64+
raise ValidationError(
65+
"Необходимо заполнить хотя бы одно из полей 'Вопрос'."
66+
)
5767
if not (self.connect_right or self.file_right):
5868
raise ValidationError("Необходимо заполнить хотя бы одно из полей 'Ответ'.")
59-
if (self.connect_left and self.file_left) or (self.connect_right and self.file_right):
60-
raise ValidationError("Заполните только одно из полей 'Вопрос' или 'Ответ'.")
69+
if (self.connect_left and self.file_left) or (
70+
self.connect_right and self.file_right
71+
):
72+
raise ValidationError(
73+
"Заполните только одно из полей 'Вопрос' или 'Ответ'."
74+
)
6175

6276
def save(self, *args, **kwargs):
6377
self.full_clean()

apps/questions/views/questions_views.py

Lines changed: 74 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,36 @@
33

44
from django.db.models import QuerySet
55
from drf_spectacular.utils import extend_schema
6+
from progress.models import TaskObjUserResult
67
from rest_framework import generics, status
78
from rest_framework.permissions import IsAuthenticated
89
from rest_framework.response import Response
10+
from subscription.permissions import SubscriptionTaskObjectPermission
911

10-
from progress.models import TaskObjUserResult
1112
from questions.mapping import TypeQuestionPoints
12-
from questions.models import (AnswerConnect, InfoSlide, QuestionConnect,
13-
QuestionSingleAnswer, QuestionWrite)
13+
from questions.models import (
14+
AnswerConnect,
15+
InfoSlide,
16+
QuestionConnect,
17+
QuestionSingleAnswer,
18+
QuestionWrite,
19+
)
1420
from questions.permissions import CheckQuestionTypePermission
15-
from questions.serializers import (ConnectQuestionSerializer,
16-
InfoSlideSerializer,
17-
SingleQuestionAnswerSerializer,
18-
WriteQuestionSerializer)
21+
from questions.serializers import (
22+
ConnectQuestionSerializer,
23+
InfoSlideSerializer,
24+
SingleQuestionAnswerSerializer,
25+
WriteQuestionSerializer,
26+
)
1927
from questions.services.helpers import add_popup_data
20-
from questions.typing import (AnswerUserWriteData, QuestionSerializerData,
21-
QuestionWriteSerializerData,
22-
QuestionСonnectSerializerData, SingleAnswerData,
23-
SingleConnectedAnswerData)
24-
from subscription.permissions import SubscriptionTaskObjectPermission
28+
from questions.typing import (
29+
AnswerUserWriteData,
30+
QuestionSerializerData,
31+
QuestionWriteSerializerData,
32+
QuestionСonnectSerializerData,
33+
SingleAnswerData,
34+
SingleConnectedAnswerData,
35+
)
2536

2637

2738
class QuestionSingleAnswerGet(generics.RetrieveAPIView):
@@ -37,22 +48,28 @@ class QuestionSingleAnswerGet(generics.RetrieveAPIView):
3748
summary="Выводит данные для трёх видов вопросов (см. описание)",
3849
tags=["Вопросы и инфо-слайд"],
3950
description="""для: вопроса с одним правильным ответом, вопроса на исключение,
40-
вопроса на выбор нескольких правильных
51+
вопроса на выбор нескольких правильных
4152
ответов (возможно пока его нет, но в будущем может появится).""",
4253
)
4354
def get(self, request, *args, **kwargs) -> Response:
4455
question: QuestionSingleAnswer = self.request_question
45-
all_answers = question.single_answers.all()
46-
answers = [SingleAnswerData(id=answer.id, text=answer.text) for answer in all_answers]
56+
all_answers = question.single_answers.order_by("id")
57+
58+
answers = [
59+
SingleAnswerData(id=answer.id, text=answer.text) for answer in all_answers
60+
]
4761

4862
user_result = TaskObjUserResult.objects.get_answered(
49-
self.task_object_id, self.profile_id, TypeQuestionPoints.QUESTION_SINGLE_ANSWER
63+
self.task_object_id,
64+
self.profile_id,
65+
TypeQuestionPoints.QUESTION_SINGLE_ANSWER,
5066
)
5167

52-
correct_answer = [
53-
SingleAnswerData(id=all_answers.get(is_correct=True).id, text=all_answers.get(is_correct=True).text)
54-
]
55-
random.shuffle(answers)
68+
try:
69+
correct = all_answers.get(is_correct=True)
70+
correct_answer = [SingleAnswerData(id=correct.id, text=correct.text)]
71+
except all_answers.model.DoesNotExist:
72+
correct_answer = []
5673

5774
serializer = self.serializer_class(
5875
QuestionSerializerData(
@@ -61,11 +78,14 @@ def get(self, request, *args, **kwargs) -> Response:
6178
description=question.description,
6279
files=[file.link for file in question.files.all()],
6380
answers=correct_answer if user_result else answers,
64-
is_answered=True if user_result else False,
81+
is_answered=bool(user_result),
6582
video_url=question.video_url,
6683
)
6784
)
68-
return Response(add_popup_data(serializer.data, self.request_task_object), status=status.HTTP_200_OK)
85+
return Response(
86+
add_popup_data(serializer.data, self.request_task_object),
87+
status=status.HTTP_200_OK,
88+
)
6989

7090

7191
class QuestionConnectGet(generics.RetrieveAPIView):
@@ -117,7 +137,10 @@ def get(self, request, *args, **kwargs):
117137
random.shuffle(target_left)
118138

119139
serializer = self.serializer_class(question_data)
120-
return Response(add_popup_data(serializer.data, self.request_task_object), status=status.HTTP_200_OK)
140+
return Response(
141+
add_popup_data(serializer.data, self.request_task_object),
142+
status=status.HTTP_200_OK,
143+
)
121144

122145

123146
class QuestionExcludeAnswerGet(generics.RetrieveAPIView):
@@ -140,9 +163,13 @@ def get(self, request, *args, **kwargs):
140163
question: QuestionSingleAnswer = self.request_question
141164

142165
all_answers = question.single_answers.all()
143-
answers = [SingleAnswerData(id=answer.id, text=answer.text) for answer in all_answers]
166+
answers = [
167+
SingleAnswerData(id=answer.id, text=answer.text) for answer in all_answers
168+
]
144169
answers_to_exclude = [
145-
SingleAnswerData(id=answer.id, text=answer.text) for answer in all_answers if answer.is_correct
170+
SingleAnswerData(id=answer.id, text=answer.text)
171+
for answer in all_answers
172+
if answer.is_correct
146173
]
147174

148175
data_to_serialize = QuestionSerializerData(
@@ -162,7 +189,10 @@ def get(self, request, *args, **kwargs):
162189
random.shuffle(answers)
163190

164191
serializer = self.serializer_class(data_to_serialize)
165-
return Response(add_popup_data(serializer.data, self.request_task_object), status=status.HTTP_200_OK)
192+
return Response(
193+
add_popup_data(serializer.data, self.request_task_object),
194+
status=status.HTTP_200_OK,
195+
)
166196

167197

168198
class InfoSlideDetails(generics.RetrieveAPIView):
@@ -188,16 +218,23 @@ def get(self, request, *args, **kwargs):
188218
"files": [file.link for file in info_slide.files.all()],
189219
"is_done": bool(
190220
TaskObjUserResult.objects.get_answered(
191-
self.task_object_id, self.profile_id, TypeQuestionPoints.INFO_SLIDE
221+
self.task_object_id,
222+
self.profile_id,
223+
TypeQuestionPoints.INFO_SLIDE,
192224
)
193225
),
194-
"video_url": info_slide.video_url
226+
"video_url": info_slide.video_url,
195227
}
196228
)
197229
if serializer.is_valid():
198-
return Response(add_popup_data(serializer.data, self.request_task_object), status=status.HTTP_200_OK)
230+
return Response(
231+
add_popup_data(serializer.data, self.request_task_object),
232+
status=status.HTTP_200_OK,
233+
)
199234
else:
200-
return Response({"error": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
235+
return Response(
236+
{"error": serializer.errors}, status=status.HTTP_400_BAD_REQUEST
237+
)
201238

202239

203240
class QuestionWriteAnswer(generics.RetrieveAPIView):
@@ -221,12 +258,16 @@ def get(self, request, *args, **kwargs):
221258
text=question.text,
222259
description=question.description,
223260
files=[file.link for file in question.files.all()],
224-
video_url=question.video_url
261+
video_url=question.video_url,
225262
)
226263

227264
if user_answer := TaskObjUserResult.objects.get_answered(
228265
self.task_object_id, self.profile_id, TypeQuestionPoints.QUESTION_WRITE
229266
):
230-
write_question.answer = AnswerUserWriteData(id=user_answer.id, text=user_answer.text)
267+
write_question.answer = AnswerUserWriteData(
268+
id=user_answer.id, text=user_answer.text
269+
)
231270
data = asdict(write_question)
232-
return Response(add_popup_data(data, self.request_task_object), status=status.HTTP_200_OK)
271+
return Response(
272+
add_popup_data(data, self.request_task_object), status=status.HTTP_200_OK
273+
)

0 commit comments

Comments
 (0)