17

I have a model Booking which has a history in it. like this and I use django_simple_history

class Booking(CreatedAtAbstractBase):
    history = HistoricalRecords()

And I use a management command to do tasks. In that I wanted to Prefetch history when taking a booking

booking_p_history = Booking.history.filter(s_id=6).order_by(
                'updated_at').first()    
booking_obj_list = Booking.objects.select_related(...) \
                    .prefetch_related(
                    Prefetch('booking_history', queryset=booking_p_history, to_attr='driver_pickup_history')
                    ,'booking_history') \
                    .filter(...)

How to use simple history inside prefetch?

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
Deepakraj Murugesan
  • 1,195
  • 11
  • 30
  • did you get an answer to this one? – AlexW Apr 24 '18 at 16:52
  • Even after a bounty, this question has still only been viewed about 50 more times. I've opened a GitHub ticket to see if anyone there has an answer or an idea of how it can be added: https://github.com/treyhunner/django-simple-history/issues/407 – Jamie Counsell Jun 12 '18 at 14:29
  • I've never used this simple-history app, and I'm not sure whats the correct approach, but just wonna give you a few tips looking at your code: 1) don't use `.first()` at the end of `booking_p_history`, you cant prefetch a single instance. 2) Don't use `to_attr` if its going to be equal to prefetch first argument. 3) Are you sure need to prefetch `'booking_history'`? Have you tried with `.prefetch_related('history_set')` -> this should cache: `instance.history.all()` give it a try. 4) Move `select_related` and `prefetch_related` at the end of the `Queryset`, after all `.filter`/`limit` calls. – Todor Jun 13 '18 at 01:55
  • The big issue that i found looking over the `simple_history`, is that the `HistoricalRecords` is a Field, instead of being a Model. that way it, even if in the db we have a foreign key between your model and the history model, the django dont recognize it, making impossible for the `select_related/prefetch_related` work: If you call the `YourModel._meta.fields` the `history` will not be present on that list. I'm trying to do something about this to help you, i never used this library sorry. – Luan Fonseca Jun 13 '18 at 02:00

1 Answers1

8

Ends up the answer is basically "you can't". And it makes sense. As per the ticket I opened:

Since history is a manager rather than a ForeignKey field, objs = MyModel.objects.all().prefetch_related('history') won't work. Right now, we don't have any defined way of implementing your feature, and nothing immediately comes to mind for me as I don't know the ins and outs of how django implements prefetch_related.

You could, however, query the historical table directly, cache the results, and then use the evaluated queryset for your checks. For more on caching and querysets, look here. So I'm thinking you could hold the history and query it like this:

history_objs = MyModel.history.all()
objs = MyModel.objects.all()

history_for_first_object = filter(lambda x: x.id == objs.first().id, history_objs)
Community
  • 1
  • 1
Jamie Counsell
  • 7,730
  • 6
  • 46
  • 81