Skip to content

Commit 34a1c34

Browse files
committed
Созданы модели вопросов и ответов
1 parent dc449cc commit 34a1c34

2 files changed

Lines changed: 632 additions & 0 deletions

File tree

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Generated by Django 4.2.11 on 2026-02-20 08:41
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
import django.utils.timezone
7+
8+
9+
class Migration(migrations.Migration):
10+
11+
dependencies = [
12+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
13+
('files', '0007_auto_20230929_1727'),
14+
('courses', '0004_courselesson_and_more'),
15+
]
16+
17+
operations = [
18+
migrations.CreateModel(
19+
name='CourseTask',
20+
fields=[
21+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22+
('title', models.CharField(max_length=255, verbose_name='Название задания')),
23+
('body_text', models.TextField(blank=True, default='', verbose_name='Текст')),
24+
('status', models.CharField(choices=[('draft', 'Черновик'), ('published', 'Опубликован')], default='draft', max_length=16, verbose_name='Статус задания')),
25+
('task_kind', models.CharField(choices=[('informational', 'Информационное'), ('question', 'Вопрос/ответ')], max_length=16, verbose_name='Тип задания')),
26+
('check_type', models.CharField(blank=True, choices=[('without_review', 'Без проверки'), ('with_review', 'С проверкой')], max_length=16, null=True, verbose_name='Тип проверки')),
27+
('informational_type', models.CharField(blank=True, choices=[('video_text', 'Видео и текст'), ('text', 'Текст'), ('text_image', 'Текст и изображение')], max_length=24, null=True, verbose_name='Тип информационного задания')),
28+
('question_type', models.CharField(blank=True, choices=[('image_text', 'Изображение и текст'), ('video', 'Видео'), ('image', 'Изображение'), ('text_file', 'Текст с файлом'), ('text', 'Текст')], max_length=24, null=True, verbose_name='Тип вопроса')),
29+
('answer_type', models.CharField(blank=True, choices=[('text', 'Текст'), ('text_and_files', 'Текст и загрузка файла'), ('files', 'Загрузка файла'), ('multiple_choice', 'Выбор одного или нескольких вариантов ответа'), ('single_choice', 'Выбор одного варианта ответа')], max_length=24, null=True, verbose_name='Тип ответа')),
30+
('video_url', models.URLField(blank=True, null=True, verbose_name='Ссылка на видео')),
31+
('order', models.PositiveIntegerField(default=1, verbose_name='Порядковый номер')),
32+
('datetime_created', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
33+
('datetime_updated', models.DateTimeField(auto_now=True, verbose_name='Дата обновления')),
34+
('attachment_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='course_task_attachments', to='files.userfile', verbose_name='Файл')),
35+
('image_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='course_task_images', to='files.userfile', verbose_name='Изображение')),
36+
('lesson', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tasks', to='courses.courselesson', verbose_name='Урок курса')),
37+
],
38+
options={
39+
'verbose_name': 'Задание курса',
40+
'verbose_name_plural': 'Задания курса',
41+
'ordering': ('lesson_id', 'order', 'id'),
42+
},
43+
),
44+
migrations.CreateModel(
45+
name='CourseTaskOption',
46+
fields=[
47+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
48+
('text', models.CharField(max_length=500, verbose_name='Текст варианта')),
49+
('is_correct', models.BooleanField(default=False, verbose_name='Правильный вариант')),
50+
('order', models.PositiveIntegerField(default=1, verbose_name='Порядковый номер')),
51+
('datetime_created', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
52+
('datetime_updated', models.DateTimeField(auto_now=True, verbose_name='Дата обновления')),
53+
('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='options', to='courses.coursetask', verbose_name='Задание')),
54+
],
55+
options={
56+
'verbose_name': 'Вариант ответа задания',
57+
'verbose_name_plural': 'Варианты ответов задания',
58+
'ordering': ('task_id', 'order', 'id'),
59+
},
60+
),
61+
migrations.CreateModel(
62+
name='UserTaskAnswer',
63+
fields=[
64+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
65+
('status', models.CharField(choices=[('submitted', 'Отправлено'), ('pending_review', 'Ожидает проверки'), ('accepted', 'Принято'), ('rejected', 'Отклонено')], default='submitted', max_length=20, verbose_name='Статус ответа')),
66+
('answer_text', models.CharField(blank=True, default='', max_length=1000, verbose_name='Текст ответа')),
67+
('is_correct', models.BooleanField(blank=True, null=True, verbose_name='Ответ корректен')),
68+
('submitted_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Дата и время отправки')),
69+
('review_comment', models.TextField(blank=True, default='', verbose_name='Комментарий проверяющего')),
70+
('reviewed_at', models.DateTimeField(blank=True, null=True, verbose_name='Дата и время проверки')),
71+
('datetime_created', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
72+
('datetime_updated', models.DateTimeField(auto_now=True, verbose_name='Дата обновления')),
73+
('reviewed_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='reviewed_course_task_answers', to=settings.AUTH_USER_MODEL, verbose_name='Проверил')),
74+
('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_answers', to='courses.coursetask', verbose_name='Задание')),
75+
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_task_answers', to=settings.AUTH_USER_MODEL, verbose_name='Пользователь')),
76+
],
77+
options={
78+
'verbose_name': 'Ответ пользователя на задание',
79+
'verbose_name_plural': 'Ответы пользователей на задания',
80+
'ordering': ('-submitted_at', 'id'),
81+
},
82+
),
83+
migrations.CreateModel(
84+
name='UserTaskAnswerOption',
85+
fields=[
86+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
87+
('answer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='selected_options', to='courses.usertaskanswer', verbose_name='Ответ пользователя')),
88+
('option', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='selected_in_answers', to='courses.coursetaskoption', verbose_name='Выбранный вариант')),
89+
],
90+
options={
91+
'verbose_name': 'Выбранный вариант ответа',
92+
'verbose_name_plural': 'Выбранные варианты ответа',
93+
},
94+
),
95+
migrations.CreateModel(
96+
name='UserTaskAnswerFile',
97+
fields=[
98+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
99+
('file_name', models.TextField(blank=True, default='', verbose_name='Название файла')),
100+
('file_size', models.PositiveBigIntegerField(default=0, verbose_name='Размер файла')),
101+
('datetime_uploaded', models.DateTimeField(auto_now_add=True, verbose_name='Дата загрузки')),
102+
('answer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='courses.usertaskanswer', verbose_name='Ответ пользователя')),
103+
('file', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_task_answer_files', to='files.userfile', verbose_name='Файл')),
104+
],
105+
options={
106+
'verbose_name': 'Файл ответа пользователя',
107+
'verbose_name_plural': 'Файлы ответов пользователей',
108+
'ordering': ('-datetime_uploaded', 'id'),
109+
},
110+
),
111+
migrations.AddConstraint(
112+
model_name='usertaskansweroption',
113+
constraint=models.UniqueConstraint(fields=('answer', 'option'), name='courses_user_task_answer_option_unique_answer_option'),
114+
),
115+
migrations.AddConstraint(
116+
model_name='usertaskanswerfile',
117+
constraint=models.UniqueConstraint(fields=('answer', 'file'), name='courses_user_task_answer_file_unique_answer_file'),
118+
),
119+
migrations.AddConstraint(
120+
model_name='usertaskanswer',
121+
constraint=models.UniqueConstraint(fields=('user', 'task'), name='courses_user_task_answer_unique_user_task'),
122+
),
123+
migrations.AddConstraint(
124+
model_name='coursetaskoption',
125+
constraint=models.UniqueConstraint(fields=('task', 'order'), name='courses_task_option_unique_task_order'),
126+
),
127+
migrations.AddConstraint(
128+
model_name='coursetaskoption',
129+
constraint=models.CheckConstraint(check=models.Q(('order__gte', 1)), name='courses_task_option_order_gte_1'),
130+
),
131+
migrations.AddConstraint(
132+
model_name='coursetask',
133+
constraint=models.UniqueConstraint(fields=('lesson', 'order'), name='courses_task_unique_lesson_order'),
134+
),
135+
migrations.AddConstraint(
136+
model_name='coursetask',
137+
constraint=models.CheckConstraint(check=models.Q(('order__gte', 1)), name='courses_task_order_gte_1'),
138+
),
139+
migrations.AddConstraint(
140+
model_name='coursetask',
141+
constraint=models.CheckConstraint(check=models.Q(models.Q(('task_kind', 'informational'), _negated=True), ('informational_type__isnull', False), _connector='OR'), name='courses_task_info_requires_info_type'),
142+
),
143+
migrations.AddConstraint(
144+
model_name='coursetask',
145+
constraint=models.CheckConstraint(check=models.Q(models.Q(('task_kind', 'question'), _negated=True), models.Q(('question_type__isnull', False), ('answer_type__isnull', False), ('check_type__isnull', False)), _connector='OR'), name='courses_task_question_requires_types'),
146+
),
147+
migrations.AddConstraint(
148+
model_name='coursetask',
149+
constraint=models.CheckConstraint(check=models.Q(models.Q(('task_kind', 'informational'), _negated=True), models.Q(('question_type__isnull', True), ('answer_type__isnull', True), ('check_type__isnull', True)), _connector='OR'), name='courses_task_info_forbids_question_fields'),
150+
),
151+
migrations.AddConstraint(
152+
model_name='coursetask',
153+
constraint=models.CheckConstraint(check=models.Q(models.Q(('task_kind', 'question'), _negated=True), ('informational_type__isnull', True), _connector='OR'), name='courses_task_question_forbids_info_type'),
154+
),
155+
]

0 commit comments

Comments
 (0)