Обновление временных меток модели и связанного с ней родителя за одно и то же время - PullRequest
0 голосов
/ 07 июня 2018

Допустим, у меня есть следующие модели:

class Blog(TimeStampedModel):
    summary = models.TextField()
    text = models.TextField()

class BlogComment(TimeStampedModel):
    author = models.CharField()
    text = models.CharField()
    blog = models.ForeignKey(Blog, models.CASCADE, related_name='comments')

class BlogTag(TimeStampedModel):
    name = models.CharField()
    blog = models.ForeignKey(Blog, models.CASCADE, related_name='tags')

Все три наследуются от следующей модели, которая реализует некоторую обработку меток времени:

class TimeStampedModel(models.Model):
    last_changed = models.DateTimeField()
    created_at = models.DateTimeField(default=timezone.now)

    def save(self, *args, **kwargs):
        try:
            self._meta.get_field('blog')
        except models.FieldDoesNotExist:
            self.last_changed = timezone.now()
            super(TimeStampedModel, self).save(*args, **kwargs)
        else:
            now = timezone.now()
            self.blog.last_changed = now
            self.last_changed = now
            with transaction.atomic():
                super(TimeStampedModel, self).save(*args, **kwargs)
                self.blog.save()

    class Meta:
        abstract = True

Основная идея, лежащая в основе пользовательских save() означает, что когда обновляется, например, комментарий (экземпляр BlogComment), он должен обновить last_changed отметку времени как экземпляра комментария, так и соответствующей записи в блоге.

К сожалению, настройка отметки временине идеален, поскольку он переопределяет временную метку блога, когда вызывается его собственное сохранение, а время просто немного отличается:

In [1]: b = Blog.objects.get(id=1)

In [2]: comment0 = t.comments.all()[0]

In [3]: b.last_changed, comment0.last_changed
Out[3]:
(datetime.datetime(2018, 6, 7, 12, 54, 12, 516855, tzinfo=<UTC>),
 datetime.datetime(2018, 6, 7, 10, 22, 09, 201690, tzinfo=<UTC>))

In [4]: comment0.text
Out[4]: 'Some text'

In [5]: comment0.text = 'test'

In [6]: comment0.save()

In [7]: t = blog.objects.get(id=1)

In [8]: comment0 = t.comments.all()[0]

In [9]: t.last_changed, comment0.last_changed
Out[9]:
(datetime.datetime(2018, 6, 7, 13, 25, 58, 64131, tzinfo=<UTC>),
 datetime.datetime(2018, 6, 7, 13, 25, 58, 61960, tzinfo=<UTC>))

Другая проблема заключается в том, что функция сохранения опирается на внешний ключ с именем blogЭто кажется странным, поскольку добавление моделей, использующих разные имена внешних ключей, требует обновления функции сохранения.

Существует ли более общее решение этой проблемы обновления временных меток связанных моделей?Как изменить указанную выше функцию save(), чтобы последовательно обновлять модели с одинаковой отметкой времени?

1 Ответ

0 голосов
/ 07 июня 2018

Нашли решение, если в каждой модели использовалась одна и та же ссылка на внешний ключ:

def save(self, *args, **kwargs):
    self.last_changed = timezone.now()
    try:
        self._meta.get_field('blog')
    except models.FieldDoesNotExist:
        super(TimeStampedModel, self).save(*args, **kwargs)
    else:
        self.blog.last_changed = self.last_changed
        with transaction.atomic():
            super(TimeStampedModel, self).save(*args, **kwargs)
            super(TimeStampedModel, self.blog).save(*args, **kwargs)
...