Как обновить DateTimeField ТОЛЬКО ТОГДА, когда логическое поле проверяется с False на True?

#django #if-statement #django-models #django-forms #django-views

#django #if-оператор #django-модели #django-forms #django-просмотры

Вопрос:

 # models.py
class Appointment(models.Model):
    # not including some model fields and instead focusing on the model fields that are of concern
    records_sent = models.BooleanField(default=False)
    record_sent_date = models.DateTimeField(blank=True, null=True)
    records_received = models.BooleanField(default=False)
    record_received_date = models.DateTimeField(blank=True, null=True)


# views.py
class AppointmentUpdateView(UpdateView):
    model = Appointment
    fields = ['records_sent', 'records_received']

    def form_valid(self, form):
        """ Update sent/received datetimes to current time
        when sent/received is checked from false to true.
        """
        appointment = self.object
        if form.instance.records_sent:
            appointment.records_sent_date = timezone.now()
        if form.instance.records_received:
            appointment.records_received_date = timezone.now()
        return super().form_valid(form)
  

Моя главная проблема связана с моей логикой if-statement в методе form_valid моего представления в классе.
В настоящее время, если мои логические поля проверяются на True с помощью POST-запроса, часовой пояс обновляется до now (), что нормально. Но, допустим, я установил records_sent = True в 14:00. Если я установлю records_received= True в 16:00, records_sent ТАКЖЕ обновит свое время до 16:00, потому что POST-запрос отправил records_sent И records_received = True в форме, впоследствии снова запуская if-оператор, когда он должен применяться только к records_received.

Как я могу сделать так, чтобы datetime.now () запускался ТОЛЬКО тогда, когда booleanfield установлено с False на True, вместо того, чтобы оно также запускалось с True на True?

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

1. Если вы не хотите обновлять records_sent при обновлении records_received , тогда отправьте records_sent как False .

Ответ №1:

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

 @receiver(pre_save, sender=Appointment)
def update_dates(sender, instance, **kwargs):
    if instance.pk:  # if instance is already exist
        now = timezone.now()
        obj = sender._default_manager.get(pk=instance.pk)
        if instance.records_sent and not obj.records_sent:
            instance.records_sent_date = now
        if instance.records_received and not obj.records_received:
            instance.records_received_date = now
  

Этот способ гарантирует, что даты будут обновлены в любое время, когда логические значения будут изменены на True, даже если вы изменили значения через панель администратора, или оболочку, или другим способом.

Ответ №2:

Один из способов — сохранить ваш статус перед изменением атрибутов класса вашей модели, и __init__ вам могут помочь следующие коды:

 class Appointment(models.Model):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.b_records_sent = self.records_sent
        self.b_records_received = self.records_received

    records_sent = models.BooleanField(default=False)
    record_sent_date = models.DateTimeField(blank=True, null=True)
    records_received = models.BooleanField(default=False)
    record_received_date = models.DateTimeField(blank=True, null=True)
  

и затем вы должны добавить некоторые дополнительные условия к form_valid методу вашей формы, чтобы что-то вроде:

 class AppointmentUpdateView(UpdateView):
    model = Appointment
    fields = ['records_sent', 'records_received']

    def form_valid(self, form):
        """ Update sent/received datetimes to current time
        when sent/received is checked from false to true.
        """
        appointment = self.object
        if form.instance.records_sent and appointment.b_records_sent != form.instance.records_sent:
            appointment.records_sent_date = timezone.now()
        if form.instance.records_received and appointment.b_records_received != form.instance.records_received:
            appointment.records_received_date = timezone.now()
        return super().form_valid(form)
  

Таким образом, поля даты и времени сохраняются в таблице, только если ваши логические поля изменяются, но если вы хотите сохранить время только один раз (т. Е. Всякий раз, когда его статус меняется на True), вы можете сделать что-то вроде следующего:

 class AppointmentUpdateView(UpdateView):
    model = Appointment
    fields = ['records_sent', 'records_received']

    def form_valid(self, form):
        """ Update sent/received datetimes to current time
        when sent/received is checked from false to true.
        """
        appointment = self.object
        if form.instance.records_sent and appointment.record_sent_date is None:
            appointment.records_sent_date = timezone.now()
        if form.instance.records_received and appointment.record_received_date is None:
            appointment.records_received_date = timezone.now()
        return super().form_valid(form)
  

Ответ №3:

Сравните поле формы с полем экземпляра модели, чтобы определить, не было ли это поле уже установлено.

 if not appointment.records_sent and form.instance.records_sent:
    appointment.records_sent_date = timezone.now()
if not appointment.records_received and form.instance.records_received:
    appointment.records_received_date = timezone.now()
return super().form_valid(form)
  

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

1. Я пробовал это раньше, и, к сожалению, когда я добавляю логику и not , поля datetimefields не будут обновляться, если я проверю с False на True, потому что назначение уже установлено в True в form_valid(). Тем не менее, спасибо за предложение!

2. appointment self.object который является объектом, подлежащим обновлению, и не должен был быть установлен в True до super().form_valid(form) выполнения.

3. Я предпочитаю другой ответ с использованием сигналов, поскольку это логика модели.

4. Я тоже так думал, пока не выполнил тест print () на объекте до и после настройки логики if-statement. в функции form_valid. Когда я проверил с False на True, оба вывода до и после if-операторов возвращали True, таким образом, не обновляя datetime в соответствии с логикой, которую вы изначально упомянули.