Search code examples
pythondjangodjango-haystackdjango-reversion

How to store parent pointers and data in a django reversion?


I'm having some trouble with some code for a django-reversion system I have set up.

I have a django model ObjectClass that inherits from a non-abstract model _concept. Long story, very unchangeable now. Makes sense in the rest of the context of the code.

On the class _concept I have mandatory ForeignKey field workgroup off to another model.

I have registered ObjectClass with Django reversion like so:

reversion.unregister(ObjectClass)
reversion.register(ObjectClass,follow=['_concept_ptr'])

All old versions save and can be compared using 'django-reversion-compare'. Unfortunately when I then click on any old version to view the historical version I get the error:

RevertError at /module.py
Could not revert revision, due to database integrity errors.

After some digging in the django-reversion code, I've done some fiddling and found that the error is coming up thus:

RelatedObjectDoesNotExist at /module.py
_concept has no workgroup.

Now I've inspected the stored versions in the database and found a few things:

  1. Any given historical reversion.models.version of a _concept has a workgroup in the serialized_data field (which is expected).
  2. Any given historical reversion.models.version of a ObjectClass does not have any of the parent information in the serialized_data field (which is expected).
  3. Any given historical reversion.models.version of an ObjectClass does not have any a _concept_ptr in the serialized_data field (which is not expected).

I'd suspect that django-reversion may have issues with fields that start with an underscore, however I have other fields that start with an underscore.

So I'm at a loss here. Is there a way to have this a model setup like this work?


edit:

After more checking it seems that the has no workgroup exception was from a Haystack call, which was alerting me to the fact that reversion is ignoring the workgroup for some reason.

I checked the database and this is whats in being serialized for an item (newlines added for readability):

In [28]: myobj.serialized_data
Out[28]: u'[{"fields": {
               "definition": "<p>A code for sex.</p>\\r\\n",
               "_is_locked": false, 
               "workgroup": 3, 
               "created": "2015-12-27T07:45:10.409Z", 
               "modified": "2015-12-27T08:38:26.989Z", 
               "readyToReview": false, 
               "_is_public": false, 
               "name": "Sex Code"
             }, 
             "model": "aristotle_mdr._concept", "pk": 30}]'

edit 2:

After disabling the haystack indexers everything works fine now, the issue is the Haystack signals are called when django-reversion tries to save the items to check consistency - then django calls the haystack post_save signals which try to update the index with incomplete data.

Still no solution yet. What I need in my haystack handler is either a way to determine if I'm inside a revisions transaction, or a way to prevent reversion from letting those signals fire. The latter is probably a better long term goal as I suspect that just by looking at revisions it is updating the Haystack index.


Solution

  • So you have come to a conclusion prevent reversion from letting those signals fire

    https://docs.djangoproject.com/en/dev/topics/signals/#disconnecting-signals

    django-reversion itself uses Signal.connect and disconnect itself.
    https://github.com/etianen/django-reversion/blob/b2f5f3362054b2b72a95bee1ed0dfe2dd2301cda/src/reversion/revisions.py

    I see you have few options.

    1. find a good place to do disconnect/connect (I guess you would need to override reversion, but I don't know much about it)
    2. (override reversion) exclude from registering certain signals such as haystack.
    3. (override haystack, reversion) set a flag on the being-saved object, and check the flag in the haystack signal to return right away.