#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 в соответствии с логикой, которую вы изначально упомянули.