def setUp(self): super(AuthenticationAPITests, self).setUp() # Create the edit user and add it to the authenticated group self.edit_user = User( username="******", email="*****@*****.**", password="******") self.edit_user.save() all_group, created = Group.objects.get_or_create(name=settings.USERS_DEFAULT_GROUP) self.edit_user.groups.add(all_group) self.edit_user.save() # Create auth token for the edit user self.token = Token.objects.get_or_create(user=self.edit_user)[0] self.sf_region = Region(full_name='San Francisco', slug='sf') self.sf_region.save() p = Page(region=self.sf_region) p.content = '<p>Dolores Park here</p>' p.name = 'Dolores Park' p.save() self.dolores_park = p p = Page(region=self.sf_region) p.content = '<p>Duboce Park here</p>' p.name = 'Duboce Park' p.save() self.duboce_park = p
def import_page(mw_p): from pages.models import Page, slugify print "Importing %s" % mw_p.title.encode('utf-8') parsed = parse_page(mw_p.title) html = parsed['html'] name = fix_pagename(mw_p.title) if Page.objects.filter(slug=slugify(name)).exists(): print "Page %s already exists" % name.encode('utf-8') # Page already exists with this slug. This is probably because # MediaWiki has case-sensitive pagenames. other_page = Page.objects.get(slug=slugify(name)) if len(html) > other_page.content: print "Clearing out other page..", other_page.name.encode('utf-8') # *This* page has more content. Let's use it instead. for other_page_version in other_page.versions.all(): other_page_version.delete() other_page.delete(track_changes=False) else: # Other page has more content. return if mw_p.title.startswith('Category:'): # include list of tagged pages include_html = ( '<a href="tags/%(quoted_tag)s" ' 'class="plugin includetag includepage_showtitle">' 'List of pages tagged "%(tag)s"' '</a>' % { 'quoted_tag': urllib.quote(name), 'tag': name, } ) html += include_html p = Page(name=name, content=html) p.content = process_html(p.content, pagename=p.name, templates=parsed['templates'], mw_page_id=mw_p.pageid, historic=False) if not (p.content.strip()): p.content = '<p> </p>' # page content can't be blank p.clean_fields() try: p.save(track_changes=False) except IntegrityError: connection.close() try: create_page_revisions(p, mw_p, parsed) except KeyError: # For some reason the response lacks a revisions key # TODO: figure out why pass process_page_categories(p, parsed['categories'])
def test_include_plugin(self): a = Page(name='Front Page') a.content = '<a class="plugin includepage" href="Explore">dummy</a>' a.save() b = Page(name='Explore') b.content = '<p>Some text</p>' b.save() context = Context({'page': a}) template = Template(html_to_template_text(a.content, context)) html = template.render(context) self.assertEqual(html, '<div><p>Some text</p></div>')
def test_include_showtitle(self): a = Page(name='Front Page') a.content = ('<a class="plugin includepage includepage_showtitle"' ' href="Explore">dummy</a>') a.save() b = Page(name='Explore') b.content = '<p>Some text</p>' b.save() context = Context({'page': a}) template = Template(html_to_template_text(a.content, context)) html = template.render(context) self.assertEqual(html, ('<div><h2><a href="/Explore">Explore</a></h2>' '<p>Some text</p></div>'))
def test_include_plugin_utf8(self): a = Page(name='Front Page') a.content = (u'<a class="plugin includepage" ' u'href="青平台基金會">dummy</a>') a.save() b = Page(name=u'青平台基金會') b.content = u'<p>青平台基金會</p>' b.save() context = Context({'page': a}) template = Template(html_to_template_text(a.content, context)) html = template.render(context) self.assertEqual(html, u'<div class="included_page_wrapper">' u'<p>青平台基金會</p></div>')
def import_pages(): from pages.models import Page, slugify request = api.APIRequest(site, { 'action': 'query', 'list': 'allpages', 'aplimit': '50', }) print "Getting master page list (this may take a bit).." response_list = request.query(querycontinue=False)['query']['allpages'] pages = pagelist.listFromQuery(site, response_list) print "Got master page list." for mw_p in pages[:100]: print "Importing %s" % mw_p.title wikitext = mw_p.getWikiText() if mw_p.isRedir(): add_redirect(mw_p) continue html = render_wikitext(mw_p.title, wikitext) if Page.objects.filter(slug=slugify(mw_p.title)): # Page already exists with this slug. This is probably because # MediaWiki has case-sensitive pagenames. other_page = Page.objects.get(slug=slugify(mw_p.title)) if len(html) > other_page.content: # *This* page has more content. Let's use it instead. for other_page_version in other_page.versions.all(): other_page_version.delete() other_page.delete(track_changes=False) p = Page(name=mw_p.title, content=html) p.content = process_html(p.content, p.name) p.clean_fields() p.save()
def commit_items(self, response_dict): """ Accepts a dict like this: {"items":[{"id":18697,"siteId":8162,"roleId":-1,"name":"Annual Report 2007 ...}],"totalItemsCount":1010,"skip":0,"limit":10} :param response_dict: dict of items :return: """ for item in response_dict['items']: try: p = Page.objects.get(page_id=item.get('id')) except Page.DoesNotExist: p = Page() exp_date = item.get('expiryDate') exp_date = datetime.datetime.strptime( exp_date.split('T')[0], '%Y-%m-%d') p.name = item.get('name') p.url = item.get('pageUrl') p.enabled = item.get('enabled') p.expires = exp_date p.page_id = item.get('id') p.content = item.get('content') p.title = item.get('title') p.template_id = item.get('templateId') p.seo_description = item.get('seoMetadataDescription') p.save()
def test_include_width(self): a = Page(name='Front Page') a.content = ('<a class="plugin includepage" style="width: 100px"' ' href="Explore">dummy</a>') a.save() b = Page(name='Explore') b.content = '<p>Some text</p>' b.save() context = Context({'page': a}) template = Template(html_to_template_text(a.content, context)) html = template.render(context) self.assertEqual(html, ('<div class="included_page_wrapper" style="width: 100px;">' '<p>Some text</p></div>'))
def handle(self, *args, **options): if len(args) < 1: self.stderr.write('Please provide a directory containing the files '+ 'relative to PROJECT_DIR.') textbook_dir = os.path.join(settings.PROJECT_DIR, '..', args[0]) listing = os.listdir( textbook_dir ) # Iterate over all of the folders. for folder in listing: page_listing = os.listdir( os.path.join(textbook_dir, folder) ) for md in [f for f in page_listing if f.endswith(".md")]: try: data = "" f = open(os.path.join(textbook_dir, folder, md)) data = f.read() slug = md[:-3] f.close() # Now try to make a page Model. try: page = Page.objects.get(name=slug) except: page = Page(name=slug) page.content = data page.save() self.stdout.write('Wrote textbook page: %s\n'%md) except: self.stderr.write('Skipped textbook page: %s\n'%md) self.stdout.write('Successfully compiled textbook pages\n')
def handle(self, *args, **options): for fp in FlatPage.objects.all(): try: p = Page.objects.get(path=fp.url) print "%s already exists" % fp.url except Page.DoesNotExist: p = Page() p.path = fp.url p.title = fp.title p.content = fp.content p.content.markup_type = 'markdown' p.template = self.get_template(fp.template_name) p.is_published = True p.save() print "saved %s" % fp.url
def test_merge_conflict(self): p = Page() p.content = '<p>old content</p>' p.name = 'Front Page' p.save() a = PageForm(instance=p) b = PageForm(instance=p) b_post = b.initial b_post['content'] = '<p>b content</p>' b = PageForm(b_post, instance=p) self.failUnless(b.is_valid()) b.save() p = Page.objects.get(pk=p.pk) a_post = a.initial a_post['content'] = '<p>a content</p>' a = PageForm(a_post, instance=p) self.failIf(a.is_valid()) self.failUnless(PageForm.conflict_error in str(a.errors)) a_post = a.data a = PageForm(a_post, instance=p) self.failUnless(a.is_valid()) a.save() p = Page.objects.get(pk=p.pk) self.failUnless('Edit conflict!' in p.content)
def create_mw_template_as_page(template_name, template_html): """ Create a page to hold the rendered template. Returns: String representing the pagename of the new include-able page. """ from pages.models import Page, slugify robot = get_robot_user() name_part = template_name[len('Template:'):] # Keeping it simple for now. We can namespace later if people want that. include_name = name_part if not Page.objects.filter(slug=slugify(include_name)): mw_page = page.Page(site, title=template_name) p = Page(name=include_name) p.content = process_html(template_html, pagename=template_name, mw_page_id=mw_page.pageid, attach_img_to_pagename=include_name, show_img_borders=False) p.clean_fields() # check if it exists again, processing takes time if not Page.objects.filter(slug=slugify(include_name)): p.save(user=robot, comment="Automated edit. Creating included page.") return include_name
def test_double_include(self): """ Multiple includes are ok """ a = Page(name='Front Page') a.content = ('<a class="plugin includepage" href="Explore">dummy</a>' '<a class="plugin includepage" href="Explore">dummy</a>') a.save() b = Page(name='Explore') b.content = '<p>Some text</p>' b.save() context = Context({'page': a}) template = Template(html_to_template_text(a.content, context)) html = template.render(context) self.assertEqual(html, ('<div class="included_page_wrapper"><p>Some text</p></div>' '<div class="included_page_wrapper"><p>Some text</p></div>'))
def test_endless_include(self): """ Should detect endless loops and give an error message """ a = Page(name='Front Page') a.content = '<a class="plugin includepage" href="Front_Page">dummy</a>' a.save() context = Context({'page': a}) template = Template(html_to_template_text(a.content, context)) html = template.render(context) self.failUnless(('Unable to include <a href="/Front_Page">Front Page' '</a>: endless include loop') in html)
def test_include_nonexistant(self): """ Should give an error message when including nonexistant page """ a = Page(name='Front Page') a.content = '<a class="plugin includepage" href="New page">dummy</a>' a.save() context = Context({'page': a}) template = Template(html_to_template_text(a.content, context)) html = template.render(context) self.failUnless(('Unable to include <a href="/New_page"' ' class="missing_link">New page</a>') in html)
def test_move_exists(self): ########################################################### # Moving a page that already exists should just silently # continue. ########################################################### p_sf = Page(region=self.sf) p_sf.content = "<p>Hello, world in SF.</p>" p_sf.name = "Page A" p_sf.save() p_oak = Page(region=self.oak) p_oak.content = "<p>Hello, world started on Oak.</p>" p_oak.name = "Page A" p_oak.save() move_to_region(self.sf, pages=[p_sf]) # Shouldn't have been moved. p = Page.objects.filter(region=self.sf, name="Page A")[0] self.assertEqual(p.content, "<p>Hello, world in SF.</p>")
def test_move_redirects(self): p = Page(region=self.sf) p.content = "<p>A page.</p>" p.name = "Page content" p.save() redir = Redirect( source="short name", destination=p, region=self.sf) redir.save() move_to_region(self.oak, pages=[p], redirects=[redir]) # Redirect should be in Oak self.assertEqual(Redirect.objects.filter(region=self.oak).count(), 1)
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_redirect_destination(self): # Destination page should be transparently moved if not specified p = Page(region=self.sf) p.content = "<p>A page.</p>" p.name = "Page content not moved directly" p.save() redir = Redirect( source="short name", destination=p, region=self.sf) redir.save() move_to_region(self.oak, redirects=[redir]) # Redirect should be in Oak self.assertEqual(Redirect.objects.filter(region=self.oak).count(), 1) # ..and page self.assertTrue(Page.objects.filter(slug='page content not moved directly', region=self.oak).exists())
def test_move_with_links(self): from links.models import Link other = Page( name="otherexists", content="<p>blah</p>", region=self.sf ) other.save() p = Page(region=self.sf) p.content = '<p>A page <a href="otherexists">other</a> and <a href="otherdoesnotexist">other</a>.</p>' p.name = "Base page" p.save() move_to_region(self.oak, pages=[p]) links = Link.objects.filter(source__slug='base page') self.assertEqual(len(links), 2) for link in links: self.assertEqual(link.source.region, self.oak) self.assertEqual(link.destination, None) self.assertEqual(link.region, self.oak)
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 create_page_revisions(p, mw_p, parsed_page): from django.contrib.auth.models import User from pages.models import Page, slugify request = api.APIRequest(site, { 'action': 'query', 'prop': 'revisions', 'rvprop': 'ids|timestamp|user|comment', 'rvlimit': '500', 'titles': mw_p.title, }) response_pages = request.query()['query']['pages'] first_pageid = response_pages.keys()[0] rev_num = 0 total_revs = len(response_pages[first_pageid]['revisions']) for revision in response_pages[first_pageid]['revisions']: rev_num += 1 if rev_num == total_revs: history_type = 0 # Added else: history_type = 1 # Updated history_comment = revision.get('comment', None) if history_comment: history_comment = history_comment[:200] username = revision.get('user', None) user = User.objects.filter(username=username) if user: user = user[0] history_user_id = user.id else: history_user_id = None history_user_ip = None # MW offers no way to get this via API timestamp = revision.get('timestamp', None) history_date = date_parse(timestamp) revid = revision.get('revid', None) if rev_num == 1: # latest revision is same as page parsed = parsed_page else: parsed = parse_revision(revid) html = parsed['html'] # Create a dummy Page object to get the correct cleaning behavior dummy_p = Page(name=p.name, content=html) dummy_p.content = process_html(dummy_p.content, pagename=p.name, templates=parsed['templates'], mw_page_id=mw_p.pageid, historic=True) if not (dummy_p.content.strip()): dummy_p.content = '<p></p>' # Can't be blank dummy_p.clean_fields() html = dummy_p.content p_h = Page.versions.model( id=p.id, name=p.name, slug=slugify(p.name), content=html, history_comment=history_comment, history_date=history_date, history_type=history_type, history_user_id=history_user_id, history_user_ip=history_user_ip ) try: p_h.save() except IntegrityError: connection.close() print "Imported historical page %s" % p.name.encode('utf-8')
def populate_region(region): Page( name="Templates", slug="templates", # Translators: Please fix the links here to point to "社區," "避難收容處所", "設備物資集結點", "Restaurant" as translated in your language. But leave the "Templates/" part of the page link. "Templates/" in a URL is currently hard-coded and must remain in English for now. content=_(u"""<p> Templates are special pages that serve as a starting point when creating a new page. Using a common template for related topics gives those pages a common structure. To use one of the templates, simply select the template when creating a new page. </p> <p> Below is a list of the available templates. To add a new template, create a page whose title starts with "Templates/", as in <a href="Templates%2FBusiness">Templates/Business</a>. When you create a new template, add it to this list so it's easier to find.</p> <h3> <span>List of templates</span></h3> <ul> <li> <a href="Templates%2F社區">Templates/社區</a></li> <li> <a href="Templates%2F避難收容處所">Templates/避難收容處所</a></li> <li> <a href="Templates%2F設備物資集結點">Templates/設備物資集結點</a></li> <li> <a href="Templates%2F土石流保全對象">Templates/土石流保全對象</a></li> <li> <a href="Templates%2F水災保全對象">Templates/水災保全對象</a></li> <li> <a href="Templates%2F特殊需求機構">Templates/特殊需求機構</a></li> <li> <a href="Templates%2F重要維生設施">Templates/重要維生設施</a></li> <li> <a href="Templates%2F緊急聯絡網">Templates/緊急聯絡網</a></li> <li> <a href="Templates%2F環境不安全點">Templates/環境不安全點</a></li> <li> <a href="Templates%2FDisambiguation">Templates/Disambiguation</a></li> </ul>"""), region=region ).save() # Translators: This is for "Templates/Page" - a template page template_type = u"社區" Page( name="Templates/%s" % template_type, slug="templates/%s" % slugify(template_type), content=_(u"""<table> <tbody> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>人口數</strong></td> </tr> <tr> <td>{{人口數}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>鄰近地形</strong></td> </tr> <tr> <td>{{鄰近地形}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>歷史災害</strong></td> </tr> <tr> <td>{{歷史災害}}</td> </tr> </tbody> </table>"""), region=region ).save() # Translators: This is for "Templates/避難收容處所" - a template page template_type = u"避難收容處所" Page( name="Templates/%s" % template_type, slug="templates/%s" % slugify(template_type), content=_(u""" <table> <tbody> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>名稱</strong></td> </tr> <tr> <td>{{名稱}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>地址</strong></td> </tr> <tr> <td>{{地址}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>適用災別</strong></td> </tr> <tr> <td>{{適用災別}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>容納人數</strong></td> </tr> <tr> <td>{{容納人數}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>面積</strong></td> </tr> <tr> <td>{{面積}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>聯絡人</strong></td> </tr> <tr> <td>{{聯絡人}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>電話</strong></td> </tr> <tr> <td>{{電話}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>設備</strong></td> </tr> <tr> <td>{{設備}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>官方/非官方</strong></td> </tr> <tr> <td>{{官方}}</td> </tr> </tbody> </table>"""), region=region ).save() # Translators: This is for "Templates/設備物資集結點" - a template page template_type = u"設備物資集結點" Page( name="Templates/%s" % template_type, slug="templates/%s" % slugify(template_type), content=_(u""" <table> <tbody> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>名稱</strong></td> </tr> <tr> <td>{{名稱}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>地址</strong></td> </tr> <tr> <td>{{地址}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>項目與數量</strong></td> </tr> <tr> <td>{{項目與數量}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>聯絡人</strong></td> </tr> <tr> <td>{{聯絡人}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>電話</strong></td> </tr> <tr> <td>{{電話}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>官方/非官方</strong></td> </tr> <tr> <td>{{官方}}</td> </tr> </tbody> </table>"""), region=region ).save() # Translators: This is for "Templates/土石流保全對象" - a template page template_type = u"土石流保全對象" Page( name="Templates/%s" % template_type, slug="templates/%s" % slugify(template_type), content=_(u""" <table> <tbody> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>災害類型</strong></td> </tr> <tr> <td>{{災害類型}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>人數</strong></td> </tr> <tr> <td>{{人數}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>上傳日期</strong></td> </tr> <tr> <td>{{上傳日期}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>官方/非官方</strong></td> </tr> <tr> <td>{{官方}}</td> </tr> </tbody> </table>"""), region=region ).save() # Translators: This is for "Templates/水災保全對象" - a template page template_type = u"水災保全對象" Page( name="Templates/%s" % template_type, slug="templates/%s" % slugify(template_type), content=_(u""" <table> <tbody> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>人數</strong></td> </tr> <tr> <td>{{人數}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>上傳日期</strong></td> </tr> <tr> <td>{{上傳日期}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>官方/非官方</strong></td> </tr> <tr> <td>{{官方}}</td> </tr> </tbody> </table>"""), region=region ).save() # Translators: This is for "Templates/特殊需求機構" - a template page template_type = u"特殊需求機構" Page( name="Templates/%s" % template_type, slug="templates/%s" % slugify(template_type), content=_(u""" <table> <tbody> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>名稱</strong></td> </tr> <tr> <td>{{名稱}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>地址</strong></td> </tr> <tr> <td>{{地址}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>聯絡人</strong></td> </tr> <tr> <td>{{聯絡人}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>電話</strong></td> </tr> <tr> <td>{{電話}}</td> </tr> </tbody> </table>"""), region=region ).save() # Translators: This is for "Templates/重要維生設施" - a template page template_type = u"重要維生設施" Page( name="Templates/%s" % template_type, slug="templates/%s" % slugify(template_type), content=_(u""" <table> <tbody> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>名稱</strong></td> </tr> <tr> <td>{{名稱}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>地址</strong></td> </tr> <tr> <td>{{地址}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>座標</strong></td> </tr> <tr> <td>{{座標}}</td> </tr> </tbody> </table>"""), region=region ).save() # Translators: This is for "Templates/緊急聯絡網" - a template page template_type = u"緊急聯絡網" Page( name="Templates/%s" % template_type, slug="templates/%s" % slugify(template_type), content=_(u""" <table> <tbody> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>名稱</strong></td> </tr> <tr> <td>{{名稱}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>電話</strong></td> </tr> <tr> <td>{{電話}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>地址</strong></td> </tr> <tr> <td>{{地址}}</td> </tr> </tbody> </table>"""), region=region ).save() # Translators: This is for "Templates/環境不安全點" - a template page template_type = u"環境不安全點" Page( name="Templates/%s" % template_type, slug="templates/%s" % slugify(template_type), content=_(u""" <table> <tbody> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>地址或位置</strong></td> </tr> <tr> <td>{{位置}}</td> </tr> <tr> <td style="background-color: rgb(232, 236, 239);"> <strong>狀況描述</strong></td> </tr> <tr> <td>{{狀況描述}}</td> </tr> </tbody> </table>"""), region=region ).save() # Translators: This is for "Templates/Disambiguation" - a template page template_type = _("Disambiguation") Page( name="Templates/%s" % template_type, slug="templates/%s" % slugify(template_type), content=_("""<p> This has multiple meanings. You are probably looking for information on one of the following:</p> <ul> <li> <a href="ItemOne">ItemOne</a> - A brief summary of ItemOne</li> <li> <a href="ItemTwo">ItemTwo</a> - A brief summary of ItemTwo</li> </ul> <p> </p> <p> This is a <em>disambiguation</em> page — a navigational aid which lists other pages that might otherwise share the same title. If an page link referred you here, you might want to go back and fix it to point directly to the intended page.</p>"""), region=region ).save() frontpage = Page( name="Front Page", slug="front page", content=(_("""<p> Welcome to the new LocalWiki region for %(region)s! There are currently just a handful of pages in it, to get you started. <p> Click on <strong>Explore</strong> at the top to see what's here now.</p> <p> You can edit this and any other page by clicking the <strong>Edit</strong> button.</p> <p>Need <strong>help</strong>? Please see the <a href="http://localwiki.net/main/Help">help page</a> on the <a href="http://localwiki.net/main/">LocalWiki Guide</a>!</p>""") % {'region': region.full_name}), region=region ) frontpage.content = (_("""<p> Welcome to the new LocalWiki region for %(region)s! Here are some information about this area. <h2>Environment</h2> <h2>Disaster Potential</h2> <h2>Historical Disasters</h2> """) % { 'region': region.full_name }) frontpage.save()
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 edit_page(request, slug=None): ''' Edits a blog entry or a web page (creates one if needed) ''' if is_authorized_user(): page = None if request.method == 'GET': if slug: try: page = memcache.get('/edit/%s/' % slug) # @UndefinedVariable if not page: key = ndb.Key(urlsafe=slug) page = key.get() p = page.to_dict() p['tags'] = ",".join(p['tags']) p['key'] = page.key.id() if p.get('published_at'): p.pop('published_at') form = PageForm(data=p) except: tb = traceback.format_exc() print tb raise Http404 else: form = PageForm(initial={'timestamp': int(time.time() * 1000)}) form.fields['blog'].initial = True if request.GET.get( 'type', False) else False else: # POST form = PageForm(data=request.POST, files=request.FILES) if form.data['save'] == 'delete': return delete_item(request, form) # else if form.is_valid(): d = form.cleaned_data if d['key']: # updating an existing entry key = ndb.Key('Page', d['key']) page = key.get() mem_key = page.get_request_path(d.get('blog')) memcache.delete(mem_key) # @UndefinedVariable memcache.delete(mem_key + "full") # @UndefinedVariable memcache.delete(mem_key + "mobile") # @UndefinedVariable else: page = Page() if d.get('link'): page.link = d['link'] else: page.link = create_link(d['title']) page.content = d['content'] page.title = d['title'] page.draft = d.get('draft', False) page.blog = d.get('blog', False) page.image = d['image'] page.timestamp = int(d['timestamp']) page.template = d.get('template') or 'blog-post.html' page.summary = d['summary'] or re.sub( '\s{2,}', ' ', strip_tags(d['content']))[0:300] page.published_at = datetime.datetime.utcfromtimestamp( int(d['timestamp']) / 1000) page.priority = d.get('priority', 1) tags = [] for tag in d['tags'].split(','): tags.append(tag.strip()) update_tag(tag.strip()) page.tags = tags page.put() if page.draft == False and page.blog == True: memcache.set('/', None) # @UndefinedVariable update_archive(page) if request.POST.get('save') == 'save and continue': # we need to deal with the eventual consistency problem. So the # page will be first pushed to the cache if we dont' do that we will see # incorrect or missing data memcache.set('/edit/%s/' % page.link, page) # @UndefinedVariable return HttpResponseRedirect('/edit/%s/' % page.link) else: if page.blog: return HttpResponseRedirect('/list/?type=blog') else: return HttpResponseRedirect('/list/') else: print form.errors return render(request, 'admin/edit-page.html', { 'form': form, 'page': page }) else: return HttpResponse("<a href='{}'>login</a>".format( users.create_login_url('/list/')))