Улучшение промежуточных таблиц Django

Я работаю над приложением Django, которое содержит следующую структуру:

Существуют Checklist, состоящие из одного или нескольких ChecklistItem. Мы хотим назначить на Job столько контрольных списков, сколько захотим, и заполнить эти вопросы Job-Checklist'а.

Примером может быть создание контрольного списка, содержащего ChecklistItems:

  • "Как дела?"
  • "Как вас зовут?". Таким образом, каждый ChecklistItem - это просто вопрос в контрольном списке.

Это означает, что теперь мы можем использовать этот Checklist, состоящий из двух ChecklistItem, в любой работе и заполнить его после назначения. Мы создаем задание №1 и назначаем ему этот контрольный список №1, создаем задание №2 и также назначаем ему контрольный список №1. На один и тот же контрольный список нужно ответить в двух разных заданиях. Тот, кто работает над конкретным заданием, будет заполнять контрольный список в соответствии с ним.

Сначала мы подходили к этому так: Job и Checklist соединялись промежуточной таблицей JobChecklist, а JobChecklistItemAnswer присваивались каждому отвеченному пункту контрольного списка (вопросу).

class Checklist(models.Model):
    """A class to represent a checklist."""

    name = models.CharField(_("name"), max_length=150)

class ChecklistItem(models.Model):
    """A class to represent an item of a checklist."""
    checklist = models.ForeignKey(Checklist, on_delete=models.CASCADE)
    question = models.CharField(_("question"), max_length=200)

    
class Job(models.Model):
    """A class to represent a job."""
    checklists = models.ManyToManyField(Checklist, through="JobChecklist")


class JobChecklist(models.Model):
    """A class to represent the intermediary relation of a checklist belonging
    to a job."""

    job = models.ForeignKey(Job, on_delete=models.CASCADE)
    checklist = models.ForeignKey(Checklist, on_delete=models.CASCADE)

class JobChecklistItemAnswer(models.Model):
    """A class to represent the relation of a checklist item's answer belonging
    to a job's checklist."""

    job_checklist = models.ForeignKey(JobChecklist, on_delete=models.CASCADE)
    checklist_item = models.ForeignKey(ChecklistItem, on_delete=models.CASCADE)
    answer = models.BooleanField(_("answer"), null=True)

    def save(self, *args, **kwargs) -> None:
        if (
            self.checklist_item
            not in self.job_checklist.checklist.checklistitem_set.all()
        ):
            raise FieldError(
                _(
                    "ChecklistItem #{} doesn't belong to {} checklist".format(
                        self.checklist_item.id, self.job_checklist.checklist
                    )
                )
            )
        return super().save(*args, **kwargs)

Как видно из отношения JobChecklistItemAnswer, мы должны были исправить метод сохранения, чтобы убедиться, что ответ принадлежит именно этому пункту контрольного списка (вопросу). Мы хотели бы решить эту проблему на уровне Django ORM. Проблема представляется мне распространенным паттерном проектирования, однако я не смог найти ни одного примера с такой структурой.

Вернуться на верх