Предисловие:
По учёбе занимаюсь небольшим проектом, к сожалению, практически в одиночку. Суть в том, что мне нужно написать веб-приложение, которое на выходе давало бы N-ое количество docx файлов (различные варианты теста + ответы к каждому из вариантов). На вход же, соответственно, подаётся информация о школьном предмете, по которому будут генерироваться варианты, и N - количество этих самых вариантов.
Варианты создаются следующим путём: в базе данных хранится множество вопросов (по разным предметам) и ответов к ним, из этого множества происходит выборка некоего количества заданий, а затем условия этих заданий и варианты ответов (если задание подразумевает варианты ответа) записываются в одни файл, а правильные ответы на эти задания записываются в другой файл - файл ответов.
Условие:
Само тело задания, как и варианты ответов на это задание (если эти варианты подразумеваются), могут состоять из обычного текста, latex формулы и картинки (что-то одно из этого обязательно должно присутствовать, остальное же может быть, а может и нет). В каждом предмете тест состоит из M количества заданий. На i место в тесте могут стать задания только с индексом i. Т.е. например, в тест по истории на пятое место станет один (случайно выбранный) из десятка вопросов, у которых индекс i равен именно 5. По этому индексу будут (всё это условно) хранится вопросы связанные с Петром Великим.
Мои попытки реализации:
Я решил, что в базе данных для начала будет таблица с предметами.
С полями: название предмета (именительный падеж), дательный падеж (для вывода информации на html страничку), количество заданий task_number в одном варианте по этому предмету. Т.е. индекс i будет принимать значения от 0 до task_number не включительно.
Затем будет таблица tasks, хранящая условие задания.
Здесь num - тот самый индекс задания, text - текстовое поле задания, latex - текстовое поля для хранения формулы в соответствующем формате, image - ссылка на изображение для задания, subject_fk_id - внешний ключ, отсылающий на id предмета, к которому относится данное задание.
И третья таблица: options.
Поля text, latex, image аналогичны вышеописанным, is_answer - булиновские значения (1 - верный ответ, 0 - нет), task_fk_id - внешний ключ на задание, к которому относятся ответы.
Мне (с моим небольшим опытом) показалось, что данная реализация неплохая, но появился ряд проблем (часть которых связана с данным вопросом) с админ-панелью django. Ведь пользователям данной системы нужно предоставить возможность добавлять/удалять/редактировать задания.
Код:
Данные ниже куски кода не используются в основной программе. Я их писал, чтобы разобраться, как создавать модели и как с ними взаимодействовать через админ-панель.
python код
models.py
from django.db import models
# Create your models here.
class Subjects(models.Model):
case_nominative = models.CharField(max_length=32, verbose_name='Название')
case_dative = models.CharField(max_length=32, verbose_name='Дательный падеж')
tasks_number = models.SmallIntegerField(default=0, verbose_name='Количество заданий в варианте')
def __str__(self):
return self.case_nominative
class Meta:
verbose_name = 'Предмет'
verbose_name_plural = 'Предметы'
ordering = ['id']
class Tasks(models.Model):
subject_fk = models.ForeignKey(Subjects, on_delete=models.CASCADE, verbose_name='Ключ предмета')
num = models.SmallIntegerField(verbose_name='Номер задания в тесте')
text = models.TextField(blank=True, verbose_name='Текст задания')
latex = models.TextField(blank=True, verbose_name='Формула (LaTeX)')
image = models.ImageField(upload_to='thumbnails_task/', blank=True,
verbose_name='Изображение')
def __str__(self):
return str(self.subject_fk) + ' [№' + str(self.num) + '] ' + self.text
class Meta:
verbose_name = 'Задание'
verbose_name_plural = 'Задания'
class Options(models.Model):
task_fk = models.ForeignKey(Tasks, on_delete=models.CASCADE, verbose_name='Ключ задания')
text = models.TextField(blank=True, verbose_name='Текст ответа')
latex = models.TextField(blank=True, verbose_name='Формула (LaTeX)')
image = models.ImageField(upload_to='thumbnails_option/', blank=True,
verbose_name='Изображение')
is_answer = models.BooleanField(default=False, verbose_name='Верный ответ?')
def __str__(self):
return str(self.task_fk) + ' | ' + self.text
class Meta:
verbose_name = 'Вариант ответа'
verbose_name_plural = 'Варианты ответов'
admin.py
Пока без фильтров.
from django.contrib import admin
from .models import *
# Register your models here.
class SubjectsAdmin(admin.ModelAdmin):
list_display = ('case_nominative', 'tasks_number')
list_display_links = ('case_nominative',)
class TasksAdmin(admin.ModelAdmin):
list_display = ('id', 'subject_fk', 'num', 'text', 'latex', 'image')
list_display_links = ('id', 'text', 'latex')
# search_fields = ('id', 'subject_fk', 'num', 'text', 'latex')
search_fields = ('id', 'num', 'text', 'latex')
ordering = ('subject_fk', 'num')
class OptionsAdmin(admin.ModelAdmin):
list_display = ('id', 'task_fk', 'text', 'latex', 'image', 'is_answer')
list_display_links = ('id', 'text')
search_fields = ('task_fk__id', 'text')
ordering = ('task_fk', 'id')
admin.site.register(Subjects, SubjectsAdmin)
admin.site.register(Tasks, TasksAdmin)
admin.site.register(Options, OptionsAdmin)
Проблема:
Страница добавления новых заданий (имеется ввиду условий) меня устраивает, только вот поле
num = models.SmallIntegerField(verbose_name='Номер задания в тесте')
не могу ограничить. Сейчас туда можно вписать любое число, а хотелось бы от 1 до task_number соответствующего предмета из таблицы subjects (ну или от 0 до task_number-1).
Страница добавления вариантов ответов (options) получается плохой.
Очевидно, что с данным раскрывающимся списком очень неудобно работать (тем более, когда заданий в базе станет много).
Отсюда и вопросы.
Вопросы:
Как ограничить поле num?
Как устранить вышеописанную проблему со страницей добавления вариантов ответа? Может, перепроектировать БД или как-то поработать с отображением? Можно ли в этот dropdown как-нибудь встроить фильтры?