• en
  • Язык: ru

Запрос истории

Запрос истории по экземпляру модели

Объект HistoricalRecords на экземпляре модели может быть использован так же, как и менеджер модели:

>>> from polls.models import Poll, Choice
>>> from datetime import datetime
>>> poll = Poll.objects.create(question="what's up?", pub_date=datetime.now())
>>>
>>> poll.history.all()
[<HistoricalPoll: Poll object as of 2010-10-25 18:03:29.855689>]

При сохранении экземпляра модели создается новая историческая запись:

>>> poll.pub_date = datetime(2007, 4, 1, 0, 0)
>>> poll.save()
>>> poll.history.all()
[<HistoricalPoll: Poll object as of 2010-10-25 18:04:13.814128>, <HistoricalPoll: Poll object as of 2010-10-25 18:03:29.855689>]

Запрос истории по классу модели

Исторические записи для всех экземпляров модели можно запросить, используя менеджер HistoricalRecords для класса модели. Например, исторические записи для всех экземпляров Choice могут быть запрошены с помощью менеджера для класса модели Choice:

>>> choice1 = poll.choice_set.create(choice_text='Not Much', votes=0)
>>> choice2 = poll.choice_set.create(choice_text='The sky', votes=0)
>>>
>>> Choice.history
<simple_history.manager.HistoryManager object at 0x1cc4290>
>>> Choice.history.all()
[<HistoricalChoice: Choice object as of 2010-10-25 18:05:12.183340>, <HistoricalChoice: Choice object as of 2010-10-25 18:04:59.047351>]

Поскольку история является моделью, вы также можете фильтровать ее как обычные QuerySets, например, Choice.history.filter(choice_text='Not Much') будет работать!

Получение предыдущей и следующей исторической записи

Если у вас есть историческая запись для экземпляра и вы хотите получить предыдущую историческую запись (более старую) или следующую историческую запись (более новую), можно использовать атрибуты prev_record и next_record, предназначенные только для чтения, соответственно.

>>> from polls.models import Poll, Choice
>>> from datetime import datetime
>>> poll = Poll.objects.create(question="what's up?", pub_date=datetime.now())
>>>
>>> record = poll.history.first()
>>> record.prev_record
None
>>> record.next_record
None
>>> poll.question = "what is up?"
>>> poll.save()
>>> record.next_record
<HistoricalPoll: Poll object as of 2010-10-25 18:04:13.814128>

Если историческая запись является первой записью, prev_record будет None. Аналогично, если это последняя запись, next_record будет None.

Изменение модели

SimpleHistoryAdmin позволяет пользователям вернуться к старой версии модели через интерфейс администратора. Вы также можете сделать это программно. Для этого можно взять любой исторический объект и сохранить связанный с ним экземпляр. Например, если мы хотим получить доступ к самому раннему HistoricalPoll, для экземпляра Poll, мы можем сделать следующее:

>>> poll.history.earliest()
<HistoricalPoll: Poll object as of 2010-10-25 18:04:13.814128>

И чтобы вернуться к этому экземпляру HistoricalPoll, мы можем сделать следующее:

>>> earliest_poll = poll.history.earliest()
>>> earliest_poll.instance.save()

Это изменит экземпляр poll на данные из объекта HistoricalPoll и создаст новую строку в таблице HistoricalPoll, указывающую на то, что было сделано новое изменение.

как_из

Этот метод возвращает экземпляр модели в том виде, в котором она существовала бы на указанную дату и время.

>>> from datetime import datetime
>>> poll.history.as_of(datetime(2010, 10, 25, 18, 4, 0))
<Poll: Poll object as of 2010-10-25 18:03:29.855689>
>>> poll.history.as_of(datetime(2010, 10, 25, 18, 5, 0))
<Poll: Poll object as of 2010-10-25 18:04:13.814128>

самый_поздний

Этот метод возвращает последнюю копию модели, доступную в истории модели.

>>> from datetime import datetime
>>> poll.history.most_recent()
<Poll: Poll object as of 2010-10-25 18:04:13.814128>

Сохранить без исторической записи

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

class Poll(models.Model):
    question = models.CharField(max_length=200)
    history = HistoricalRecords()

    def save_without_historical_record(self, *args, **kwargs):
        self.skip_history_when_saving = True
        try:
            ret = self.save(*args, **kwargs)
        finally:
            del self.skip_history_when_saving
        return ret


poll = Poll(question='something')
poll.save_without_historical_record()

Фильтрация данных с использованием связи с моделью

Для фильтрации изменений в данных можно установить связь с историей. Например, все записи данных, в которых участвовал определенный пользователь.

class Poll(models.Model):
    question = models.CharField(max_length=200)
    log = HistoricalRecords(related_name='history')


Poll.objects.filter(history__history_user=4)

Вы также можете выполнить предварительную выборку объектов с этим отношением, используя что-то вроде этого, например, для предварительной выборки в порядке убывания по history_date:

Poll.objects.filter(something).prefetch_related(Prefetch('history', queryset=Poll.history.order_by('-history_date'),
                                            to_attr='ordered_histories')
Вернуться на верх