def test_move_with_fks(self): ########################################################### # Moving should carry along files and FK'ed items that # point to it. ########################################################### p = Page(region=self.sf) p.content = "<p>A page with files and a map in SF.</p>" p.name = "Page With FKs" p.save() # Create a file that points at the page. pf = PageFile(file=ContentFile("foo"), name="file.txt", slug=p.slug, region=self.sf) pf.save() # Create a redirect that points at the page. redirect = Redirect(source="foobar", destination=p, region=self.sf) redirect.save() # Create a map that points at the page. points = GEOSGeometry("""MULTIPOINT (-122.4378964233400069 37.7971758820830033, -122.3929211425700032 37.7688207875790027, -122.3908612060599950 37.7883584775320003, -122.4056240844700056 37.8013807351830025, -122.4148937988299934 37.8002956347170027, -122.4183270263600036 37.8051784612779969)""") map = MapData(points=points, page=p, region=self.sf) map.save() # Add tags to page tagset = PageTagSet(page=p, region=self.sf) tagset.save() tag = Tag(name="tag1", region=self.sf) tag.save() tagset.tags.add(tag) move_to_region(self.oak, pages=[p]) # Check to see that the related objects were moved. p = Page.objects.get(name="Page With FKs", region=self.oak) self.assertEqual(len(MapData.objects.filter(page=p, region=self.oak)), 1) self.assertEqual(len(p.pagetagset.tags.all()), 1) self.assertEqual(len(Redirect.objects.filter(destination=p, region=self.oak)), 1) self.assertEqual(len(PageFile.objects.filter(slug=p.slug, region=self.oak)), 1) # Check to see that version history was moved as well self.assertEquals(p.versions.all().count(), 1) self.assertEqual(len(MapData.versions.filter(page=p, region=self.oak)), 1) for pts in p.pagetagset.tags.all(): self.assertEqual(pts.versions.all().count(), 1) self.assertEqual(len(Redirect.versions.filter(destination=p, region=self.oak)), 1) self.assertEqual(len(PageFile.versions.filter(slug=p.slug, region=self.oak)), 1) # ..and that the page is no longer in the SF region self.assertFalse(Page.objects.filter(region=self.sf, name="Page With FKs").exists())
def test_move_with_existing_file(self): p = Page(region=self.sf) p.content = "<p>A page w a file.</p>" p.name = "Page With File" p.save() # Create a file that points at the page. pf_sf = PageFile(name="file.txt", slug=p.slug, region=self.sf) pf_sf.file.save("file.txt", ContentFile("foo sf")) pf_sf.save() # Make the file already exist on oak pf_oak = PageFile(name="file.txt", slug=p.slug, region=self.oak) pf_oak.file.save("file.txt", ContentFile("foo oak")) pf_oak.save() move_to_region(self.oak, pages=[p]) # The file shouldn't have been moved because it already exists at the # destination. pf = PageFile.objects.get(slug=p.slug, region=self.oak) self.assertEqual(pf_oak.file.name, pf.file.name)
def test_page_rename(self): p = Page() p.content = "<p>The page content.</p>" p.name = "Original page" p.save() p.rename_to("New page") # Renamed-to page should exist. new_p = Page.objects.get(name="New page") # new_p should have the same content. self.assertEqual(new_p.content, p.content) # "Original page" should no longer exist. pgs = Page.objects.filter(name="Original page") self.assertEqual(len(pgs), 0) # and a redirect from "original page" to "New page" should exist. Redirect.objects.filter(source="original page", destination=new_p) ########################################################### # Renaming to a page that already exists should raise an # exception and not affect the original page. ########################################################### p = Page() p.content = "<p>Hello, world.</p>" p.name = "Page A" p.save() self.assertRaises(exceptions.PageExistsError, p.rename_to, "New page") # p should be unaffected. No redirect should be created. p = Page.objects.get(name="Page A") self.assertEqual(p.content, "<p>Hello, world.</p>") self.assertEqual(len(Redirect.objects.filter(source="page a")), 0) ########################################################### # Renaming should carry along files and FK'ed items that # point to it. ########################################################### p = Page() p.content = "<p>A page with files and a map.</p>" p.name = "Page With FKs" p.save() # Create a file that points at the page. pf = PageFile(file=ContentFile("foo"), name="file.txt", slug=p.slug) pf.save() # Create a redirect that points at the page. redirect = Redirect(source="foobar", destination=p) redirect.save() # Create a map that points at the page. points = GEOSGeometry("""MULTIPOINT (-122.4378964233400069 37.7971758820830033, -122.3929211425700032 37.7688207875790027, -122.3908612060599950 37.7883584775320003, -122.4056240844700056 37.8013807351830025, -122.4148937988299934 37.8002956347170027, -122.4183270263600036 37.8051784612779969)""") map = MapData(points=points, page=p) map.save() p.rename_to("New Page With FKs") new_p = Page.objects.get(name="New Page With FKs") self.assertEqual(len(MapData.objects.filter(page=new_p)), 1) # Two redirects: one we created explicitly and one that was # created during rename_to() self.assertEqual(len(Redirect.objects.filter(destination=new_p)), 2) self.assertEqual(len(PageFile.objects.filter(slug=new_p.slug)), 1) # Renaming should keep slugs pointed at old page /and/ copy # them to the new page. self.assertEqual(len(PageFile.objects.filter(slug=p.slug)), 1) ########################################################### # Renaming with multiple files. ########################################################### p = Page() p.content = "<p>A new page with multiple files.</p>" p.name = "Page with multiple files" p.save() # Create a file that points at the page. pf = PageFile(file=ContentFile("foo"), name="file.txt", slug=p.slug) pf.save() pf = PageFile(file=ContentFile("foo2"), name="file2.txt", slug=p.slug) pf.save() pf = PageFile(file=ContentFile("foo3"), name="file3.txt", slug=p.slug) pf.save() p.rename_to("A page with multiple files 2") p = Page.objects.get(name="A page with multiple files 2") self.assertEqual(len(PageFile.objects.filter(slug=p.slug)), 3) ########################################################### # Reverting a renamed page should be possible and should # restore files and FK'ed items that were pointed at the # original page. The renamed-to page should still exist # after the revert and should still have its own files and # FK'ed items pointed at it. ########################################################### p = Page(name="Page With FKs", slug="page with fks") # get the version right before it was deleted v_before_deleted = len(p.versions.all()) - 1 p_h = p.versions.as_of(version=v_before_deleted) p_h.revert_to() p = Page.objects.get(name="Page With FKs") self.assertEqual(len(MapData.objects.filter(page=p)), 1) self.assertEqual(len(PageFile.objects.filter(slug=p.slug)), 1) p2 = Page.objects.get(name="New Page With FKs") self.assertEqual(len(MapData.objects.filter(page=p2)), 1) self.assertEqual(len(PageFile.objects.filter(slug=p2.slug)), 1) self.assertEqual(len(Redirect.objects.filter(destination=p2)), 1) ########################################################### # Renaming a page and then renaming it back. ########################################################### # 1. Simple case p = Page(name="Page X", content="<p>Foobar</p>") p.save() p.rename_to("Page Y") self.assertEqual(len(Page.objects.filter(name="Page X")), 0) self.assertEqual(len(Page.objects.filter(name="Page Y")), 1) p_new = Page.objects.get(name="Page Y") p_new.rename_to("Page X") self.assertEqual(len(Page.objects.filter(name="Page X")), 1) self.assertEqual(len(Page.objects.filter(name="Page Y")), 0) # 2. If we have FKs pointed at the page this shouldn't be # totally f****d. p = Page(name="Page X2", content="<p>Foo X</p>") p.save() points = GEOSGeometry("""MULTIPOINT (-122.4378964233400069 37.7971758820830033, -122.3929211425700032 37.7688207875790027, -122.3908612060599950 37.7883584775320003, -122.4056240844700056 37.8013807351830025, -122.4148937988299934 37.8002956347170027, -122.4183270263600036 37.8051784612779969)""") map = MapData(points=points, page=p) map.save() # Create a file that points at the page. pf = PageFile(file=ContentFile("foooo"), name="file_foo.txt", slug=p.slug) pf.save() p.rename_to("Page Y2") p_new = Page.objects.get(name="Page Y2") # FK points at the page we renamed to. self.assertEqual(len(MapData.objects.filter(page=p_new)), 1) self.assertEqual(len(PageFile.objects.filter(slug=p_new.slug)), 1) # Now rename it back. p_new.rename_to("Page X2") p = Page.objects.get(name="Page X2") # After rename-back-to, FK points to the renamed-back-to page. self.assertEqual(len(MapData.objects.filter(page=p)), 1) self.assertEqual(len(PageFile.objects.filter(slug=p.slug)), 1) ########################################################### # Renaming a page but keeping the same slug ########################################################### p = Page(name="Foo A", content="<p>Foo A</p>") p.save() p.rename_to("FOO A") # Name has changed. self.assertEqual(len(Page.objects.filter(name="FOO A")), 1) # Has the same history, with a new entry for the name change. p = Page.objects.get(name="FOO A") p1, p0 = p.versions.all() self.assertEqual(p1.name, 'FOO A') self.assertEqual(p0.name, 'Foo A') self.assertEqual(p0.content, p1.content) ########################################################### # Renaming a page twice (A -> B -> C) and then revert A to # an existing state. ########################################################### p = Page(name="Bar A", content="<p>Bar A</p>") p.save() p.rename_to("Bar B") p = Page.objects.get(name="Bar B") p.rename_to("Bar C") p = Page(name="Bar A", slug="bar a") p_h = p.versions.as_of(version=1) p_h.revert_to() ########################################################### # Renaming a page back and forth and reverting. ########################################################### p = Page(name="Zoo A", content="<p>Zoo A</p>") p.save() p.rename_to("Zoo B") p = Page.objects.get(name="Zoo B") p.rename_to("Zoo A") p = Page.objects.get(name="Zoo A") p.rename_to("Zoo B") p = Page(name="Zoo A", slug="zoo a") p_h = p.versions.as_of(version=1) p_h.revert_to() ########################################################### # page A, rename to B, then create new A, rename B to C, # rename C to B, then revert C to first version ########################################################### p = Page(name="Mike A", content="<p>A</p>") p.save() p.rename_to("Mike B") new_a = Page(name="Mike A", content="<p>A new</p>") new_a.save() p = Page.objects.get(name="Mike B") p.rename_to("Mike C") p = Page.objects.get(name="Mike C") p.rename_to("Mike B") p_c = Page(name="Mike C", slug="mike c") p_h = p_c.versions.as_of(version=1) p_h.revert_to()
def test_page_rename(self): p = Page() p.content = "<p>The page content.</p>" p.name = "Original page" p.save() p.rename_to("New page") # Renamed-to page should exist. new_p = Page.objects.get(name="New page") # new_p should have the same content. self.assertEqual(new_p.content, p.content) # "Original page" should no longer exist. pgs = Page.objects.filter(name="Original page") self.assertEqual(len(pgs), 0) # and a redirect from "original page" to "New page" should exist. Redirect.objects.filter(source="original page", destination=new_p) ########################################################### # Renaming to a page that already exists should raise an # exception and not affect the original page. ########################################################### p = Page() p.content = "<p>Hello, world.</p>" p.name = "Page A" p.save() self.assertRaises(exceptions.PageExistsError, p.rename_to, "New page") # p should be unaffected. No redirect should be created. p = Page.objects.get(name="Page A") self.assertEqual(p.content, "<p>Hello, world.</p>") self.assertEqual(len(Redirect.objects.filter(source="page a")), 0) ########################################################### # Renaming should carry along files and FK'ed items that # point to it. ########################################################### p = Page() p.content = "<p>A page with files and tags</p>" p.name = "Page With FKs" p.save() # Create a file that points at the page. pf = PageFile(file=ContentFile("foo"), name="file.txt", slug=p.slug) pf.save() # Create a redirect that points at the page. redirect = Redirect(source="foobar", destination=p) redirect.save() # Add tags to page tagset = PageTagSet(page=p) tagset.save() tag = Tag(name="tag1") tag.save() tagset.tags.add(tag) p.rename_to("New Page With FKs") new_p = Page.objects.get(name="New Page With FKs") self.assertEqual(len(new_p.pagetagset.tags.all()), 1) # Two redirects: one we created explicitly and one that was # created during rename_to() self.assertEqual(len(Redirect.objects.filter(destination=new_p)), 2) self.assertEqual(len(PageFile.objects.filter(slug=new_p.slug)), 1) # Renaming should keep slugs pointed at old page /and/ copy # them to the new page. self.assertEqual(len(PageFile.objects.filter(slug=p.slug)), 1) ########################################################### # Renaming with multiple files. ########################################################### p = Page() p.content = "<p>A new page with multiple files.</p>" p.name = "Page with multiple files" p.save() # Create a file that points at the page. pf = PageFile(file=ContentFile("foo"), name="file.txt", slug=p.slug) pf.save() pf = PageFile(file=ContentFile("foo2"), name="file2.txt", slug=p.slug) pf.save() pf = PageFile(file=ContentFile("foo3"), name="file3.txt", slug=p.slug) pf.save() p.rename_to("A page with multiple files 2") p = Page.objects.get(name="A page with multiple files 2") self.assertEqual(len(PageFile.objects.filter(slug=p.slug)), 3) ########################################################### # Reverting a renamed page should be possible and should # restore files and FK'ed items that were pointed at the # original page. The renamed-to page should still exist # after the revert and should still have its own files and # FK'ed items pointed at it. ########################################################### p = Page(name="Page With FKs", slug="page with fks") # get the version right before it was deleted v_before_deleted = len(p.versions.all()) - 1 p_h = p.versions.as_of(version=v_before_deleted) p_h.revert_to() p = Page.objects.get(name="Page With FKs") self.assertEqual(len(PageFile.objects.filter(slug=p.slug)), 1) p2 = Page.objects.get(name="New Page With FKs") self.assertEqual(len(PageFile.objects.filter(slug=p2.slug)), 1) self.assertEqual(len(Redirect.objects.filter(destination=p2)), 1) ########################################################### # Renaming a page and then renaming it back. ########################################################### # 1. Simple case p = Page(name="Page X", content="<p>Foobar</p>") p.save() p.rename_to("Page Y") self.assertEqual(len(Page.objects.filter(name="Page X")), 0) self.assertEqual(len(Page.objects.filter(name="Page Y")), 1) p_new = Page.objects.get(name="Page Y") p_new.rename_to("Page X") self.assertEqual(len(Page.objects.filter(name="Page X")), 1) self.assertEqual(len(Page.objects.filter(name="Page Y")), 0) # 2. If we have FKs pointed at the page this shouldn't be # totally f****d. p = Page(name="Page X2", content="<p>Foo X</p>") p.save() # Create a file that points at the page. pf = PageFile(file=ContentFile("foooo"), name="file_foo.txt", slug=p.slug) pf.save() p.rename_to("Page Y2") p_new = Page.objects.get(name="Page Y2") # FK points at the page we renamed to. self.assertEqual(len(PageFile.objects.filter(slug=p_new.slug)), 1) # Now rename it back. p_new.rename_to("Page X2") p = Page.objects.get(name="Page X2") # After rename-back-to, FK points to the renamed-back-to page. self.assertEqual(len(PageFile.objects.filter(slug=p.slug)), 1) ########################################################### # Renaming a page but keeping the same slug ########################################################### p = Page(name="Foo A", content="<p>Foo A</p>") p.save() p.rename_to("FOO A") # Name has changed. self.assertEqual(len(Page.objects.filter(name="FOO A")), 1) # Has the same history, with a new entry for the name change. p = Page.objects.get(name="FOO A") p1, p0 = p.versions.all() self.assertEqual(p1.name, 'FOO A') self.assertEqual(p0.name, 'Foo A') self.assertEqual(p0.content, p1.content) ########################################################### # Renaming a page twice (A -> B -> C) and then revert A to # an existing state. ########################################################### p = Page(name="Bar A", content="<p>Bar A</p>") p.save() p.rename_to("Bar B") p = Page.objects.get(name="Bar B") p.rename_to("Bar C") p = Page(name="Bar A", slug="bar a") p_h = p.versions.as_of(version=1) p_h.revert_to() ########################################################### # Renaming a page back and forth and reverting. ########################################################### p = Page(name="Zoo A", content="<p>Zoo A</p>") p.save() p.rename_to("Zoo B") p = Page.objects.get(name="Zoo B") p.rename_to("Zoo A") p = Page.objects.get(name="Zoo A") p.rename_to("Zoo B") p = Page(name="Zoo A", slug="zoo a") p_h = p.versions.as_of(version=1) p_h.revert_to() ########################################################### # page A, rename to B, then create new A, rename B to C, # rename C to B, then revert C to first version ########################################################### p = Page(name="Mike A", content="<p>A</p>") p.save() p.rename_to("Mike B") new_a = Page(name="Mike A", content="<p>A new</p>") new_a.save() p = Page.objects.get(name="Mike B") p.rename_to("Mike C") p = Page.objects.get(name="Mike C") p.rename_to("Mike B") p_c = Page(name="Mike C", slug="mike c") p_h = p_c.versions.as_of(version=1) p_h.revert_to()
def grab_images(tree, page_id, pagename, attach_to_pagename=None, show_image_borders=True): """ Imports the images on a page as PageFile objects and fixes the page's HTML to be what we want for images. """ from django.core.files.base import ContentFile from pages.models import slugify, PageFile robot = get_robot_user() # Get the list of images on this page params = { 'action': 'query', 'prop': 'images', 'imlimit': 500, 'pageids': page_id, } req = api.APIRequest(site, params) response = req.query() imagelist_by_pageid = response['query']['pages'] # We're processing one page at a time, so just grab the first. imagelist = imagelist_by_pageid[imagelist_by_pageid.keys()[0]] if not 'images' in imagelist: # Page doesn't have images. return tree images = imagelist['images'] for image_dict in images: image_title = image_dict['title'] filename = image_title[len('File:'):] # Get the image info for this image title try: image_info = get_image_info(image_title) except KeyError: # For some reason we can't get the image info. # TODO: Investigate this. continue image_url = image_info['url'] image_description_url = image_info['descriptionurl'] quoted_image_title = page_url_to_name(image_description_url) attach_to_pagename = attach_to_pagename or pagename if PageFile.objects.filter(name=filename, slug=slugify(attach_to_pagename)): continue # Image already exists. # For each image, find the image's supporting HTML in the tree # and transform it to comply with our HTML. html_before_fix = _convert_to_string(tree) tree = fix_image_html(image_title, quoted_image_title, filename, tree, border=show_image_borders ) if _convert_to_string(tree) == html_before_fix: # Image isn't actually on the page, so let's not create or attach # the PageFile. continue # Get the full-size image binary and store it in a string. img_ptr = urllib.URLopener() img_tmp_f = open(img_ptr.retrieve(image_url)[0], 'r') file_content = ContentFile(img_tmp_f.read()) img_tmp_f.close() img_ptr.close() # Create the PageFile and associate it with the current page. print "Creating image %s on page %s" % (filename.encode('utf-8'), pagename.encode('utf-8')) try: pfile = PageFile(name=filename, slug=slugify(attach_to_pagename)) pfile.file.save(filename, file_content, save=False) pfile.save(user=robot, comment="Automated edit. Creating file.") except IntegrityError: connection.close() return tree