Задать вопрос
@DenisShahbazyan

Почему при создании объекта поля содержащие время заполняются по разному?

У меня есть модель постов:

class Post(models.Model):
    """Модель 'Посты'."""
    text = CKEditor5Field(
        verbose_name='текст поста',
        help_text='Введите текст поста',
        config_name='extends',
    )
    pub_date = models.DateTimeField(
        verbose_name='дата публикации',
        auto_now_add=True,
    )
    edit_date = models.DateTimeField(
        verbose_name='дата редактирования',
        auto_now=True,
    )
    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        verbose_name='автор',
        related_name='posts',
    )
    tags = models.ManyToManyField(
        Tag,
        verbose_name='теги',
        related_name='posts',
        blank=True,
    )

    class Meta:
        ordering = ['-pub_date']
        verbose_name = 'пост'
        verbose_name_plural = 'посты'

    def __str__(self):
        return str(self.pk)


На dev сервере (python manage.py runserver) если я добавляю новый пост, то поля pub_date и edit_date равны.
Загрузил проект в докер контейнере на сервер, а там при добавлении поста поля pub_date и edit_date отличаются миллисекундами. Как я понял, потому сохранение происходит не сразу а поэтапно каждое поле и между сохранением каждого поля успевает пройти некоторое время.

6515e4a7df57b706143208.png

Для меня это критично, так как в шаблоне я проверяю и вывожу информацию о посте: пост был создан или изменен.

<div class="d-flex justify-content-end">
      {% if post.pub_date == post.edit_date %}
        Создано: {{ post.pub_date|date:"d E Y H:m:s" }}
      {% else %}
        Изменено: {{ post.edit_date|date:"d E Y H:m:s" }}
      {% endif %}
    </div>


1. Была версия снести все миграции и БД и в модели edit_date поднять выше pub_date и тогда возможно в шаблоне можно будет проверять edit_date <= pub_date.
2. Возможно в шаблонах и без изменений можно как-то проверять не учитывая доли секунд. (Но тогда время может попасть на границу секунд и тогда уже будут секунды тоже отличаться).
3. Добавил в модель:
def save(self, *args, **kwargs):
        now = timezone.now()
        if not self.pk:
            self.pub_date = now
        self.edit_date = now
        super(Post, self).save(*args, **kwargs)

Т.е. при первом сохранении (при создании) время будет устанавливаться в оба поля из одной и той же переменной и тогда время точно будет одинаковым. А при редактировании будет изменять только edit_date.

Есть ли у меня правильный вариант, и вообще как это исправить?
Контейнер с БД PostgreSQL 16
Контейнер с веб сервером Nginx
Контейнер с приложением Django
Контейнер с вебмордой для БД PGAdmin.
  • Вопрос задан
  • 69 просмотров
Подписаться 1 Простой 1 комментарий
Решения вопроса 1
trapwalker
@trapwalker
Программист, энтузиаст
Сделайте у модели вычисляемое свойство, которое будет сравнивать время с некоторой точностью. То есть таймдельта сравниваете с половиной секунды и все. При этом и в шаблонах у вас будет читабельно и лаконично, и в коде видно как вы определяете отредактирован ли пост.
Ещё вы можете сделать дополнительное целочисленное поле с номером правки. По умолчанию оно будет ноль, а при каждой правке вы его будете инкрементировать. Тогда будет видно однозначно и без вот этих вот сравнений дат.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@DenisShahbazyan Автор вопроса
Метод save не сработал, решил проблему так:
<div class="d-flex justify-content-end">
      {% if post.pub_date|date:"Y-m-d H:i:s" == post.edit_date|date:"Y-m-d H:i:s" %}
        Создано: {{ post.pub_date|date:"d E Y H:m:s" }}
      {% else %}
        Изменено: {{ post.edit_date|date:"d E Y H:m:s" }}
      {% endif %}
    </div>

Обычно бывает такая разница:
pub_date = 2023-09-28 22:20:20.303671+00
edit_date = 2023-09-28 22:20:20.303689+00
Конечно если миллисекунды попадут на границу секунд, то мое решение не спасет...
pub_date = 2023-09-28 22:20:20.999991+00
edit_date = 2023-09-28 22:20:21.000009+00
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы