wimfeijen
5/10/2012 - 11:22 AM

https://github.com/etianen/django-reversion/issues/153#issuecomment-5622318

#!/usr/bin/env python
# coding: utf-8

"""
based in http://www.djangosnippets.org/snippets/1044/
"""

import os

BASE_PATH = os.path.abspath(os.path.dirname(__file__))
APP_LABEL = os.path.splitext(os.path.basename(__file__))[0]

os.environ["DJANGO_SETTINGS_MODULE"] = APP_LABEL

import reversion

# settings:
DEBUG = TEMPLATE_DEBUG = True
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'reversion',
    APP_LABEL,
)
DATABASES = {
    'default': {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": ":memory:",
    }
}

if __name__ == "__main__":
    from django.contrib.contenttypes.models import ContentType

    #______________________________________________________________________________
    # TestModel model classes:

    from django.db import models
    from django.contrib.auth.models import User

    class Pet(models.Model):
        name = models.CharField(max_length=100)
        def __unicode__(self):
            return self.name
        class Meta:
            app_label = "auth" # Hack: Cannot use an app_label that is under South control, due to http://south.aeracode.org/ticket/520

    class Person(models.Model):
        name = models.CharField(max_length=100)
        pets = models.ManyToManyField(Pet, blank=True)
        def __unicode__(self):
            return self.name
        class Meta:
            app_label = "auth" # Hack: Cannot use an app_label that is under South control, due to http://south.aeracode.org/ticket/520

    reversion.register(Person, follow=["pets"])
    reversion.register(Pet, follow=["person_set"])

    #------------------------------------------------------------------------------

    print "_"*79
    print " *** call 'syncdb':"
    from django.core import management
    management.call_command('syncdb', verbosity=0, interactive=False)
    print "-"*79

    #__________________________________________________________________________
    # play with TestModel:

    with reversion.create_revision():
        pet1 = Pet.objects.create(name="Catworth")
        pet2 = Pet.objects.create(name="Dogwoth")
        person = Person.objects.create(name="Dave")
        person.pets.add(pet1, pet2)

    print "version 1:", person, person.pets.all()

    with reversion.create_revision():
        pet1.name = "Catworth the second"
        pet1.save()
        pet2.save()
        pet2.delete()
        person.save()

    print "version 2:", person, person.pets.all()


    # Try to access the old version:
    old_version = reversion.get_for_object(person)[1]
    old_person = old_version.object


    # XXX: These output is not right, cause of current m2m state:
    print "old version test 1:", old_person, old_person.pets.all()
    # Output is:
    #    old version test 1: Dave [<Pet: Catworth the second>]


    # XXX: Also not right, cause of current m2m state:
    ids = old_version.field_dict["pets"]
    queryset = Pet.objects.all().filter(pk__in=ids)
    print "old version test 2:", ids, queryset
    # Output is:
    #    old version test 2: [u'1', u'2'] [<Pet: Catworth the second>]


    # This will work and gets the old version m2m state:
    old_revision = old_version.revision  # Get the associated 'revision' for this version, that groups all associated models.
    m2m_relations = old_revision.version_set.filter(
        content_type=ContentType.objects.get_for_model(Pet),
    )
    print "old version test 3:", m2m_relations
    # Output is:
    #    old version test 3: [<Version: Catworth>, <Version: Dogwoth>]


    # Get back the pets that were altered / deleted.
    old_version.revision.revert()


    print "revert to version 1:", person, person.pets.all()
    # Output is:
    #    revert to version 1: Dave [<Pet: Catworth>, <Pet: Dogwoth>]

    print "-"*79
    print "- END -"