#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:
В моем понимании сигналы — это средство для разделения модулей. Поскольку ваша задача, похоже, выполняется только в одном модуле, я бы настроил сохранение.