Django form.instance.field отображает неверное значение даты в HTML-шаблоне, несмотря на наличие правильного значения под рукой
Я запускаю Django 4.1
, и представление, которое обслуживает шаблон, является FormView
-child.
Для начала, вот канонический ответ о том, какое значение является правильным, взятый непосредственно из базы данных:
In [6]: DCF.objects.last().appreciation_date
Out[6]: datetime.date(2023, 1, 24)
Первый вызов шаблона HTML для этого же поля:
<h5>Title: {{ form.instance.appreciation_date }}</h5>
И результат соответствует ожиданиям:
Около 30 строк кода ниже (ни одна из которых не делает ничего особенно функционального, это просто куча объявлений div
для CSS и стилизации), внутри <form>
, на модале:
<div class="mb-3">
<label for="{{ form.appreciation_date.id_for_label }}">Date</label>
<input class="form-control datepicker" placeholder="Please select date" type="text" onfocus="focused(this)" onfocusout="defocused(this)" name="{{ form.appreciation_date.name }}" value="{{ form.instance.appreciation_date }}">
</div>
А теперь приготовьтесь к результату - который также освещает вопрос, к которому я собираюсь перейти:
Что происходит с призраком Джанго в оболочке? Как 2023-01-24
превратилось в 2023-01-01
без видимой причины? Или, говоря иначе, почему и как один и тот же контекстный вызов может иметь два разных значения в одном и том же рендере одного и того же шаблона?
Я бы очень хотел, чтобы во втором вызове было показано правильное значение - имеется в виду значение, которое находится как в базе данных, так и, предположительно, в контексте (поскольку оно показывает правильное значение до открытия модала).
То, что не работает:
- Перезагрузка (F5)
- Принудительная перезагрузка (Shift+F5)
- Перезапуск сервера
- Принудительное обновление значения базы данных для этого поля на другую дату
Еще хуже то, что значение, по-видимому, является правильным, даже если это не так - или так говорит консоль разработчика. Дата отличается от 2023-01-24
, потому что этот снимок экрана был сделан после того, как я обновил дату вручную, как указано в списке того, что не сработало:
In [7]: DCF.objects.last().appreciation_date
Out[7]: datetime.date(2023, 1, 25)
Итак, в конце концов, что происходит, что заставляет ... что-то, будь то Django или что-то другое, отображать значение 2023-01-24
как 2023-01-01
в одном случае, но не в другом?
Я практически час писал этот вопрос, прежде чем наткнулся на то, что, как я почти сразу понял, приведет к решению в конце поста, поэтому, учитывая затраченные усилия, я опубликую и отвечу сам.
Похоже, что Django выбрал строковый формат, когда пришло время передать объект datetime
браузеру, и при попытке заполнить элемент date-picker
этим предопределенным значением, мы обнаруживаем, что браузер не понимает даты в формате MMM-DD-YYYY
.
Изменение проблемного вызова таким образом решило проблему:
value="{{ form.instance.appreciation_date|date:'Y-m-d'}}"
Объяснение того, почему это работает, окольным путем выглядит следующим образом:
Включение |date:'Y-m-d'
использует встроенный в Django фильтр date filter для форматирования объекта datetime
перед тем, как значения будут отображены в HTML-файл.