Django: когда настраивать сохранение по сравнению с использованием сигнала после сохранения

#python #django #save #receiver

#python #django #Сохранить #приемник

Вопрос:

У меня есть серия тестов и обращений в базе данных. Всякий раз, когда тест устарел, он получает дату окончания, и любые поднаборы этого теста также должны быть датированы концом. Я вижу два способа добиться этого:

1) Измените функцию сохранения на вложенные случаи даты окончания.
2) Создайте приемник, который прослушивает сохраняемые тестовые модели, а затем завершает датировку их вложенных случаев.

Есть ли причина использовать одно, отличное от другого?

Редактировать: я вижу, что в этом сообщении в блоге предлагается использовать метод сохранения всякий раз, когда вы проверяете заданные значения модели. Поскольку я проверяю end_date, возможно, это наводит на мысль, что мне следует использовать пользовательское сохранение?

Edit2: Также, для записи, полная иерархия — это Протокол -> Тест -> Случай -> Планируемое выполнение, и всякий раз, когда один из них имеет end_date, каждый дочерний элемент также должен иметь EndDate . Я полагаю, что в конечном итоге я буду делать в основном одно и то же для каждого.

Edit3: оказывается, чтобы определить, является ли текущее сохранение () тем, которое завершает тест, мне нужно иметь доступ к старым и новым данным, поэтому я использовал пользовательское сохранение. Вот как это выглядит:

 def save(self):
    """Use a custom save to end date any subCases"""
    try:
        orig = Test.objects.get(id=self.id)
        enddated = (not orig.end_date) and self.end_date is not None   
    except:
        enddated = False

    super(Test, self).save()

    if enddated:
        for case in self.case_set.exclude(end_date__isnull=False):
            case.end_date = self.end_date
            case.enddater = self.enddater
            case.save()
  

Комментарии:

1. Я бы просто добавил, что вам, вероятно, следует принять * args и ** kwargs в save и передать их super на случай, если кто-то захочет использовать параметры типа update_save или force_insert.

Ответ №1:

Обычно я использую это эмпирическое правило:

  • Если вам нужно изменить данные, чтобы сохранение не завершилось ошибкой, переопределите save() (на самом деле у вас нет другого варианта). Например, в приложении, над которым я работаю, у меня есть модель с текстовым полем, содержащим список вариантов. Это взаимодействует со старым кодом и заменяет более старую модель, в которой было аналогичное текстовое поле, но с другим списком вариантов. Старый код иногда передает моей модели выбор из более старой модели, но между вариантами есть сопоставление 1: 1, поэтому в таком случае я могу изменить выбор на новый. Имеет смысл сделать это в save() .
  • В противном случае, если сохранение может продолжаться без вмешательства, я обычно использую сигнал после сохранения.

Комментарии:

1. Или, если быть более конкретным, используйте сохранение, когда вам нужно манипулировать самим объектом. Это означает, что методы вашего объекта имеют меньше «побочных эффектов» в других местах вашего кода, что значительно упрощает обслуживание.

Ответ №2:

В моем понимании сигналы — это средство для разделения модулей. Поскольку ваша задача, похоже, выполняется только в одном модуле, я бы настроил сохранение.