def test_fix_tags(self): """ Test the `fix_tags` utility function. """ from pages.models import Page from tags.tag_utils import fix_tags ######################### # Create some test regions ######################### sf = Region(full_name="San Francisco Test", slug='sftest') sf.save() mission = Region(full_name="Mission", slug="mission") mission.save() ######################### # Create some test tags ######################### park = Tag(name='park', region=sf) park.save() fun = Tag(name='fun', region=sf) fun.save() ######################### # Add the tags to a test page ######################### page = Page(name="Duboce Park", content="<p>Park.</p>", region=sf) page.save() pts = PageTagSet( page=page, region=sf ) pts.save() pts.tags.add(park) pts.tags.add(fun) pts.save() # Now do something odd and make one of the referenced `Tag`s point # to a different region than the PageTagSet. fun.region = mission fun.save() self.assertTrue(pts.tags.filter(region=mission).exists()) # Then attempt a fix: fix_tags(sf, PageTagSet.objects.filter(id=pts.id)) pts = PageTagSet.objects.get(page=page, region=sf) self.assertFalse(pts.tags.filter(region=mission).exists()) # Check that this is fixed in historical versions as well for pts_h in pts.versions.all(): self.assertFalse(pts_h.tags.filter(region=mission).exists())
def move_to_region(region, pages=None, redirects=None): """ Move the provided `pages` and `redirects` to `region`, updating all related objects accordingly. """ from tags.models import PageTagSet from tags.tag_utils import fix_tags # XXX and TODO: right now this just rewrites the version history. When we're # versioning Regions we should make this do something like # p.save(comment="Moved region"), etc. pages = pages or [] redirects = redirects or [] for p in pages: if Page(slug=p.slug, region=region).exists(): # Page already exists in the new region, so let's # skip moving it. continue p._in_move = True clear_regenerable_dependencies(p) # Need to get these before moving the page itself. rel_objs = p._get_related_objs() slug_rel_objs = p._get_slug_related_objs() old_region = p.region update_region_for_instance(p, region) for _, rel_obj in rel_objs: if isinstance(rel_obj, list): for obj in rel_obj: update_region_for_instance(obj, region) else: update_region_for_instance(rel_obj, region) for info in slug_rel_objs: unique_together = info["unique_together"] # We need to check to see if these objects exist already. Unlike # normal related objects, by-slug related objs can persist # when a page is deleted. def _get_lookup(unique_together, obj, region): d = {} for field in unique_together: d[field] = getattr(obj, field) d['region'] = region return d for obj in info['objs']: obj_lookup = _get_lookup(unique_together, obj, region) if obj.__class__.objects.filter(**obj_lookup): # Already exists, so let's skip it. continue update_region_for_instance(obj, region) p._in_move = False fix_tags(region, pts_qs=PageTagSet.objects.filter(page=p)) # Save page to fire signals p.save(track_changes=False) for r in redirects: update_region_for_instance(r.destination, region) update_region_for_instance(r, region)