|
| 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