Commits

Ivan Zakrevsky committed 24d8f2d Merge

Merged in fsw_/django-versioning (pull request #2)

ForeignKey versioning fixes

Comments (0)

Files changed (3)

versioning/models.py

 
 from . import _registry
 from .managers import RevisionManager
-from .utils import dmp, diff_split_by_fields, get_field_data
+from .utils import dmp, diff_split_by_fields, get_field_data, set_field_data
 
 try:
     str = unicode  # Python 2.* compatible
                 content = get_field_data(content_object, field_name)
                 patch = dmp.patch_fromText(diff)
                 content = dmp.patch_apply(patch, content)[0]
-                fobj = content_object._meta.get_field(field_name)
-                if content == 'None':
-                    if fobj.null:
-                        content = None
-                    else:
-                        continue
-                elif fobj.get_internal_type() in ('BooleanField',
-                                                  'NullBooleanField', ):
-                    if content == 'True':
-                        content = True
-                    elif content == 'False':
-                        content = False
-                elif fobj.get_internal_type() == 'ForeignKey':
-                    rel_model = fobj.rel.to
-                    try:
-                        #content = rel_model._meta.pk.to_python(content)
-                        content = rel_model.objects.get(pk=content)
-                    except rel_model.DoesNotExist:
-                        continue
-                else:
-                    content = fobj.to_python(content)
-                setattr(content_object, field_name, content)
+                
+                set_field_data(content_object, field_name, content)
+                
             changeset.reverted = True
             changeset.save()
 
                 if model_name != model.__name__ or field_name not in fields:
                     continue
                 patches = dmp.patch_fromText(diff)
-                setattr(
-                    old,
-                    field_name,
+                
+                set_field_data(
+                    old, 
+                    field_name, 
                     dmp.patch_apply(
                         patches,
                         get_field_data(old, field_name)

versioning/tests.py

     attr_bool = models.NullBooleanField(blank=True)
     attr_int = models.IntegerField(blank=True, null=True)
     attr_fk = models.ForeignKey(TestFkModel, blank=True, null=True)
+    attr_fk_notnull = models.ForeignKey(TestFkModel, related_name='foreign_key_notnull')
 
     class Meta:
         db_table = 'versioning_testmodel'
 
 versioning.register(
     TestModel,
-    ['attr_text', 'attr_int', 'attr_bool', 'attr_fk', ]
+    ['attr_text', 'attr_int', 'attr_bool', 'attr_fk', 'attr_fk_notnull']
 )
 
 
         )
         obj_1 = TestModel(
             attr_text="строка первая\nстрока вторая\nстрока третья",
-            attr_fk=obj_fk_1,
+            attr_fk=None,
+            attr_fk_notnull=obj_fk_2,
             attr_int=1
         )
         obj_1.revision_info = {
         obj_2 = TestModel.objects.get(pk=obj_1.pk)
         obj_2.attr_text = "строка первая\nстрока измененная вторая\nстрока третья"
         obj_2.attr_bool = True
+        obj_3.attr_fk = obj_fk_1
         obj_2.revision_info = {
             'editor': self.admin,
             'comment': 'comment 1',
         obj_3.attr_bool = False
         obj_3.attr_int = 3
         obj_3.attr_fk = obj_fk_2
+        obj_3.attr_fk_notnull = obj_fk_1
         obj_3.revision_info = {
             'editor': self.admin,
             'comment': 'comment 1',
 
         rev_1 = Revision.objects.get_for_object(obj_1).order_by('pk')[0]
         self.assertEqual(rev_1.revision, 1)
+        
+        rev_1.display_diff()
+        
         rev_1.reapply()
 
+
         obj_4 = TestModel.objects.get(pk=obj_1.pk)
         self.assertEqual(obj_4.attr_text, obj_1.attr_text)
         self.assertEqual(obj_4.attr_bool, obj_1.attr_bool)

versioning/utils.py

 from difflib import SequenceMatcher
 from django.db import models
 from django.utils.encoding import force_unicode
+from django.core.exceptions import ObjectDoesNotExist
 
 #from django.utils.encoding import smart_unicode
 # Google Diff Match Patch library
     patch = dmp.patch_make(txt1, txt2)
     return dmp.patch_toText(patch)
 
-
+def set_field_data(obj, field, data):
+    field_class = obj._meta.get_field(field)
+    if (field_class.null) and (data == 'None'):
+        data = None
+    elif isinstance(field_class, models.BooleanField) or isinstance(field_class, models.NullBooleanField):
+        if data == 'True':
+            data = True
+        elif data == 'False':
+            data = False              
+    elif isinstance(field_class, models.ForeignKey):
+        if data == 'None':
+            data = field_class.rel.to()
+        else:
+            data = field_class.rel.to._default_manager.get(pk=data)
+    else:
+        data = field_class.to_python(data)
+        
+    setattr(obj, field, data)
+    
 def get_field_data(obj, field):
     """Returns field's data"""
-    data = getattr(obj, field)
-    if isinstance(data, models.Model):
-        data = getattr(data, 'pk', None)
+    field_class = obj._meta.get_field(field)
+    if isinstance(field_class, models.ForeignKey):
+        try:
+            data = getattr(obj, field)
+            data = getattr(data, 'pk', None)
+        except ObjectDoesNotExist:
+            data = None
+    else:
+        data = getattr(obj, field)
     return force_unicode(data)