Search code examples
pythondjangodjango-modelsdjango-simple-history

Django simple history inheritance getting from parent to child history


I am trying to use django-simple-history for keeping state of an Object.

Let's say i have the following:

class Parent(models.Model):
    fields...
    history = HistoricalRecords(inherit=True)

class Child(Parent):
    fields...

class Invoice(models.Model):
    fields...
    parent_history = models.ForeignKey("app.HistoricalParent", blank=True, null=True, on_delete=models.PROTECT, help_text="This keeps the state of the Child when Invoice is generated")
    parent =  models.ForeignKey(Parent, blank=True, null=True, on_delete=models.PROTECT) # can be removed so foreign key loop gets eliminated

How can i reach from Invoice to Child?

Invoice.objects.get(id=1).parent_history.child

Does not work and raise

AttributeError: 'HistoricalParent' object has no attribute 'child'

and this is how i am reaching Child from Parent

Invoice.objects.get(id=1).parent.child

I can't find the foreign key from HistoricalChild to HistoricalParent. Am i missing something? Does django-simple-history works some other way?


Solution

  • So let me break the foreign key relation when using django-simple-history

    So the HistoricalChild dosn't get a foreign key to HistoricalParent

    HistoricalChild = apps.get_model('app', 'HistoricalChild')
    HistoricalChild.objects.filter(parent_ptr_id=invoice.parent_history.id).order_by('-history_date')
    

    Will return so many item and it's pretty useless to me cause the parent has it's state from a certain date but the child is from the future

    and this mean i can't recreate a full child at by having a reference to it's historical parent at certain point in time..

    i ended up using historical_date for recreating a Child instance from certain time, like so

    parent_dict = apps.get_model('order', 'HistoricalParent').objects.filter(history_date__lte=invoice.created_date).order_by('-history_date').values().first()
    child_dict = apps.get_model('app', 'HistoricalChild').objects.filter(history_date__lte=invoice.created_date).order_by('-history_date').values().first()
    
    child_dict.update(parent_dict)
    
    for field in ['history_change_reason', 'history_id', 'history_type', 'history_date', 'history_user_id']:
        child_dict.pop(field)
    
    child_from_the_past = Child(**child_dict)