def delete_category(blog_id, category_id, confirm='N'): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_admin(user, blog) category = Category.load(category_id, blog_id=blog.id) auth.check_category_editing_lock(blog) tags = template_tags(blog=blog, user=user) from core.utils import Status if request.forms.getunicode('confirm') == user.logout_nonce: message = 'Category {} successfully deleted'.format(category.for_log) url = '{}/blog/{}/categories'.format(BASE_URL, blog.id) action = 'Return to the category listing' reparent_categories = Category.update( parent_category=category.parent_category).where( Category.parent_category == category) reparent_categories.execute() delete_category = PageCategory.delete().where( PageCategory.category == category.id) delete_category.execute() category.delete_instance() tags.status = Status(type='success', message=message, action=action, url=url, close=False) else: message = ( 'You are about to delete category <b>{}</b> from blog <b>{}</b>.'. format(category.for_display, blog.for_display)) yes = { 'label': 'Yes, delete this category', 'id': 'delete', 'name': 'confirm', 'value': user.logout_nonce } no = { 'label': 'No, return to category properties', 'url': '{}/blog/{}/category/{}'.format(BASE_URL, blog.id, category.id) } tags.status = Status(message=message, type='warning', close=False, yes=yes, no=no) tags.category = category return report(tags, 'blog_delete_category', category)
def blog_pages_in_category(blog_id, category_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_editor(user, blog) errormsg = auth.check_category_editing_lock(blog, True) from core.models import Category category = Category.load(category_id, blog_id=blog.id) return listing(request, category, category.pages, 'blog', 'blog_pages_in_category', user=user, errormsg=errormsg, search_ui='blog_pages_in_category', search_context=blog_pages_in_category_search_results, tags_data={'blog':blog} )
def blog_pages_in_category(blog_id, category_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_editor(user, blog) errormsg = auth.check_category_editing_lock(blog, True) from core.models import Category category = Category.load(category_id, blog_id=blog.id) return listing(request, category, category.pages, 'blog', 'blog_pages_in_category', user=user, errormsg=errormsg, search_ui='blog_pages_in_category', search_context=blog_pages_in_category_search_results, tags_data={'blog': blog})
def template_preview_core(template_id): ''' UI for generating a preview of a given template ''' from core.models import Page, FileInfo, page_status from core.cms import fileinfo from core.cms import invalidate_cache invalidate_cache() template = Template.load(template_id) # TODO: only rebuild mappings if the dirty bit is set if template.template_type == template_type.index: fi = template.default_mapping.fileinfos test_preview_mapping(fi.count(), template) fi = fi.get() tags = template_tags(blog=template.blog, template=template, fileinfo=fi) elif template.template_type == template_type.page: try: fi = Page.load(int(request.query['use_page'])).fileinfos[0] except (KeyError, TypeError): fi = template.fileinfos test_preview_mapping(fi.count(), template) fi = fi.select().join(Page).where( FileInfo.page == Page.id, Page.blog == template.blog, Page.status == page_status.published, ).order_by(Page.publication_date.desc()).get() tags = template_tags( template=template, page=fi.page, ) elif template.template_type == template_type.include: if template.publishing_mode != publishing_mode.ssi: from core.error import PreviewException raise PreviewException( 'You can only preview server-side includes.') page = template.blog.pages.published.order_by( Page.publication_date.desc()).get() fi = page.fileinfos[0] tags = template_tags( template=template, page=page, ) elif template.template_type == template_type.archive: if 'use_page' in request.query: page_list = [Page.load(int(request.query['use_page']))] elif 'use_category' in request.query: from core.models import Category page_list = Category.load(int( request.query['use_category'])).pages.published.limit(1) elif 'use_tag' in request.query: from core.models import Tag page_list = Tag.load(int( request.query['use_tag'])).pages.published.limit(1) else: page_list = template.blog.pages.published.limit(1) fi = fileinfo.build_archives_fileinfos_by_mappings(template, pages=page_list) test_preview_mapping(len(fi), template) fi = fi[0] archive_pages = fileinfo.generate_archive_context_from_fileinfo( fi.xref.archive_xref, template.blog.pages.published, fi) tags = template_tags(blog=template.blog, archive=archive_pages, archive_context=fi, fileinfo=fi, template=template) elif template.template_type in (template_type.media, template_type.system): from core.error import PreviewException raise PreviewException( 'Template {} is of a type that cannot yet be previewed.'.format( template.for_log)) import time from core.template import tplt tc = time.clock start = tc() tpl_output = tplt(template, tags) end = tc() tpl_output = r'<!-- Produced by template {}. Total render time:{} secs -->{}'.format( template.for_log, end - start, tpl_output) preview_file_path, preview_url = fi.make_preview() from core.cms import queue queue.write_file(tpl_output, template.blog.path, preview_file_path) return ("{}?_={}".format(preview_url, template.modified_date.microsecond))
def save_page(page, user, blog=None): ''' Saves edits to a page in the CMS. Note that this function does _not_ perform permission checking. In other words, it doesn't verify if the user described in the `user` parameter does in fact have permissions to edit the page in question. :param page: Page object whose data is to be saved. If this is None, then it is assumed that we are creating a new page. :param user: The user object associated with the save action for this page. If this is a newly-created page, the page's user will be set to this. :param blog: The blog object under which the page will be created, if this is a newly-created page. ''' getunicode = request.forms.getunicode # invalidate_cache() save_action = int(request.forms.get('save')) original_page_status = page_status.unpublished new_basename = getunicode('basename') if page is None: # CREATE NEW PAGE ENTRY page = Page() page.user = user.id page.blog = blog.id page.basename = create_basename(getunicode('page_title'), page.blog) original_page_basename = page.basename time_now = datetime.datetime.utcnow() page.publication_date = time_now page.created_date = time_now else: # UPDATE EXISTING ENTRY # Queue neighbor actions for page BEFORE modification if page.status == page_status.published: if not (save_action & save_action_list.UNPUBLISH_PAGE): queue_page_actions((page.next_page, page.previous_page),no_neighbors=True, no_archive=True) queue_page_archive_actions(page) original_page_status = page.status original_page_basename = page.basename page.modified_date = datetime.datetime.utcnow() change_basename = False if new_basename is not None: if new_basename == "": change_basename = True new_basename = create_basename(getunicode('page_title'), page.blog) if new_basename != original_page_basename: change_basename = True new_publication_date = datetime.datetime.strptime( request.forms.get('publication_date'), DATE_FORMAT) if change_basename: page.basename = create_basename(new_basename, page.blog) page.publication_date = page._date_to_utc(page.blog.timezone, new_publication_date).replace(tzinfo=None) page.title = getunicode('page_title') page.text = getunicode('page_text') page.status = page_status.modes[int(request.forms.get('publication_status'))] page.tag_text = getunicode('page_tag_text') page.excerpt = getunicode('page_excerpt') change_note = getunicode('change_note') msg = [] # UNPUBLISH if ( (save_action & save_action_list.UNPUBLISH_PAGE and page.status == page_status.published) or # unpublished a published page (original_page_status == page_status.published and page.status == page_status.unpublished) # set a published page to draft ): unpublish_page(page) msg.append("Page <b>{}</b> unpublished successfully.") # SET UNPUBLISHED TO PUBLISHED elif original_page_status == page_status.unpublished and (save_action & save_action_list.UPDATE_LIVE_PAGE): page.status = page_status.published msg.append("Set to publish.") # SAVE DRAFT if (save_action & save_action_list.SAVE_TO_DRAFT): try: save_result = page.save(user, False, False, change_note) except PageNotChanged: save_result = (None, None) msg.append("Page <b>{}</b> saved successfully.") # Assign categories for page categories = [] for n in request.forms.allitems(): if n[0][:8] == 'cat-sel-': try: category_id = int(n[0][8:]) except ValueError: category_id = None else: categories.append(category_id) if not categories: categories.append(blog.default_category.id) msg.append(" Default category auto-assigned for page.") page_categories = [] primary = None for n in page.categories: if n.category.id not in categories: delete_category = PageCategory.delete().where( PageCategory.id == n.id) delete_category.execute() else: page_categories.append(n.category.id) if n.primary is True: primary = n for n in categories: if n not in page_categories: new_page_category = PageCategory.create( page=page, category=Category.load(n, blog_id=page.blog.id), primary=False) if primary is None: n = page.categories[0] n.primary = True n.save() delete_page_fileinfo(page) build_archives_fileinfos((page,)) build_pages_fileinfos((page,)) # UPDATE TAGS if getunicode('tag_text') is not None: import json tag_text = json.loads(getunicode('tag_text')) add_tags_to_page(tag_text, page) delete_orphaned_tags(page.blog) # QUEUE CHANGES FOR PUBLICATION (if any) if ((save_action & save_action_list.UPDATE_LIVE_PAGE) and (page.status == page_status.published)): queue_ssi_actions(page.blog) queue_page_actions((page,)) queue_index_actions(page.blog) msg.append(" Live page updated.") # DETECT ANY PAGE CHANGES if ( (save_action & (save_action_list.SAVE_TO_DRAFT + save_action_list.UPDATE_LIVE_PAGE)) and (save_result[1]) is None): msg.append(" (Page unchanged.)") # RETURN REPORT tags = template_tags(page=page, user=user) status = Status( type='success', message=' / '.join(msg), vals=(page.for_log,) ) tags.status = status tags._save_action = save_action tags._save_action_list = save_action_list return tags
def delete_category(blog_id, category_id, confirm='N'): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_admin(user, blog) category = Category.load(category_id, blog_id=blog.id) auth.check_category_editing_lock(blog) tags = template_tags( blog=blog, user=user) from core.utils import Status if request.forms.getunicode('confirm') == user.logout_nonce: message = 'Category {} successfully deleted'.format( category.for_log) url = '{}/blog/{}/categories'.format(BASE_URL, blog.id) action = 'Return to the category listing' reparent_categories = Category.update( parent_category=category.parent_category).where( Category.parent_category == category) reparent_categories.execute() delete_category = PageCategory.delete().where( PageCategory.category == category.id) delete_category.execute() category.delete_instance() tags.status = Status( type='success', message=message, action=action, url=url, close=False) else: message = ('You are about to delete category <b>{}</b> from blog <b>{}</b>.'.format( category.for_display, blog.for_display)) yes = { 'label':'Yes, delete this category', 'id':'delete', 'name':'confirm', 'value':user.logout_nonce} no = { 'label':'No, return to category properties', 'url':'{}/blog/{}/category/{}'.format( BASE_URL, blog.id, category.id) } tags.status = Status( message=message, type='warning', close=False, yes=yes, no=no ) tags.category = category return report(tags, 'blog_delete_category', category)
def edit_category(blog_id, category_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_admin(user, blog) category = Category.load(category_id, blog_id=blog.id) auth.check_category_editing_lock(blog) category_list = [n for n in blog.categories] top_level_category = Category( id=None, title='[Top-level category]', parent=None ) category_list.insert(0, top_level_category) tags = template_tags( blog=blog, user=user) from core.utils import Status status = [] if request.method == "POST": new_category_title = request.forms.getunicode('category_title') old_category_title = category.title if new_category_title != old_category_title: category.title = new_category_title category.save() status.append( ['Category <b>{}</b> was renamed to <b>{}</b>.', [old_category_title, new_category_title]]) old_parent_category = category.parent_category try: new_parent_category = int(request.forms.getunicode('category_parent')) except ValueError: new_parent_category = None new_basename = request.forms.getunicode('category_basename') if category.basename != new_basename: category.basename = new_basename category.save() status.append(['Category basename was changed.', []]) if old_parent_category != new_parent_category: category.parent_category = new_parent_category category.save() if new_parent_category is not None: new_category = Category.load( category_id=new_parent_category, blog=blog) else: new_category = top_level_category status.append(['Category <b>{}</b> was reparented to <b>{}</b>.', [category.title, new_category.for_log]]) if request.forms.getunicode('default') == "Y": clear_default_categories = Category.update( default=False).where( Category.blog == blog, Category.default == True) clear_default_categories.execute() category.default = True category.save() status.append(['Category <b>{}</b> was set to default for blog <b>{}</b>.', [category.title, blog.for_log]]) if len(status) > 0: message = '' vals = [] for n in status: message += n[0] for m in n[1]: vals.append(m) vals.append('{}/blog/{}/purge'.format(BASE_URL, blog.id)) tags.status = Status(type='success', message=message + '<br/><a href="{}">Purge and republish this blog</a> to make these changes take effect.', vals=vals) # from core.ui_kv import kv_ui from core.ui import kv kv_ui_data = kv.ui(category.kv_list()) from core.ui import sidebar tags.sidebar = sidebar.render_sidebar( panel_set='edit_category', # status_badge=status_badge, kv_object='Category', kv_objectid=category.id, kv_ui=kv_ui_data) tpl = template('edit/category', category=category, category_list=category_list, menu=generate_menu('blog_edit_category', category), search_context=(search_contexts['sites'], None), **tags.__dict__) return tpl
def edit_category(blog_id, category_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_admin(user, blog) category = Category.load(category_id, blog_id=blog.id) auth.check_category_editing_lock(blog) category_list = [n for n in blog.categories] top_level_category = Category(id=None, title='[Top-level category]', parent=None) category_list.insert(0, top_level_category) tags = template_tags(blog=blog, user=user) from core.utils import Status status = [] if request.method == "POST": new_category_title = request.forms.getunicode('category_title') old_category_title = category.title if new_category_title != old_category_title: category.title = new_category_title category.save() status.append([ 'Category <b>{}</b> was renamed to <b>{}</b>.', [old_category_title, new_category_title] ]) old_parent_category = category.parent_category try: new_parent_category = int( request.forms.getunicode('category_parent')) except ValueError: new_parent_category = None new_basename = request.forms.getunicode('category_basename') if category.basename != new_basename: category.basename = new_basename category.save() status.append(['Category basename was changed.', []]) if old_parent_category != new_parent_category: category.parent_category = new_parent_category category.save() if new_parent_category is not None: new_category = Category.load(category_id=new_parent_category, blog=blog) else: new_category = top_level_category status.append([ 'Category <b>{}</b> was reparented to <b>{}</b>.', [category.title, new_category.for_log] ]) if request.forms.getunicode('default') == "Y": clear_default_categories = Category.update(default=False).where( Category.blog == blog, Category.default == True) clear_default_categories.execute() category.default = True category.save() status.append([ 'Category <b>{}</b> was set to default for blog <b>{}</b>.', [category.title, blog.for_log] ]) if len(status) > 0: message = '' vals = [] for n in status: message += n[0] for m in n[1]: vals.append(m) vals.append('{}/blog/{}/purge'.format(BASE_URL, blog.id)) tags.status = Status( type='success', message=message + '<br/><a href="{}">Purge and republish this blog</a> to make these changes take effect.', vals=vals) # from core.ui_kv import kv_ui from core.ui import kv kv_ui_data = kv.ui(category.kv_list()) from core.ui import sidebar tags.sidebar = sidebar.render_sidebar( panel_set='edit_category', # status_badge=status_badge, kv_object='Category', kv_objectid=category.id, kv_ui=kv_ui_data) tpl = template('edit/category', category=category, category_list=category_list, menu=generate_menu('blog_edit_category', category), search_context=(search_contexts['sites'], None), **tags.__dict__) return tpl
def save_page(page, user, blog=None): ''' Saves edits to a page in the CMS. Note that this function does _not_ perform permission checking. In other words, it doesn't verify if the user described in the `user` parameter does in fact have permissions to edit the page in question. :param page: Page object whose data is to be saved. If this is None, then it is assumed that we are creating a new page. :param user: The user object associated with the save action for this page. If this is a newly-created page, the page's user will be set to this. :param blog: The blog object under which the page will be created, if this is a newly-created page. ''' getunicode = request.forms.getunicode # invalidate_cache() save_action = int(request.forms.get('save')) original_page_status = page_status.unpublished new_basename = getunicode('basename') if page is None: # CREATE NEW PAGE ENTRY page = Page() page.user = user.id page.blog = blog.id page.basename = create_basename(getunicode('page_title'), page.blog) original_page_basename = page.basename time_now = datetime.datetime.utcnow() page.publication_date = time_now page.created_date = time_now else: # UPDATE EXISTING ENTRY # Queue neighbor actions for page BEFORE modification if page.status == page_status.published: if not (save_action & save_action_list.UNPUBLISH_PAGE): queue_page_actions((page.next_page, page.previous_page), no_neighbors=True, no_archive=True) queue_page_archive_actions(page) original_page_status = page.status original_page_basename = page.basename page.modified_date = datetime.datetime.utcnow() change_basename = False if new_basename is not None: if new_basename == "": change_basename = True new_basename = create_basename(getunicode('page_title'), page.blog) if new_basename != original_page_basename: change_basename = True new_publication_date = datetime.datetime.strptime( request.forms.get('publication_date'), DATE_FORMAT) if change_basename: page.basename = create_basename(new_basename, page.blog) page.publication_date = page._date_to_utc( page.blog.timezone, new_publication_date).replace(tzinfo=None) page.title = getunicode('page_title') page.text = getunicode('page_text') page.status = page_status.modes[int( request.forms.get('publication_status'))] page.tag_text = getunicode('page_tag_text') page.excerpt = getunicode('page_excerpt') change_note = getunicode('change_note') msg = [] # UNPUBLISH if ((save_action & save_action_list.UNPUBLISH_PAGE and page.status == page_status.published) or # unpublished a published page (original_page_status == page_status.published and page.status == page_status.unpublished ) # set a published page to draft ): unpublish_page(page) msg.append("Page <b>{}</b> unpublished successfully.") # SET UNPUBLISHED TO PUBLISHED elif original_page_status == page_status.unpublished and ( save_action & save_action_list.UPDATE_LIVE_PAGE): page.status = page_status.published msg.append("Set to publish.") # SAVE DRAFT if (save_action & save_action_list.SAVE_TO_DRAFT): try: save_result = page.save(user, False, False, change_note) except PageNotChanged: save_result = (None, None) msg.append("Page <b>{}</b> saved successfully.") # Assign categories for page categories = [] for n in request.forms.allitems(): if n[0][:8] == 'cat-sel-': try: category_id = int(n[0][8:]) except ValueError: category_id = None else: categories.append(category_id) if not categories: categories.append(blog.default_category.id) msg.append(" Default category auto-assigned for page.") page_categories = [] primary = None for n in page.categories: if n.category.id not in categories: delete_category = PageCategory.delete().where( PageCategory.id == n.id) delete_category.execute() else: page_categories.append(n.category.id) if n.primary is True: primary = n for n in categories: if n not in page_categories: new_page_category = PageCategory.create( page=page, category=Category.load(n, blog_id=page.blog.id), primary=False) if primary is None: n = page.categories[0] n.primary = True n.save() delete_page_fileinfo(page) build_archives_fileinfos((page, )) build_pages_fileinfos((page, )) # UPDATE TAGS if getunicode('tag_text') is not None: import json tag_text = json.loads(getunicode('tag_text')) add_tags_to_page(tag_text, page) delete_orphaned_tags(page.blog) # QUEUE CHANGES FOR PUBLICATION (if any) if ((save_action & save_action_list.UPDATE_LIVE_PAGE) and (page.status == page_status.published)): queue_ssi_actions(page.blog) queue_page_actions((page, )) queue_index_actions(page.blog) msg.append(" Live page updated.") # DETECT ANY PAGE CHANGES if ((save_action & (save_action_list.SAVE_TO_DRAFT + save_action_list.UPDATE_LIVE_PAGE)) and (save_result[1]) is None): msg.append(" (Page unchanged.)") # RETURN REPORT tags = template_tags(page=page, user=user) status = Status(type='success', message=' / '.join(msg), vals=(page.for_log, )) tags.status = status tags._save_action = save_action tags._save_action_list = save_action_list return tags
def blog_import(blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) reason = auth.check_template_lock(blog, True) tags = template_tags(blog=blog, user=user) import os, settings import_path = os.path.join(settings.APPLICATION_PATH, "data", "import.json") tags.status = reason if request.method == "POST": from core.models import db tpl = '' with db.atomic() as txn: import json from core.utils import string_to_date import_path = request.forms.getunicode('import_path') with open(import_path, 'r', encoding='utf8') as f: json_data = json.load(f) from core.models import page_status, MediaAssociation, Category from core.error import PageNotChanged from core.libs.peewee import InterfaceError from core.cms import media_filetypes format_str = "<b>{}</b> / (<i>{}</i>)" # TODO: go in chunks of 50 or something? # allow graceful disconnection? for n in json_data: q = [] n_id = n['id'] q.append("Checking {}".format(n_id)) changed = False found = False match = Page.kv_get('legacy_id', n_id) if match.count() > 0: if match[0].object_ref.blog == blog: found = True q.append(match[0].key + "/" + match[0].value + " / Exists: " + format_str.format(n['title'], n_id)) existing_entry = Page.load(match[0].objectid) update = existing_entry.kv_get('update').count() # raise Exception(update) q.append('{} / {}'.format( string_to_date( n['modified_date']).replace(tzinfo=None), existing_entry.modified_date)) if string_to_date(n['modified_date']).replace( tzinfo=None ) <= existing_entry.modified_date and update == 0: q.append('Existing page {} not changed.'.format( existing_entry.id)) else: changed = True q.append( 'Updating data for existing page {}.'.format( existing_entry.id)) existing_entry.title = n['title'] existing_entry.text = n['text'] existing_entry.basename = n['basename'] existing_entry.excerpt = n['excerpt'] existing_entry.created_date = string_to_date( n['created_date']).replace(tzinfo=None) existing_entry.modified_date = string_to_date( n['modified_date']).replace(tzinfo=None) existing_entry.publication_date = string_to_date( n['publication_date']).replace(tzinfo=None) try: existing_entry.save( user, False, False, 'New revision from import') except PageNotChanged: pass except InterfaceError: raise Exception( "Error saving {}. Check the JSON to make sure it's valid." .format(n_id)) for media in existing_entry.media: media.kv_del() existing_entry.clear_categories() existing_entry.clear_kvs() existing_entry.clear_tags() existing_entry.clear_media() entry = existing_entry if found is False: q.append("Creating: " + format_str.format(n['title'], n_id)) changed = True new_entry = Page( title=n['title'], text=n['text'], basename=n['basename'], excerpt=n['excerpt'], user=user, blog=blog, created_date=string_to_date(n['created_date']), publication_date=string_to_date(n['publication_date']), modified_date=string_to_date(n['modified_date']), ) new_entry.modified_date = new_entry.publication_date if n['status'] in ('Publish', 'Published', 'Live'): new_entry.status = page_status.published new_entry.save(user) entry = new_entry q.append("New ID: {}".format(entry.id)) # Everything from here on out is if changed: # Register a legacy ID for the page entry.kv_set("legacy_id", n["id"]) entry.kv_set("legacy_user", n["user_id"]) # Category assignments categories = n['categories'] if categories == []: saved_page_category = PageCategory.create( page=entry, category=blog.default_category, primary=True).save() else: primary = True for category in categories: cat_exists = False category_id = category['id'] existing_category = Category.kv_get( 'legacy_id', category_id) if existing_category.count() > 0: if existing_category[ 0].object_ref.blog == blog: cat_exists = True if cat_exists is False: q.append('Created new category {}/{}'.format( category_id, category['name'])) new_category = Category.create( blog=blog, title=category['name'], parent_category=getattr( category, 'parent', None)) new_category.save() new_category.kv_set('legacy_id', category_id) else: new_category = Category.load( existing_category[0].objectid) q.append( 'Added to existing category {}/{}'.format( new_category.id, category['name'])) saved_page_category = PageCategory.create( page=entry, category=new_category, primary=primary).save() primary = False # Check to make sure a default category exists for the whole blog. # If not, assign one based on the lowest ID. # This can always be reassigned later. # Register tags tags_added, tags_existing, _ = Tag.add_or_create( n['tags'], page=entry) q.append('Tags added: {}'.format(','.join( n.tag for n in tags_added))) q.append('Tags existing: {}'.format(','.join( n.tag for n in tags_existing))) # Register KVs kvs = n['kvs'] for key in kvs: if key != "": value = kvs[key] entry.kv_set(key, value) q.append('KV: {}:{}'.format(key, value)) # Register media media = n['media'] for m in media: if 'path' not in m: continue path = os.path.split(m['path']) try: new_media = Media.get(Media.url == m['url']) except: new_media = Media(filename=path[1], path=m['path'], url=m['url'], type=media_filetypes.image, created_date=string_to_date( m['created_date']), modified_date=string_to_date( m['modified_date']), friendly_name=m['friendly_name'], user=user, blog=blog, site=blog.site) # TODO: RBF try: new_media.save() except Exception: continue media_association = MediaAssociation(media=new_media, page=entry) media_association.save() # Save legacy ID to KV on media if 'id' in m: new_media.kv_set('legacy_id', m['id']) q.append('IMG: {}'.format(new_media.url)) # add tags for media q.append('Tags: {}'.format(m['tags'])) new_tags = Tag.add_or_create(m['tags'], media=new_media) kvs = m['kvs'] for key in kvs: value = kvs[key] new_media.kv_set(key, value) q.append('KV: {}:{}'.format(key, value)) fileinfo.build_pages_fileinfos((entry, )) fileinfo.build_archives_fileinfos((entry, )) tpl += ('<p>'.join(q)) + '<hr/>' return tpl # TODO: # Import or create categories as needed # Categories in export will need to have parent-child data # categories should have legacy identifiers where possible too # Import image files, assign those legacy KV identifiers # Modify URLs for imported images in posts # Make importing of image assets optional else: tpl = template( 'ui/ui_blog_import', menu=generate_menu('blog_import', blog), # search_context=(search_context['blog'], blog), import_path=import_path, **tags.__dict__) return tpl
def blog_import (blog_id): user = auth.is_logged_in(request) blog = Blog.load(blog_id) permission = auth.is_blog_publisher(user, blog) reason = auth.check_template_lock(blog, True) tags = template_tags(blog=blog, user=user) import os, settings import_path = os.path.join( settings.APPLICATION_PATH, "data", "import.json") tags.status = reason if request.method == "POST": from core.models import db tpl = '' with db.atomic() as txn: import json from core.utils import string_to_date import_path = request.forms.getunicode('import_path') with open(import_path, 'r', encoding='utf8') as f: json_data = json.load(f) from core.models import page_status, MediaAssociation, Category from core.error import PageNotChanged from core.libs.peewee import InterfaceError from core.cms import media_filetypes format_str = "<b>{}</b> / (<i>{}</i>)" # TODO: go in chunks of 50 or something? # allow graceful disconnection? for n in json_data: q = [] n_id = n['id'] q.append("Checking {}".format(n_id)) changed = False found = False match = Page.kv_get('legacy_id', n_id) if match.count() > 0: if match[0].object_ref.blog == blog: found = True q.append(match[0].key + "/" + match[0].value + " / Exists: " + format_str.format(n['title'], n_id)) existing_entry = Page.load(match[0].objectid) update = existing_entry.kv_get('update').count() # raise Exception(update) q.append('{} / {}'.format(string_to_date(n['modified_date']).replace(tzinfo=None), existing_entry.modified_date )) if string_to_date(n['modified_date']).replace(tzinfo=None) <= existing_entry.modified_date and update == 0: q.append('Existing page {} not changed.'.format(existing_entry.id)) else: changed = True q.append('Updating data for existing page {}.'.format(existing_entry.id)) existing_entry.title = n['title'] existing_entry.text = n['text'] existing_entry.basename = n['basename'] existing_entry.excerpt = n['excerpt'] existing_entry.created_date = string_to_date(n['created_date']).replace(tzinfo=None) existing_entry.modified_date = string_to_date(n['modified_date']).replace(tzinfo=None) existing_entry.publication_date = string_to_date(n['publication_date']).replace(tzinfo=None) try: existing_entry.save(user, False, False, 'New revision from import') except PageNotChanged: pass except InterfaceError: raise Exception("Error saving {}. Check the JSON to make sure it's valid.".format(n_id)) for media in existing_entry.media: media.kv_del() existing_entry.clear_categories() existing_entry.clear_kvs() existing_entry.clear_tags() existing_entry.clear_media() entry = existing_entry if found is False: q.append("Creating: " + format_str.format(n['title'], n_id)) changed = True new_entry = Page( title=n['title'], text=n['text'], basename=n['basename'], excerpt=n['excerpt'], user=user, blog=blog, created_date=string_to_date(n['created_date']), publication_date=string_to_date(n['publication_date']), modified_date=string_to_date(n['modified_date']), ) new_entry.modified_date = new_entry.publication_date if n['status'] in ('Publish', 'Published', 'Live'): new_entry.status = page_status.published new_entry.save(user) entry = new_entry q.append("New ID: {}".format(entry.id)) # Everything from here on out is if changed: # Register a legacy ID for the page entry.kv_set("legacy_id", n["id"]) entry.kv_set("legacy_user", n["user_id"]) # Category assignments categories = n['categories'] if categories == []: saved_page_category = PageCategory.create( page=entry, category=blog.default_category, primary=True).save() else: primary = True for category in categories: cat_exists = False category_id = category['id'] existing_category = Category.kv_get('legacy_id', category_id) if existing_category.count() > 0: if existing_category[0].object_ref.blog == blog: cat_exists = True if cat_exists is False: q.append('Created new category {}/{}'.format( category_id, category['name'] )) new_category = Category.create( blog=blog, title=category['name'], parent_category=getattr(category, 'parent', None) ) new_category.save() new_category.kv_set('legacy_id', category_id ) else: new_category = Category.load(existing_category[0].objectid) q.append('Added to existing category {}/{}'.format( new_category.id, category['name'] )) saved_page_category = PageCategory.create( page=entry, category=new_category, primary=primary ).save() primary = False # Check to make sure a default category exists for the whole blog. # If not, assign one based on the lowest ID. # This can always be reassigned later. # Register tags tags_added, tags_existing, _ = Tag.add_or_create( n['tags'], page=entry) q.append('Tags added: {}'.format(','.join(n.tag for n in tags_added))) q.append('Tags existing: {}'.format(','.join(n.tag for n in tags_existing))) # Register KVs kvs = n['kvs'] for key in kvs: if key != "": value = kvs[key] entry.kv_set(key, value) q.append('KV: {}:{}'.format(key, value)) # Register media media = n['media'] for m in media: if 'path' not in m: continue path = os.path.split(m['path']) try: new_media = Media.get(Media.url == m['url']) except: new_media = Media( filename=path[1], path=m['path'], url=m['url'], type=media_filetypes.image, created_date=string_to_date(m['created_date']), modified_date=string_to_date(m['modified_date']), friendly_name=m['friendly_name'], user=user, blog=blog, site=blog.site ) # TODO: RBF try: new_media.save() except Exception: continue media_association = MediaAssociation( media=new_media, page=entry) media_association.save() # Save legacy ID to KV on media if 'id' in m: new_media.kv_set('legacy_id', m['id']) q.append('IMG: {}'.format(new_media.url)) # add tags for media q.append('Tags: {}'.format(m['tags'])) new_tags = Tag.add_or_create(m['tags'], media=new_media) kvs = m['kvs'] for key in kvs: value = kvs[key] new_media.kv_set(key, value) q.append('KV: {}:{}'.format(key, value)) fileinfo.build_pages_fileinfos((entry,)) fileinfo.build_archives_fileinfos((entry,)) tpl += ('<p>'.join(q)) + '<hr/>' return tpl # TODO: # Import or create categories as needed # Categories in export will need to have parent-child data # categories should have legacy identifiers where possible too # Import image files, assign those legacy KV identifiers # Modify URLs for imported images in posts # Make importing of image assets optional else: tpl = template('ui/ui_blog_import', menu=generate_menu('blog_import', blog), # search_context=(search_context['blog'], blog), import_path=import_path, **tags.__dict__) return tpl