def test_get_translations_versions_for_object(self): # check that object has 2 translation already self.assertEqual(self.with_translation.translations.count(), 2) # get_for_object returns latest version first. version_2 = default_revision_manager.get_for_object( self.with_translation)[0] version_1 = default_revision_manager.get_for_object( self.with_translation)[1] revision_2 = version_2.revision revision_1 = version_1.revision # compare count of translations from latest revision to actual count result_revision_2 = get_translations_versions_for_object( self.with_translation, revision_2) result_revision_1 = get_translations_versions_for_object( self.with_translation, revision_1) self.assertEqual(len(result_revision_2), 2) self.assertEqual(len(result_revision_1), 1) # test with providing versions explicitly, should respect versions # over revision exclude_en_pks = default_revision_manager.get_for_object( self.with_translation.translations.filter( language_code='en').get()).values_list('pk', flat=True) versions = revision_2.version_set.all().exclude(pk__in=exclude_en_pks) # check that we have versions (should be object and german translation) self.assertEqual(len(versions), 2) result_versions = get_translations_versions_for_object( self.with_translation, revision_1, versions=versions) self.assertEqual(len(result_versions), 1)
def test_get_conflict_fks_versions_with_simple_models(self): # test with object that has no relations simple_no_admin_version = default_revision_manager.get_for_object( self.simple_registered)[0] result = get_conflict_fks_versions(self.simple_registered, simple_no_admin_version, simple_no_admin_version.revision) self.assertEqual(len(result), 0) # test with object that has no conflicts simple_fk_version = default_revision_manager.get_for_object( self.simple_fk)[0] result = get_conflict_fks_versions(self.simple_fk, simple_fk_version, simple_fk_version.revision) self.assertEqual(len(result), 0) # test with object that has conflicts self.simple_fk.delete() self.simple_no_admin.delete() result = get_conflict_fks_versions(self.simple_fk, simple_fk_version, simple_fk_version.revision) self.assertEqual(len(result), 1) # check that exclude excludes by excluding previous result version result = get_conflict_fks_versions(self.simple_fk, simple_fk_version, simple_fk_version.revision, exclude={'pk': result[0].pk}) self.assertEqual(len(result), 0)
def test_edit_plugin_directly(self): content0 = self.rand_str(prefix='content0_') content1 = self.rand_str(prefix='content1_') content2 = self.rand_str(prefix='content2_') article = self.create_article(content=content0) # Revision 1 self.create_revision(article, content=content1) self.assertEqual( len(default_revision_manager.get_for_object(article)), 1) # Revision 2 with transaction.atomic(): plugins = article.content.get_plugins() plugin = plugins[0].get_plugin_instance()[0] plugin.body = content2 plugin.save() aldryn_create_revision(article) self.assertEqual( len(default_revision_manager.get_for_object(article)), 2) response = self.client.get(article.get_absolute_url()) self.assertContains(response, content2) self.assertNotContains(response, content1) # Revert to revision 1 self.revert_to(article, 1) response = self.client.get(article.get_absolute_url()) self.assertContains(response, content1) self.assertNotContains(response, content2)
def test_get_deleted_placeholders(self): with_placeholder_version = default_revision_manager.get_for_object( self.with_placeholder)[0] # test returns nothing if there are no deleted placeholders result = get_deleted_placeholders(with_placeholder_version.revision) self.assertEqual(len(result), 0) # delete placeholder placeholder_pk = self.with_placeholder.content.pk self.with_placeholder.content.delete() # check that placeholder was actually deleted. self.assertEqual(self.with_placeholder._meta.model.objects.filter( pk=placeholder_pk).count(), 0) result = get_deleted_placeholders(with_placeholder_version.revision) self.assertEqual(len(result), 1) # test with revision that has more then one deleted placeholder # (misc objects) complex_one_fk_version = default_revision_manager.get_for_object( self.complex_one_fk)[0] other_placeholder_pk = self.complex_one_fk.complex_content.pk self.complex_one_fk.complex_content.delete() self.assertEqual(self.with_placeholder._meta.model.objects.filter( pk__in=[placeholder_pk, other_placeholder_pk]).count(), 0) result = get_deleted_placeholders(complex_one_fk_version.revision) self.assertEqual(len(result), 2)
def test_people_revision_is_reverted(self): rev_1_values = self.make_new_values( self.data_raw['person']['en'], 1) # rev 1 self.person1.set_current_language('en') self.create_revision(self.person1, **rev_1_values) self.assertEqual( len(default_revision_manager.get_for_object(self.person1)), 1) # check that values are actually changed self.assertEqual(self.person1.function, rev_1_values['function']) self.assertEqual(self.person1.description, rev_1_values['description']) # rev 2 rev_2_values = self.make_new_values( self.data_raw['person']['en'], 2) self.create_revision(self.person1, **rev_2_values) self.assertEqual( len(default_revision_manager.get_for_object(self.person1)), 2) # check that values are actually changed self.assertEqual(self.person1.function, rev_2_values['function']) self.assertEqual(self.person1.description, rev_2_values['description']) # revert self.revert_to(self.person1, 1) self.person1 = Person.objects.get(pk=self.person1.pk) # check previous values self.assertEqual( self.person1.function, rev_1_values['function']) self.assertEqual( self.person1.description, rev_1_values['description'])
def test_get_deleted_placeholders(self): with_placeholder_version = default_revision_manager.get_for_object( self.with_placeholder)[0] # test returns nothing if there are no deleted placeholders result = get_deleted_placeholders(with_placeholder_version.revision) self.assertEqual(len(result), 0) # delete placeholder placeholder_pk = self.with_placeholder.content.pk self.with_placeholder.content.delete() # check that placeholder was actually deleted. self.assertEqual( self.with_placeholder._meta.model.objects.filter( pk=placeholder_pk).count(), 0) result = get_deleted_placeholders(with_placeholder_version.revision) self.assertEqual(len(result), 1) # test with revision that has more then one deleted placeholder # (misc objects) complex_one_fk_version = default_revision_manager.get_for_object( self.complex_one_fk)[0] other_placeholder_pk = self.complex_one_fk.complex_content.pk self.complex_one_fk.complex_content.delete() self.assertEqual( self.with_placeholder._meta.model.objects.filter( pk__in=[placeholder_pk, other_placeholder_pk]).count(), 0) result = get_deleted_placeholders(complex_one_fk_version.revision) self.assertEqual(len(result), 2)
def test_get_translations_versions_for_object(self): # check that object has 2 translation already self.assertEqual(self.with_translation.translations.count(), 2) # get_for_object returns latest version first. version_2 = default_revision_manager.get_for_object( self.with_translation)[0] version_1 = default_revision_manager.get_for_object( self.with_translation)[1] revision_2 = version_2.revision revision_1 = version_1.revision # compare count of translations from latest revision to actual count result_revision_2 = get_translations_versions_for_object( self.with_translation, revision_2) result_revision_1 = get_translations_versions_for_object( self.with_translation, revision_1) self.assertEqual(len(result_revision_2), 2) self.assertEqual(len(result_revision_1), 1) # test with providing versions explicitly, should respect versions # over revision exclude_en_pks = default_revision_manager.get_for_object( self.with_translation.translations.filter( language_code='en').get()).values_list('pk', flat=True) versions = revision_2.version_set.all().exclude( pk__in=exclude_en_pks) # check that we have versions (should be object and german translation) self.assertEqual(len(versions), 2) result_versions = get_translations_versions_for_object( self.with_translation, revision_1, versions=versions) self.assertEqual(len(result_versions), 1)
def test_get_conflict_fks_versions_with_simple_models(self): # test with object that has no relations simple_no_admin_version = default_revision_manager.get_for_object( self.simple_registered)[0] result = get_conflict_fks_versions( self.simple_registered, simple_no_admin_version, simple_no_admin_version.revision) self.assertEqual(len(result), 0) # test with object that has no conflicts simple_fk_version = default_revision_manager.get_for_object( self.simple_fk)[0] result = get_conflict_fks_versions( self.simple_fk, simple_fk_version, simple_fk_version.revision) self.assertEqual(len(result), 0) # test with object that has conflicts self.simple_fk.delete() self.simple_no_admin.delete() result = get_conflict_fks_versions( self.simple_fk, simple_fk_version, simple_fk_version.revision) self.assertEqual(len(result), 1) # check that exclude excludes by excluding previous result version result = get_conflict_fks_versions( self.simple_fk, simple_fk_version, simple_fk_version.revision, exclude={'pk': result[0].pk}) self.assertEqual(len(result), 0)
def test_get_deleted_objects_versions(self): blank_fk_version = default_revision_manager.get_for_object( self.blank_fk)[0] blank_fk_pk = self.blank_fk.pk # ensure that returns nothing for not deleted objects result = get_deleted_objects_versions( blank_fk_version.revision.version_set.all()) self.assertEqual(len(result), 0) # delete and ensure that object was deleted. self.blank_fk.delete() self.assertEqual( BlankFK.objects.filter(pk=blank_fk_pk).count(), 0) # test against deleted object result = get_deleted_objects_versions( blank_fk_version.revision.version_set.all()) self.assertEqual(len(result), 1) self.assertEqual(result[0].object_id_int, blank_fk_pk) # test with mixing 2 deleted object Versions simple_fk_version = default_revision_manager.get_for_object( self.simple_fk)[0] simple_fk_pk = self.simple_fk.pk self.simple_fk.delete() self.assertEqual(SimpleFK.objects.filter(pk=simple_fk_pk).count(), 0) # construct versions with this two objects and test blank_fk_versions_pks = [version.pk for version in blank_fk_version.revision.version_set.all()] simple_fk_versions_pks = [version.pk for version in simple_fk_version.revision.version_set.all()] both_obj_versions_pks = blank_fk_versions_pks + simple_fk_versions_pks custom_versions = Version.objects.filter(pk__in=both_obj_versions_pks) result = get_deleted_objects_versions(custom_versions) self.assertEqual(len(result), 2)
def test_create_aldryn_revision(self): # would be used to get admin instance with_placeholder_version = get_version_for_object( self.with_placeholder) admin_instance = self.get_admin_instance_for_object( with_placeholder_version) plugin = api.add_plugin(self.with_placeholder.content, 'TextPlugin', language='en') plugin.body = 'Initial text' plugin.save() # ensure there was no versions for plugin before self.assertEqual( default_revision_manager.get_for_object(plugin).count(), 0) with transaction.atomic(): with revision_context_manager.create_revision(): admin_instance._create_aldryn_revision( plugin.placeholder, comment='New aldryn revision with initial plugin') # ensure there is at least one version after create aldryn revision self. assertEqual( default_revision_manager.get_for_object(plugin).count(), 1) new_plugin_text = 'test plugin content was changed' plugin.body = new_plugin_text plugin.save() with transaction.atomic(): with revision_context_manager.create_revision(): admin_instance._create_aldryn_revision( plugin.placeholder, comment='New aldryn revision with initial plugin') # ensure there is at least one version after create aldryn revision self. assertEqual( default_revision_manager.get_for_object(plugin).count(), 2) latest_plugin = plugin._meta.model.objects.get(pk=plugin.pk) # ensure text is latest self.assertEqual(latest_plugin.body, new_plugin_text) # ensure text is initial if reverted to previous revision prev_version = default_revision_manager.get_for_object( self.with_placeholder)[1] prev_version.revision.revert() # refresh from db latest_plugin = plugin._meta.model.objects.get(pk=plugin.pk) # ensure plugin text was chagned. Note however that there might be # different paths to ensure that text is chagned for CMSPlugin # This only checks that plugin content (which is text plugin not the cms # is reverted, so be careful. self.assertEqual(latest_plugin.body, 'Initial text')
def test_group_revision_is_created(self): values = self.make_new_values(self.data_raw['group']['en'], 1) with transaction.atomic(): with create_revision(): group = Group.objects.create(**values) self.assertEqual( len(default_revision_manager.get_for_object(group)), 1)
def test_person_revision_is_created(self): values = self.make_new_values(self.data_raw['person']['en'], 1) with transaction.atomic(): with create_revision(): person = Person.objects.create(**values) self.assertEqual( len(default_revision_manager.get_for_object(person)), 1)
def test_get_conflict_fks_versions_with_blank_fk_no_fk(self): # test with new blank fk that has no relations, should not have # conflicts after delete. new_blank_fk = self.create_with_revision(BlankFK) new_blank_fk_version = default_revision_manager.get_for_object( new_blank_fk)[0] result = get_conflict_fks_versions(new_blank_fk, new_blank_fk_version, new_blank_fk_version.revision) self.assertEqual(len(result), 0)
def revert_to(self, object_with_revision, revision_number): """ Revert <object with revision> to revision number. """ # get by position, since reversion_id is not reliable, version = list(reversed( default_revision_manager.get_for_object( object_with_revision)))[revision_number - 1] version.revision.revert()
def test_get_conflict_fks_versions_with_blank_fk_no_fk(self): # test with new blank fk that has no relations, should not have # conflicts after delete. new_blank_fk = self.create_with_revision(BlankFK) new_blank_fk_version = default_revision_manager.get_for_object( new_blank_fk)[0] result = get_conflict_fks_versions( new_blank_fk, new_blank_fk_version, new_blank_fk_version.revision) self.assertEqual(len(result), 0)
def test_get_deleted_placeholders_for_object(self): # test that it not fails with object that has no placeholders simple_no_admin_version = default_revision_manager.get_for_object( self.simple_no_admin)[0] result = get_deleted_placeholders_for_object( self.with_placeholder, simple_no_admin_version.revision) self.assertEqual(len(result), 0) # test if no placeholders were deleted with_placeholder_version = default_revision_manager.get_for_object( self.with_placeholder)[0] result = get_deleted_placeholders_for_object( self.with_placeholder, with_placeholder_version.revision) self.assertEqual(len(result), 0) # test if placeholder was deleted for this object # delete placeholder placeholder_pk = self.with_placeholder.content.pk self.with_placeholder.content.delete() # check that placeholder was actually deleted. self.assertEqual( self.with_placeholder._meta.model.objects.filter( pk=placeholder_pk).count(), 0) result = get_deleted_placeholders_for_object( self.with_placeholder, with_placeholder_version.revision) self.assertEqual(len(result), 1) # test if placeholder was deleted for not related object (no result) complex_one_fk_version = default_revision_manager.get_for_object( self.complex_one_fk)[0] other_placeholder_pk = self.complex_one_fk.complex_content.pk self.complex_one_fk.complex_content.delete() self.assertEqual( self.with_placeholder._meta.model.objects.filter( pk__in=[placeholder_pk, other_placeholder_pk]).count(), 0) result = get_deleted_placeholders_for_object( self.with_placeholder, with_placeholder_version.revision) self.assertEqual(len(result), 1) result = get_deleted_placeholders_for_object( self.complex_one_fk, complex_one_fk_version.revision) self.assertEqual(len(result), 1)
def revert_to(self, object_with_revision, revision_number): """ Revert <object with revision> to revision number. """ # get by position, since reversion_id is not reliable, version = list( reversed( default_revision_manager.get_for_object( object_with_revision)))[revision_number - 1] version.revision.revert()
def test_person_revision_with_fk_relations(self): """ Tests against recovering object with fk relations, NOTE though at time of writing this test cases aldryn-reversion DOES restores ALL OBJECTS THAT ARE PRESENT IN REVISION, which means that from history view it would also restore related objects to state of currently restored revision. Also this test case doesn't checks against that behavior, so be careful. """ # rev 1 user1 group 1 user1 = self.create_user('rev1_user', 'rev1_user') rev_1_values = self.make_new_values( self.data_raw['person']['en'], 1) rev_1_values['user'] = user1 rev_1_values['groups'] = [self.group1] self.person1.set_current_language('en') self.create_revision(self.person1, **rev_1_values) self.assertEqual( len(default_revision_manager.get_for_object(self.person1)), 1) self.assertEqual(self.person1.user, user1) self.assertIn(self.group1, self.person1.groups.all()) # rev 2 user 2 group 2 user2 = self.create_user('rev2_user', 'rev2_user') rev_2_values = self.make_new_values( self.data_raw['person']['en'], 2) rev_2_values['user'] = user2 rev_2_values['groups'] = [self.group2] self.create_revision(self.person1, **rev_2_values) self.assertEqual( len(default_revision_manager.get_for_object(self.person1)), 2) self.assertEqual(self.person1.user, user2) self.assertIn(self.group2, self.person1.groups.all()) # revert to rev 1 with user 1 self.revert_to(self.person1, 1) self.person1 = Person.objects.get(pk=self.person1.pk) self.person1.set_current_language('en') self.assertEqual(self.person1.user, user1) self.assertNotEqual(self.person1.user, user2) self.assertIn(self.group1, self.person1.groups.all())
def test_get_deleted_placeholders_for_object(self): # test that it not fails with object that has no placeholders simple_no_admin_version = default_revision_manager.get_for_object( self.simple_no_admin)[0] result = get_deleted_placeholders_for_object( self.with_placeholder, simple_no_admin_version.revision) self.assertEqual(len(result), 0) # test if no placeholders were deleted with_placeholder_version = default_revision_manager.get_for_object( self.with_placeholder)[0] result = get_deleted_placeholders_for_object( self.with_placeholder, with_placeholder_version.revision) self.assertEqual(len(result), 0) # test if placeholder was deleted for this object # delete placeholder placeholder_pk = self.with_placeholder.content.pk self.with_placeholder.content.delete() # check that placeholder was actually deleted. self.assertEqual(self.with_placeholder._meta.model.objects.filter( pk=placeholder_pk).count(), 0) result = get_deleted_placeholders_for_object( self.with_placeholder, with_placeholder_version.revision) self.assertEqual(len(result), 1) # test if placeholder was deleted for not related object (no result) complex_one_fk_version = default_revision_manager.get_for_object( self.complex_one_fk)[0] other_placeholder_pk = self.complex_one_fk.complex_content.pk self.complex_one_fk.complex_content.delete() self.assertEqual(self.with_placeholder._meta.model.objects.filter( pk__in=[placeholder_pk, other_placeholder_pk]).count(), 0) result = get_deleted_placeholders_for_object( self.with_placeholder, with_placeholder_version.revision) self.assertEqual(len(result), 1) result = get_deleted_placeholders_for_object( self.complex_one_fk, complex_one_fk_version.revision) self.assertEqual(len(result), 1)
def get_for_object(self, object): """ Returns all the versions of the given object, ordered by date created. This method was deprecated in django-reversion 1.5, and will be removed in django-reversion 1.7. New applications should use reversion.get_for_object(). The new version of this method returns results ordered with the most recent versions first. This legacy version of the method continues to return the results ordered with the oldest versions first. """ from reversion.revisions import default_revision_manager return default_revision_manager.get_for_object(object).order_by("pk")
def registrationHistory(request, item_id): item = get_if_user_can_view(MDR._concept,request.user,item_id) from reversion.revisions import default_revision_manager history = [] for s in item.statuses.all(): past = default_revision_manager.get_for_object(s) history.append((s,past)) return render(request,"aristotle_mdr/registrationHistory.html", {'item':item, 'user_can_edit':False, 'history': history } )
def test_revision_view_reverts_object_to_selected_state(self): initial_position = self.simple_registered.position new_position = 99 self.create_revision(self.simple_registered, position=new_position) self.assertNotEqual(initial_position, self.simple_registered.position) prev_version = default_revision_manager.get_for_object( self.simple_registered)[1] response = self.post_revision_veiw_response( self.simple_registered, prev_version) self.assertEqual(response.status_code, 302) self.simple_registered = SimpleRegistered.objects.get( pk=self.simple_registered.pk) self.assertEquals(self.simple_registered.position, initial_position)
def test_get_conflict_fks_versions_with_blank_fk_model(self): # test with no conflict bank_fk_version = default_revision_manager.get_for_object( self.blank_fk)[0] result = get_conflict_fks_versions( self.blank_fk, bank_fk_version, bank_fk_version.revision) self.assertEqual(len(result), 0) # test with conflict, self.blank_fk.delete() self.simple_registered.delete() result = get_conflict_fks_versions( self.blank_fk, bank_fk_version, bank_fk_version.revision) self.assertEqual(len(result), 1)
def get_version_for_object(obj, revision_pk=None): """ Return version for object, if revision_pk is provided - returns a version from that specific revision. No exception handling! if you get exceptions check your logic. :param obj: revisionable object :param revision_pk: int revision pk :return: reversion.models.Version """ versions = default_revision_manager.get_for_object(obj) if revision_pk is not None: versions = versions.filter(revision__pk=revision_pk) version = versions[0] return version
def test_get_conflict_fks_versions_with_blank_fk_model(self): # test with no conflict bank_fk_version = default_revision_manager.get_for_object( self.blank_fk)[0] result = get_conflict_fks_versions(self.blank_fk, bank_fk_version, bank_fk_version.revision) self.assertEqual(len(result), 0) # test with conflict, self.blank_fk.delete() self.simple_registered.delete() result = get_conflict_fks_versions(self.blank_fk, bank_fk_version, bank_fk_version.revision) self.assertEqual(len(result), 1)
def test_get_deleted_objects_versions(self): blank_fk_version = default_revision_manager.get_for_object( self.blank_fk)[0] blank_fk_pk = self.blank_fk.pk # ensure that returns nothing for not deleted objects result = get_deleted_objects_versions( blank_fk_version.revision.version_set.all()) self.assertEqual(len(result), 0) # delete and ensure that object was deleted. self.blank_fk.delete() self.assertEqual(BlankFK.objects.filter(pk=blank_fk_pk).count(), 0) # test against deleted object result = get_deleted_objects_versions( blank_fk_version.revision.version_set.all()) self.assertEqual(len(result), 1) self.assertEqual(result[0].object_id_int, blank_fk_pk) # test with mixing 2 deleted object Versions simple_fk_version = default_revision_manager.get_for_object( self.simple_fk)[0] simple_fk_pk = self.simple_fk.pk self.simple_fk.delete() self.assertEqual(SimpleFK.objects.filter(pk=simple_fk_pk).count(), 0) # construct versions with this two objects and test blank_fk_versions_pks = [ version.pk for version in blank_fk_version.revision.version_set.all() ] simple_fk_versions_pks = [ version.pk for version in simple_fk_version.revision.version_set.all() ] both_obj_versions_pks = blank_fk_versions_pks + simple_fk_versions_pks custom_versions = Version.objects.filter(pk__in=both_obj_versions_pks) result = get_deleted_objects_versions(custom_versions) self.assertEqual(len(result), 2)
def item_history(request,iid): item = get_if_user_can_view(MDR._concept,request.user,iid) if not item: if request.user.is_anonymous(): return redirect(reverse('django.contrib.auth.views.login')+'?next=%s' % request.path) else: raise PermissionDenied item = item.item versions = default_revision_manager.get_for_object(item) from django.contrib.contenttypes.models import ContentType ct = ContentType.objects.get_for_model(item) versions = reversion.models.Version.objects.filter(content_type=ct,object_id=item.pk).order_by('-revision__date_created') page = render(request,"aristotle_mdr/actions/concept_history.html",{"item":item,'versions':versions}) return page
def item_history(request, iid): item = get_if_user_can_view(MDR._concept, request.user, iid) if not item: if request.user.is_anonymous(): return redirect(reverse('friendly_login') + '?next=%s' % request.path) else: raise PermissionDenied item = item.item versions = default_revision_manager.get_for_object(item) from django.contrib.contenttypes.models import ContentType ct = ContentType.objects.get_for_model(item) versions = reversion.models.Version.objects.filter(content_type=ct, object_id=item.pk).order_by('-revision__date_created') page = render(request, "aristotle_mdr/actions/concept_history.html", {"item": item, 'versions': versions}) return page
def test_recover_form_clean(self): # test with no conflicts, should validate fine form_simple_kwargs = self.build_form_kwargs(self.simple_no_admin) # form validation doesn't triggers if form is not bound, so # we need to pass dummy data so it would be considered as bound # Should not be the case in real life because of request.POST form_simple = self.build_bound_form(form_simple_kwargs) self.assertTrue(form_simple.is_valid()) # test with not resolved conflicts - should rise validation error simple_no_admin_version = default_revision_manager.get_for_object( self.simple_no_admin)[0] self.simple_no_admin.delete() self.assertEqual(SimpleNoAdmin.objects.count(), 0) self.assertEqual(SimpleFK.objects.count(), 0) simple_fk_kwargs = self.build_form_kwargs(self.simple_fk) form_simple_fk_with_conflicts = self.build_bound_form(simple_fk_kwargs) self.assertFalse(form_simple_fk_with_conflicts.is_valid()) self.assertEqual( len(form_simple_fk_with_conflicts.non_field_errors()), 1) self.assertEqual(form_simple_fk_with_conflicts.non_field_errors()[0], 'Cannot restore object, there are conflicts!') # test with conflicts that were resolved by utility # RecursiveRevisionConflictResolver, and result were passed to form # init, should validate fine simple_fk_resolved_conflicts = RecursiveRevisionConflictResolver( simple_fk_kwargs['version']).resolve() simple_fk_kwargs['resolve_conflicts'] = simple_fk_resolved_conflicts form_simple_fk_resolved = self.build_bound_form(simple_fk_kwargs) self.assertTrue(form_simple_fk_resolved.is_valid()) # test with conflicts that were resolved, and passed to form init, # but then something more was corrupted (new conflicts) should raise simple_no_admin_version.revert() partially_resolved = RecursiveRevisionConflictResolver( simple_fk_kwargs['version']).resolve() simple_fk_kwargs['resolve_conflicts'] = partially_resolved form_simple_fk_resolved = self.build_bound_form(simple_fk_kwargs) # delete object which was not resolved by resolver SimpleNoAdmin.objects.all()[0].delete() self.assertEqual(SimpleNoAdmin.objects.count(), 0) self.assertFalse(form_simple_fk_resolved.is_valid())
def test_recover_form_clean(self): # test with no conflicts, should validate fine form_simple_kwargs = self.build_form_kwargs(self.simple_no_admin) # form validation doesn't triggers if form is not bound, so # we need to pass dummy data so it would be considered as bound # Should not be the case in real life because of request.POST form_simple = self.build_bound_form(form_simple_kwargs) self.assertTrue(form_simple.is_valid()) # test with not resolved conflicts - should rise validation error simple_no_admin_version = default_revision_manager.get_for_object( self.simple_no_admin)[0] self.simple_no_admin.delete() self.assertEqual(SimpleNoAdmin.objects.count(), 0) self.assertEqual(SimpleFK.objects.count(), 0) simple_fk_kwargs = self.build_form_kwargs(self.simple_fk) form_simple_fk_with_conflicts = self.build_bound_form(simple_fk_kwargs) self.assertFalse(form_simple_fk_with_conflicts.is_valid()) self.assertEqual(len(form_simple_fk_with_conflicts.non_field_errors()), 1) self.assertEqual(form_simple_fk_with_conflicts.non_field_errors()[0], 'Cannot restore object, there are conflicts!') # test with conflicts that were resolved by utility # RecursiveRevisionConflictResolver, and result were passed to form # init, should validate fine simple_fk_resolved_conflicts = RecursiveRevisionConflictResolver( simple_fk_kwargs['version']).resolve() simple_fk_kwargs['resolve_conflicts'] = simple_fk_resolved_conflicts form_simple_fk_resolved = self.build_bound_form(simple_fk_kwargs) self.assertTrue(form_simple_fk_resolved.is_valid()) # test with conflicts that were resolved, and passed to form init, # but then something more was corrupted (new conflicts) should raise simple_no_admin_version.revert() partially_resolved = RecursiveRevisionConflictResolver( simple_fk_kwargs['version']).resolve() simple_fk_kwargs['resolve_conflicts'] = partially_resolved form_simple_fk_resolved = self.build_bound_form(simple_fk_kwargs) # delete object which was not resolved by resolver SimpleNoAdmin.objects.all()[0].delete() self.assertEqual(SimpleNoAdmin.objects.count(), 0) self.assertFalse(form_simple_fk_resolved.is_valid())
def compare_concepts(request, obj_type=None): comparison = {} item_a = request.GET.get('item_a', None) item_b = request.GET.get('item_b', None) context = {"item_a": item_a, "item_b": item_b} item_a = MDR._concept.objects.visible(request.user).filter(pk=item_a).first() # .item item_b = MDR._concept.objects.visible(request.user).filter(pk=item_b).first() # .item context = {"item_a": item_a, "item_b": item_b} request.GET = request.GET.copy() if item_a: item_a = item_a.item else: request.GET['item_a']="0" if item_b: item_b = item_b.item else: request.GET['item_b']="0" qs = MDR._concept.objects.visible(request.user) form = MDRForms.CompareConceptsForm(request.GET, user=request.user, qs=qs) # A form bound to the POST data if form.is_valid(): from django.contrib.contenttypes.models import ContentType revs=[] for item in [item_a, item_b]: versions = default_revision_manager.get_for_object(item) ct = ContentType.objects.get_for_model(item) version = reversion.models.Version.objects.filter(content_type=ct, object_id=item.pk).order_by('-revision__date_created').first() revs.append(version) if revs[0] is None: form.add_error('item_a', _('This item has no revisions. A comparison cannot be made')) if revs[1] is None: form.add_error('item_b', _('This item has no revisions. A comparison cannot be made')) if revs[0] is not None and revs[1] is not None: comparator_a_to_b = item_a.comparator() comparator_b_to_a = item_b.comparator() version1 = revs[0] version2 = revs[1] compare_data_a, has_unfollowed_fields_a = comparator_a_to_b.compare(item_a, version2, version1) compare_data_b, has_unfollowed_fields_b = comparator_b_to_a.compare(item_a, version1, version2) has_unfollowed = has_unfollowed_fields_a or has_unfollowed_fields_b context.update({'debug': {'cmp_a': compare_data_a}}) comparison = {} for field_diff_a in compare_data_a: name = field_diff_a['field'].name x = comparison.get(name, {}) x['field'] = field_diff_a['field'] x['a'] = field_diff_a['diff'] comparison[name] = x for field_diff_b in compare_data_b: name = field_diff_b['field'].name comparison.get(name, {})['b'] = field_diff_b['diff'] same = {} for f in item_a._meta.fields: if f.name not in comparison.keys(): same[f.name] = {'field': f, 'value': getattr(item_a, f.name)} if f.name.startswith('_'): # hidden field comparison.pop(f.name, None) same.pop(f.name, None) hidden_fields = ['readyToReview', 'workgroup', 'created', 'modified', 'id'] for h in hidden_fields: comparison.pop(h, None) same.pop(h, None) only_a = {} for f in item_a._meta.fields: if (f not in item_b._meta.fields and f not in comparison.keys() and f not in same.keys() and f.name not in hidden_fields): only_a[f.name] = {'field': f, 'value': getattr(item_a, f.name)} only_b = {} for f in item_b._meta.fields: if (f not in item_a._meta.fields and f not in comparison.keys() and f not in same.keys() and f.name not in hidden_fields): only_b[f.name] = {'field': f, 'value': getattr(item_b, f.name)} comparison = sorted(comparison.items()) context.update({ "comparison": comparison, "same": same, "only_a": only_a, "only_b": only_b, }) context.update({"form": form}) # comparison = {'a': compare_data_a, 'b': compare_data_b} return render(request, "aristotle_mdr/actions/compare/compare_items.html", context)
def test_recover_form_save(self): # test reverts object_version (no extras, simple object with # no translations, placeholders or fks form_simple_kwargs = self.build_form_kwargs(self.simple_no_admin) self.simple_no_admin.delete() self.assertEqual(SimpleNoAdmin.objects.count(), 0) form_simple = self.build_bound_form(form_simple_kwargs) self.assertTrue(form_simple.is_valid()) form_simple.save() self.assertEqual(SimpleNoAdmin.objects.count(), 1) # test reverts object and deleted placeholders with_placeholder_version = default_revision_manager.get_for_object( self.with_placeholder)[0] placeholder_pk = self.with_placeholder.content.pk self.with_placeholder.content.delete() # check that placeholder was actually deleted. self.assertEqual( Placeholder.objects.filter(pk=placeholder_pk).count(), 0) placeholder_versions = get_deleted_placeholders_for_object( self.with_placeholder, with_placeholder_version.revision) form_with_placeholders_kwargs = self.build_form_kwargs( self.with_placeholder) self.with_placeholder.delete() self.assertEqual(WithPlaceholder.objects.count(), 0) form_with_placeholders_kwargs['placeholders'] = placeholder_versions form_with_placeholder = self.build_bound_form( form_with_placeholders_kwargs) self.assertTrue(form_with_placeholder.is_valid()) form_with_placeholder.save() self.assertEqual(WithPlaceholder.objects.count(), 1) # check that placeholder was restored self.assertEqual( Placeholder.objects.filter(pk=placeholder_pk).count(), 1) # test reverts object and translations form_translated_kwargs = self.build_form_kwargs(self.with_translation) self.with_translation.delete() self.assertEqual(WithTranslations.objects.count(), 0) self.assertEqual(self.with_translation.translations.count(), 0) form_with_translation = self.build_unbound_form(form_translated_kwargs) translations_pks = [ tr[0] for tr in form_with_translation.fields['translations'].choices ] form_with_translation = self.form_class( {'translations': translations_pks}, **form_translated_kwargs) self.assertTrue(form_with_translation.is_valid()) form_with_translation.save() self.assertEqual(WithTranslations.objects.count(), 1) self.assertEqual(WithTranslations.objects.get().translations.count(), 2) self.assertEqual(self.with_translation.description, WithTranslations.objects.get().description) # test reverts object and conflicts simple_fk_kwargs = self.build_form_kwargs(self.simple_fk) SimpleNoAdmin.objects.get().delete() self.assertEqual(SimpleNoAdmin.objects.count(), 0) self.assertEqual(SimpleFK.objects.count(), 0) simple_fk_resolved_conflicts = RecursiveRevisionConflictResolver( simple_fk_kwargs['version']).resolve() simple_fk_kwargs['resolve_conflicts'] = simple_fk_resolved_conflicts form_simple_fk_resolved = self.build_bound_form(simple_fk_kwargs) self.assertTrue(form_simple_fk_resolved.is_valid()) form_simple_fk_resolved.save() self.assertEqual(SimpleFK.objects.count(), 1) self.assertEqual(SimpleNoAdmin.objects.count(), 1) self.assertEqual(self.simple_fk.simple_relation, SimpleFK.objects.get().simple_relation)
def compare_concepts(request, obj_type=None): comparison = {} item_a = request.GET.get('item_a', None) item_b = request.GET.get('item_b', None) context = {"item_a": item_a, "item_b": item_b} item_a = MDR._concept.objects.visible( request.user).filter(pk=item_a).first() # .item item_b = MDR._concept.objects.visible( request.user).filter(pk=item_b).first() # .item context = {"item_a": item_a, "item_b": item_b} request.GET = request.GET.copy() if item_a: item_a = item_a.item else: request.GET['item_a'] = "0" if item_b: item_b = item_b.item else: request.GET['item_b'] = "0" qs = MDR._concept.objects.visible(request.user) form = MDRForms.CompareConceptsForm(request.GET, user=request.user, qs=qs) # A form bound to the POST data if form.is_valid(): from django.contrib.contenttypes.models import ContentType revs = [] for item in [item_a, item_b]: versions = default_revision_manager.get_for_object(item) ct = ContentType.objects.get_for_model(item) version = reversion.models.Version.objects.filter( content_type=ct, object_id=item.pk).order_by('-revision__date_created').first() revs.append(version) if revs[0] is None: form.add_error( 'item_a', _('This item has no revisions. A comparison cannot be made')) if revs[1] is None: form.add_error( 'item_b', _('This item has no revisions. A comparison cannot be made')) if revs[0] is not None and revs[1] is not None: comparator_a_to_b = item_a.comparator() comparator_b_to_a = item_b.comparator() version1 = revs[0] version2 = revs[1] compare_data_a, has_unfollowed_fields_a = comparator_a_to_b.compare( item_a, version2, version1) compare_data_b, has_unfollowed_fields_b = comparator_b_to_a.compare( item_a, version1, version2) has_unfollowed = has_unfollowed_fields_a or has_unfollowed_fields_b context.update({'debug': {'cmp_a': compare_data_a}}) comparison = {} for field_diff_a in compare_data_a: name = field_diff_a['field'].name x = comparison.get(name, {}) x['field'] = field_diff_a['field'] x['a'] = field_diff_a['diff'] comparison[name] = x for field_diff_b in compare_data_b: name = field_diff_b['field'].name comparison.get(name, {})['b'] = field_diff_b['diff'] same = {} for f in item_a._meta.fields: if f.name not in comparison.keys(): same[f.name] = { 'field': f, 'value': getattr(item_a, f.name) } if f.name.startswith('_'): # hidden field comparison.pop(f.name, None) same.pop(f.name, None) hidden_fields = [ 'workgroup', 'created', 'modified', 'id', 'submitter', 'statuses' ] for h in hidden_fields: comparison.pop(h, None) same.pop(h, None) only_a = {} for f in item_a._meta.fields: if (f not in item_b._meta.fields and f not in comparison.keys() and f not in same.keys() and f.name not in hidden_fields): only_a[f.name] = { 'field': f, 'value': getattr(item_a, f.name) } only_b = {} for f in item_b._meta.fields: if (f not in item_a._meta.fields and f not in comparison.keys() and f not in same.keys() and f.name not in hidden_fields): only_b[f.name] = { 'field': f, 'value': getattr(item_b, f.name) } comparison = sorted(comparison.items()) context.update({ "comparison": comparison, "same": same, "only_a": only_a, "only_b": only_b, }) context.update({"form": form}) # comparison = {'a': compare_data_a, 'b': compare_data_b} return render(request, "aristotle_mdr/actions/compare/compare_items.html", context)
def test_recover_form_save(self): # test reverts object_version (no extras, simple object with # no translations, placeholders or fks form_simple_kwargs = self.build_form_kwargs(self.simple_no_admin) self.simple_no_admin.delete() self.assertEqual(SimpleNoAdmin.objects.count(), 0) form_simple = self.build_bound_form(form_simple_kwargs) self.assertTrue(form_simple.is_valid()) form_simple.save() self.assertEqual(SimpleNoAdmin.objects.count(), 1) # test reverts object and deleted placeholders with_placeholder_version = default_revision_manager.get_for_object( self.with_placeholder)[0] placeholder_pk = self.with_placeholder.content.pk self.with_placeholder.content.delete() # check that placeholder was actually deleted. self.assertEqual( Placeholder.objects.filter(pk=placeholder_pk).count(), 0) placeholder_versions = get_deleted_placeholders_for_object( self.with_placeholder, with_placeholder_version.revision) form_with_placeholders_kwargs = self.build_form_kwargs( self.with_placeholder) self.with_placeholder.delete() self.assertEqual(WithPlaceholder.objects.count(), 0) form_with_placeholders_kwargs['placeholders'] = placeholder_versions form_with_placeholder = self.build_bound_form( form_with_placeholders_kwargs) self.assertTrue(form_with_placeholder.is_valid()) form_with_placeholder.save() self.assertEqual(WithPlaceholder.objects.count(), 1) # check that placeholder was restored self.assertEqual( Placeholder.objects.filter(pk=placeholder_pk).count(), 1) # test reverts object and translations form_translated_kwargs = self.build_form_kwargs(self.with_translation) self.with_translation.delete() self.assertEqual(WithTranslations.objects.count(), 0) self.assertEqual( self.with_translation.translations.count(), 0) form_with_translation = self.build_unbound_form(form_translated_kwargs) translations_pks = [tr[0] for tr in form_with_translation.fields[ 'translations'].choices] form_with_translation = self.form_class( {'translations': translations_pks}, **form_translated_kwargs) self.assertTrue(form_with_translation.is_valid()) form_with_translation.save() self.assertEqual(WithTranslations.objects.count(), 1) self.assertEqual(WithTranslations.objects.get().translations.count(), 2) self.assertEqual(self.with_translation.description, WithTranslations.objects.get().description) # test reverts object and conflicts simple_fk_kwargs = self.build_form_kwargs(self.simple_fk) SimpleNoAdmin.objects.get().delete() self.assertEqual(SimpleNoAdmin.objects.count(), 0) self.assertEqual(SimpleFK.objects.count(), 0) simple_fk_resolved_conflicts = RecursiveRevisionConflictResolver( simple_fk_kwargs['version']).resolve() simple_fk_kwargs['resolve_conflicts'] = simple_fk_resolved_conflicts form_simple_fk_resolved = self.build_bound_form(simple_fk_kwargs) self.assertTrue(form_simple_fk_resolved.is_valid()) form_simple_fk_resolved.save() self.assertEqual(SimpleFK.objects.count(), 1) self.assertEqual(SimpleNoAdmin.objects.count(), 1) self.assertEqual(self.simple_fk.simple_relation, SimpleFK.objects.get().simple_relation)
def test_group_revisions_with_diverged_translations(self): rev_1_values_en = self.make_new_values( self.data_raw['group']['en'], 1) # rev 1: en 1 de 0 self.group1.set_current_language('en') self.create_revision(self.group1, **rev_1_values_en) self.assertEqual( len(default_revision_manager.get_for_object(self.group1)), 1) # check that values are actually changed self.assertEqual(self.group1.name, rev_1_values_en['name']) self.assertEqual( self.group1.description, rev_1_values_en['description']) # rev 2: en 1 de 1 rev_2_values_de = self.make_new_values( self.data_raw['group']['de'], 1) self.group1.set_current_language('de') self.create_revision(self.group1, **rev_2_values_de) self.assertEqual( len(default_revision_manager.get_for_object(self.group1)), 2) # check that values are actually changed self.group1 = Group.objects.get(pk=self.group1.pk) self.group1.set_current_language('de') self.assertEqual(self.group1.name, rev_2_values_de['name']) self.assertEqual( self.group1.description, rev_2_values_de['description']) # rev 3: en 1 de 2 rev_3_values_de = self.make_new_values( self.data_raw['group']['de'], 1) self.group1.set_current_language('de') self.create_revision(self.group1, **rev_3_values_de) self.assertEqual( len(default_revision_manager.get_for_object(self.group1)), 3) # check that values are actually changed self.group1 = Group.objects.get(pk=self.group1.pk) self.group1.set_current_language('de') self.assertEqual(self.group1.name, rev_3_values_de['name']) self.assertEqual( self.group1.description, rev_3_values_de['description']) # check that en values are left the same self.group1.set_current_language('en') self.assertEqual(self.group1.name, rev_1_values_en['name']) self.assertEqual( self.group1.description, rev_1_values_en['description']) # revert to rev2 en 1 de 1 self.revert_to(self.group1, 2) self.group1 = Group.objects.get(pk=self.group1.pk) # check previous values for en self.group1.set_current_language('en') self.assertEqual( self.group1.name, rev_1_values_en['name']) self.assertEqual( self.group1.description, rev_1_values_en['description']) # check previous values for de self.group1.set_current_language('de') self.assertEqual( self.group1.name, rev_2_values_de['name']) self.assertEqual( self.group1.description, rev_2_values_de['description'])
def revert_to(self, article, revision): (default_revision_manager.get_for_object(article)[revision] .revision.revert())