def get(self): if capabilities.CapabilitySet('datastore_v3', capabilities=['write']).is_enabled() \ and capabilities.CapabilitySet('memcache').is_enabled(): self.update_counter(main_counter) self.update_counter(stats_counter) self.update_counter(unlisted_counter) self.update_counter(queries_counter) self.update_counter(steamids_counter) self.update_counter(report_counter)
def get_apis_statuses(e): if not isinstance(e, DeadlineExceededError): return {} t1 = time.time() statuses = { 'blobstore': capabilities.CapabilitySet('blobstore').is_enabled(), 'datastore_v3': capabilities.CapabilitySet('datastore_v3').is_enabled(), 'datastore_v3_write': capabilities.CapabilitySet('datastore_v3', ['write']).is_enabled(), 'images': capabilities.CapabilitySet('images').is_enabled(), 'mail': capabilities.CapabilitySet('mail').is_enabled(), 'memcache': capabilities.CapabilitySet('memcache').is_enabled(), 'taskqueue': capabilities.CapabilitySet('taskqueue').is_enabled(), 'urlfetch': capabilities.CapabilitySet('urlfetch').is_enabled(), } t2 = time.time() statuses['time'] = t2 - t1 return statuses
def testEnabledCapability(self): admin_msg = 'Write performance is degraded for the next 15-20 minutes.' expected_request = IsEnabledRequest() expected_request.package = 'datastore_v3' expected_request.capability.append('*') expected_request.capability.append('write') actual_response = IsEnabledResponse() actual_response.summary_status = IsEnabledResponse.ENABLED config = actual_response.config.add() config.package = 'datastore_v3' config.capability = '*' config.status = CapabilityConfig.ENABLED config = actual_response.config.add() config.package = 'datastore_v3' config.capability = 'write' config.status = CapabilityConfig.ENABLED config.admin_message = admin_msg stub_map = MockCapabilityImpl(expected_request, actual_response) capability_set = capabilities.CapabilitySet( 'datastore_v3', capabilities=['write'], stub_map=stub_map) self.assertEqual(True, capability_set.is_enabled()); self.assertEqual(admin_msg, capability_set.admin_message()) self.assertEqual(actual_response, capability_set._get_status())
def testMultipleCalls(self): expected_request = IsEnabledRequest() expected_request.package = 'datastore_v3' expected_request.capability.append('*') expected_request.call.append('Put') expected_request.call.append('Delete') actual_response = IsEnabledResponse() actual_response.summary_status = IsEnabledResponse.ENABLED config = actual_response.config.add() config.package = 'datastore_v3' config.capability = '*' config.status = CapabilityConfig.ENABLED config = actual_response.config.add() config.package = 'datastore_v3' config.capability = 'write' config.status = CapabilityConfig.ENABLED config = actual_response.config.add() config.package = 'datastore_v3' config.capability = 'erase' config.status = CapabilityConfig.ENABLED stub_map = MockCapabilityImpl(expected_request, actual_response) capability_set = capabilities.CapabilitySet( 'datastore_v3', methods=['Put', 'Delete'], stub_map=stub_map) self.assertEqual(True, capability_set.is_enabled()); self.assertEqual('', capability_set.admin_message()) self.assertEqual(actual_response, capability_set._get_status())
def testDisabledCapability(self): admin_msg = 'The datastore is in read-only mode for scheduled maintenance.' expected_request = IsEnabledRequest() expected_request.package = 'datastore_v3' expected_request.capability.append('*') expected_request.capability.append('write') actual_response = IsEnabledResponse() actual_response.summary_status = IsEnabledResponse.DISABLED config = actual_response.config.add() config.package = 'datastore_v3' config.capability = '*' config.status = CapabilityConfig.ENABLED config = actual_response.config.add() config.package = 'datastore_v3' config.capability = 'write' config.status = CapabilityConfig.DISABLED config.admin_message = admin_msg stub_map = MockCapabilityImpl(expected_request, actual_response) capability_set = capabilities.CapabilitySet( 'datastore_v3', capabilities=['write'], stub_map=stub_map) self.assertEqual(False, capability_set.is_enabled()); self.assertEqual(admin_msg, capability_set.admin_message()) self.assertEqual(actual_response, capability_set._get_status())
def Render(cls, handler): """Rendering method that can be called by main.py. Args: handler: the webapp.RequestHandler invoking the method """ namespace = handler.request.get('namespace') kinds = handler.request.get('kind', allow_multiple=True) sizes_known, size_total, remainder = utils.ParseKindsAndSizes(kinds) (namespace_str, kind_str) = utils.GetPrintableStrs(namespace, kinds) notreadonly_warning = capabilities.CapabilitySet( 'datastore_v3', capabilities=['write']).is_enabled() blob_warning = bool(blobstore.BlobInfo.all().fetch(1)) datastore_type = datastore._GetConnection().get_datastore_type() high_replication_warning = (datastore_type == datastore_rpc.Connection. HIGH_REPLICATION_DATASTORE) template_params = { 'form_target': DoCopyHandler.SUFFIX, 'kind_list': kinds, 'remainder': remainder, 'sizes_known': sizes_known, 'size_total': size_total, 'app_id': handler.request.get('app_id'), 'cancel_url': handler.request.get('cancel_url'), 'kind_str': kind_str, 'namespace_str': namespace_str, 'xsrf_token': utils.CreateXsrfToken(XSRF_ACTION), 'notreadonly_warning': notreadonly_warning, 'blob_warning': blob_warning, 'high_replication_warning': high_replication_warning, } utils.RenderToResponse(handler, 'confirm_copy.html', template_params)
def Render(cls, handler): """Rendering method that can be called by main.py or get. This method executes no action, so the method by which it is accessed is immaterial. Creating a form with get may be a desirable function. That is, if this builtin is turned on, anyone can create a form to delete a kind by simply linking to the ConfirmDeleteHandler like so: <a href="/_ah/datastore_admin/confirm_delete?kind=trash"> Delete all Trash Objects</a> Args: handler: the webapp.RequestHandler invoking the method """ readonly_warning = not capabilities.CapabilitySet( 'datastore_v3', capabilities=['write']).is_enabled() namespace = handler.request.get('namespace') kinds = handler.request.get_all('kind') sizes_known, size_total, remainder = utils.ParseKindsAndSizes(kinds) (namespace_str, kind_str) = utils.GetPrintableStrs(namespace, kinds) template_params = { 'readonly_warning': readonly_warning, 'form_target': DoDeleteHandler.SUFFIX, 'kind_list': kinds, 'remainder': remainder, 'sizes_known': sizes_known, 'size_total': size_total, 'app_id': handler.request.get('app_id'), 'datastore_admin_home': utils.GenerateHomeUrl(handler.request), 'kind_str': kind_str, 'namespace_str': namespace_str, 'xsrf_token': utils.CreateXsrfToken(XSRF_ACTION), } utils.RenderToResponse(handler, 'confirm_delete.html', template_params)
def Render(cls, handler, default_backup_id=None, default_delete_backup_after_restore=False): """Rendering method that can be called by main.py. Args: handler: the webapp.RequestHandler invoking the method default_backup_id: default value for handler.request default_delete_backup_after_restore: default value for handler.request """ backup_id = handler.request.get('backup_id', default_backup_id) backup = db.get(backup_id) if backup_id else None notreadonly_warning = capabilities.CapabilitySet( 'datastore_v3', capabilities=['write']).is_enabled() original_app_warning = backup.original_app if os.getenv('APPLICATION_ID') == original_app_warning: original_app_warning = None template_params = { 'form_target': DoBackupRestoreHandler.SUFFIX, 'queues': None, 'cancel_url': handler.request.get('cancel_url'), 'backup': backup, 'delete_backup_after_restore': handler.request.get( 'delete_backup_after_restore', default_delete_backup_after_restore), 'xsrf_token': utils.CreateXsrfToken(XSRF_ACTION), 'notreadonly_warning': notreadonly_warning, 'original_app_warning': original_app_warning } utils.RenderToResponse(handler, 'confirm_restore_from_backup.html', template_params)
def testUnknownApi(self): expected_request = IsEnabledRequest() expected_request.package = 'kittens' expected_request.capability.append('*') expected_request.capability.append('cuteness') expected_request.call.append('Meow') actual_response = IsEnabledResponse() actual_response.summary_status = IsEnabledResponse.ENABLED config = actual_response.config.add() config.package = 'kittens' config.capability = '*' config.status = CapabilityConfig.ENABLED config = actual_response.config.add() config.package = 'kittens' config.capability = 'cuteness' config.status = CapabilityConfig.ENABLED stub_map = MockCapabilityImpl(expected_request, actual_response) capability_set = capabilities.CapabilitySet('kittens', capabilities=['cuteness'], methods=['Meow'], stub_map=stub_map) self.assertEqual(True, capability_set.is_enabled()) self.assertEqual(actual_response, capability_set._get_status())
def Render(cls, handler): """Rendering method that can be called by main.py. Args: handler: the webapp.RequestHandler invoking the method """ namespace = handler.request.get('namespace', None) has_namespace = namespace is not None kinds = handler.request.get_all('kind') sizes_known, size_total, remainder = utils.ParseKindsAndSizes(kinds) notreadonly_warning = capabilities.CapabilitySet( 'datastore_v3', capabilities=['write']).is_enabled() blob_warning = bool(blobstore.BlobInfo.all().count(1)) app_id = handler.request.get('app_id') template_params = { 'form_target': DoBackupHandler.SUFFIX, 'kind_list': kinds, 'remainder': remainder, 'sizes_known': sizes_known, 'size_total': size_total, 'app_id': app_id, 'queues': None, 'cancel_url': handler.request.get('cancel_url'), 'has_namespace': has_namespace, 'namespace': namespace, 'xsrf_token': utils.CreateXsrfToken(XSRF_ACTION), 'notreadonly_warning': notreadonly_warning, 'blob_warning': blob_warning, 'backup_name': 'datastore_backup_%s' % time.strftime('%Y_%m_%d') } utils.RenderToResponse(handler, 'confirm_backup.html', template_params)
def GetStatus(user): """Return the status of Snipper, according to the datastore write.""" status = 'OK' help_msg = 'Snipper should be working properly.' datastore_write = capabilities.CapabilitySet('datastore_v3', capabilities=['write']) if not datastore_write.is_enabled(): status = 'Read only' help_msg = 'App Engine is down for maintenance, please try again later.' return _STATUS_TEMPLATE % {'help': help_msg, 'status': status, 'user': user}
def services(self): """Return the status and admin message list for all available services.""" blobstore_api = capabilities.CapabilitySet('blobstore') datastore_read_api = capabilities.CapabilitySet('datastore_v3') datastore_write_api = capabilities.CapabilitySet( 'datastore_v3', ['write']) mail_api = capabilities.CapabilitySet('mail') memcache_api = capabilities.CapabilitySet('memcache') taskqueue_api = capabilities.CapabilitySet('taskqueue') urlfetch_api = capabilities.CapabilitySet('urlfetch') return [ { 'blobstore': { 'enabled': blobstore_api.is_enabled(), 'message': blobstore_api.admin_message(), } }, { 'datastore_read': { 'enabled': datastore_read_api.is_enabled(), 'message': datastore_read_api.admin_message(), } }, { 'datastore_write': { 'enabled': datastore_write_api.is_enabled(), 'message': datastore_write_api.admin_message(), } }, { 'mail': { 'enabled': mail_api.is_enabled(), 'message': mail_api.admin_message(), } }, { 'memcache': { 'enabled': memcache_api.is_enabled(), 'message': memcache_api.admin_message(), } }, { 'taskqueue': { 'enabled': taskqueue_api.is_enabled(), 'message': taskqueue_api.admin_message(), } }, { 'urlfetch': { 'enabled': urlfetch_api.is_enabled(), 'message': urlfetch_api.admin_message(), } }, ]
def get(self): self.generate_manage_bar() if not capabilities.CapabilitySet('datastore_v3', ['write']).is_enabled(): self.abort(500, "The datastore is down") self.template_vars[ 'MaxHomepageSlides'] = self.settings.MaxHomepageSlides self.template_vars['LinkPrefix'] = '/'.join( (os.environ['HTTP_HOST'], )) self.template_vars['form'] = self.generate_form(HomepageSlide_Form) self.template_vars['error_msg'] = self.session.get('new_slide_error') self.render_template("manage/homepage_slides/new_slide.html")
def wsgi_app(environ, start_response): app = application(environ, start_response) if not capabilities.CapabilitySet('memcache').is_enabled(): logging.error("Memcache service not available.") return app record = False path_info = os.environ['PATH_INFO'] for re_obj in compiled_url_patterns: if re.match(re_obj, path_info): record = True break if record: recorder.trace() return app
def testUnknownCall(self): expected_request = IsEnabledRequest() expected_request.package = 'datastore_v3' expected_request.capability.append('*') expected_request.call.append('ShipMeADVD') actual_response = IsEnabledResponse() actual_response.summary_status = IsEnabledResponse.ENABLED config = actual_response.config.add() config.package = 'datastore_v3' config.capability = '*' config.status = CapabilityConfig.ENABLED stub_map = MockCapabilityImpl(expected_request, actual_response) capability_set = capabilities.CapabilitySet( 'datastore_v3', methods=['ShipMeADVD'], stub_map=stub_map) self.assertEqual(True, capability_set.is_enabled()) self.assertEqual(actual_response, capability_set._get_status())
def Render(cls, handler): """Rendering method that can be called by main.py. Args: handler: the webapp.RequestHandler invoking the method """ backup_id = handler.request.get('backup_id') backup = db.get(backup_id) if backup_id else None notreadonly_warning = capabilities.CapabilitySet( 'datastore_v3', capabilities=['write']).is_enabled() app_id = handler.request.get('app_id') template_params = { 'form_target': DoBackupRestoreHandler.SUFFIX, 'app_id': app_id, 'queues': None, 'cancel_url': handler.request.get('cancel_url'), 'backup': backup, 'xsrf_token': utils.CreateXsrfToken(XSRF_ACTION), 'notreadonly_warning': notreadonly_warning } utils.RenderToResponse(handler, 'confirm_restore_from_backup.html', template_params)
def get(self): # データブックの名前を取得 databook_name = get_databook_name(self.request.get('db')) # データブックの表示タイトルを取得 databook_title = get_databook_title(self.request.get('db')) # 全文検索用インデックスの名前を取得 databook_indexname = get_databook_indexname(self.request.get('db')) # 表示メッセージの初期化 message_data = '' # 管理者ログインのチェック admin_login = False if users.is_current_user_admin(): admin_login = True # 管理者ログイン中の表示 admin_message = '' if users.get_current_user(): if admin_login: admin_message = '(管理者としてログインしています)' else: admin_message = '(管理者ではありません)' # ログイン/ログアウトURL設定 if users.get_current_user(): login_url = users.create_logout_url(self.request.uri) login_text = '[ログアウト]' else: login_url = users.create_login_url(self.request.uri) # login_text = '[ログイン]' login_text = '[管理]' # 書き込み禁止の判定 write_disabled_message = '' if not capabilities.CapabilitySet('datastore_v3', ['write']).is_enabled(): write_disabled_message = '【現在書き込みは禁止しています】' # 全文検索の単語を取得 search_flag = False search_count = 0 search_word = self.request.get('word').strip() # 全文検索の単語の先頭が「=」のときは特別扱い show_all_flag = False show_offset = 0 if search_word.startswith('='): i = 1 while i < len(search_word): ch = search_word[i] # 「*」のときは表示フラグを無視して全て表示する if ch == '*': i += 1 show_all_flag = True continue # 数字のときは表示件数のオフセットとする if ch.isdigit(): i += 1 j = i - 1 while i < len(search_word): ch = search_word[i] if ch.isdigit(): i += 1 continue break k = i if (k - j) > 5: k = j + 5 show_offset = int(search_word[j:k]) continue # その他のときは抜ける break search_word2 = search_word[i:] else: search_word2 = search_word # 全文検索の単語をチェック if search_word2: # 全文検索を行うとき articles = [] # 検索結果を日付の降順でソートする指定 expr_list = [ search.SortExpression( expression='date', default_value=datetime.datetime.min, direction=search.SortExpression.DESCENDING) ] # ソートオプションに設定する sort_opts = search.SortOptions(expressions=expr_list) # クエリーオプションに設定する # (表示件数指定、ソートオプション指定、検索結果はタイトルのみ取得) query_opts = search.QueryOptions(limit=mainpage_show_num, offset=show_offset, sort_options=sort_opts, returned_fields=['title']) try: # 単語とクエリーオプションを指定して全文検索実行 query_obj = search.Query(query_string=search_word2, options=query_opts) search_results = search.Index(name=databook_indexname).search( query=query_obj) # 検索結果から記事のタイトルを取得する req_titles = [] for scored_doc in search_results: req_titles.append(scored_doc.field('title').value) if len(req_titles) >= 1: # 記事を検索(タイトルで表示件数まで) if show_all_flag: articles_query = Article.query( Article.title.IN(req_titles), ancestor=databook_key(databook_name)).order( -Article.date) else: articles_query = Article.query( Article.title.IN(req_titles), Article.show_flag == 1, ancestor=databook_key(databook_name)).order( -Article.date) articles = articles_query.fetch(mainpage_show_num) except (search.QueryError, search.InvalidRequest), e: # クエリーエラーのとき message_data = message_data + '(クエリーエラー:検索文字列に記号が含まれると発生することがあります)' search_flag = True search_count = len(articles)
def post(self): # データブックの名前を取得 databook_name = get_databook_name(self.request.get('db')) # 表示メッセージの初期化 message_data = '' # 記事のタイトルをチェック req_title = self.request.get('title').strip() if not req_title: self.redirect(mainpage_url + '?' + urllib.urlencode({'db': databook_name})) return # 管理者ログインのチェック admin_login = False if users.is_current_user_admin(): admin_login = True # 書き込み禁止の判定 write_disabled_message = '' if not capabilities.CapabilitySet('datastore_v3', ['write']).is_enabled(): write_disabled_message = '【現在書き込みは禁止しています】' # 日時更新のチェック(デフォルトON) datechg_flag = 1 if self.request.get('datechg') == '0': datechg_flag = 0 # 記事を検索(タイトルで1件だけ) articles_query = Article.query( Article.title == req_title, ancestor=databook_key(databook_name)).order(-Article.date) articles = articles_query.fetch(1) # 記事が存在しなければ新規作成 if len(articles) < 1: article = Article(parent=databook_key(databook_name)) article.title = req_title article.author = '' article.content = '' article.source = '' article.date = datetime.datetime.now() article.bkup_authors = [] article.bkup_contents = [] article.bkup_sources = [] article.bkup_dates = [] article.bkup_lastupdate = datetime.datetime.min article.search_doc_id = '' article.show_flag = 1 else: article = articles[0] # バックアップをロードするかのチェック req_bkup_sel = self.request.get('bkup_sel') if req_bkup_sel and req_bkup_sel.isdigit(): req_bkup_no = int(req_bkup_sel) - 1 if req_bkup_no >= 0 and req_bkup_no < len(article.bkup_dates): article.author = article.bkup_authors[req_bkup_no] article.content = article.bkup_contents[req_bkup_no] article.source = article.bkup_sources[req_bkup_no] # article.date = article.bkup_dates[req_bkup_no] date_temp = article.bkup_dates[req_bkup_no] date_temp = date_temp.replace(tzinfo=UTC()).astimezone( JapanTZ()) message_data = message_data + '(「' + date_temp.strftime( '%Y-%m-%d %H:%M:%S %Z') + '」の履歴をロードしました)' # 全文検索用ドキュメントの登録チェック if not article.search_doc_id: message_data = message_data + '(全文検索未登録)' # 文字コード変換(表示用) message_data = message_data.decode('utf-8') write_disabled_message = write_disabled_message.decode('utf-8') # ローカル日時変換(表示用) article.date = article.date.replace(tzinfo=UTC()).astimezone(JapanTZ()) for i in range(len(article.bkup_dates)): article.bkup_dates[i] = article.bkup_dates[i].replace( tzinfo=UTC()).astimezone(JapanTZ()) # 編集ページのテンプレートに記事データを埋め込んで表示 template = jinja_environment.get_template(editpage_html) self.response.out.write( template.render(databook_name=databook_name, article=article, update_url=update_url, runpage_url=runpage_url, mainpage_url=mainpage_url, editpage_url=editpage_url, message_data=message_data, admin_login=admin_login, datechg_flag=datechg_flag, write_disabled_message=write_disabled_message))
FLAG_TYPE_MASK = 7 FLAG_COMPRESSED = 1 << 3 TYPE_STR = 0 TYPE_UNICODE = 1 TYPE_PICKLED = 2 TYPE_INT = 3 TYPE_LONG = 4 TYPE_BOOL = 5 CAPABILITY = capabilities.CapabilitySet('memcache') def _add_name_space(message, namespace=None): """Populate the name_space field in a messagecol buffer. Args: message: A messagecol buffer supporting the set_name_space() operation. namespace: The name of the namespace part. If None, use the default namespace. The empty namespace (i.e. '') will clear the name_space field. """ if namespace is None: namespace = namespace_manager.get_namespace() if not namespace: message.clear_name_space()
def get(self): for c in CAPABILITIES: if capabilities.CapabilitySet(c).is_enabled(): self.response.out.write("<br />capability %s is enabled!" % c) else: self.response.out.write("<br />capability %s is disabled!" % c)
def post(self): # データブックの名前を取得 databook_name = get_databook_name(self.request.get('db')) # 全文検索用インデックスの名前を取得 databook_indexname = get_databook_indexname(self.request.get('db')) # 表示メッセージの初期化 message_data = '' # 記事のタイトルをチェック req_title = self.request.get('title').strip() if not req_title: self.redirect(mainpage_url + '?' + urllib.urlencode({'db': databook_name})) return # 管理者ログインのチェック admin_login = False if users.is_current_user_admin(): admin_login = True # 書き込み禁止の判定 write_enabled = True write_disabled_message = '' if not capabilities.CapabilitySet('datastore_v3', ['write']).is_enabled(): write_enabled = False write_disabled_message = '【現在書き込みは禁止しています】' # 日時更新のチェック(デフォルトOFF) datechg_flag = 0 if self.request.get('datechg') == '1': datechg_flag = 1 # 記事を検索(タイトルで1件だけ) articles_query = Article.query( Article.title == req_title, ancestor=databook_key(databook_name)).order(-Article.date) articles = articles_query.fetch(1) # 記事が存在しなければ新規作成 if len(articles) < 1: article = Article(parent=databook_key(databook_name)) article.title = req_title article.author = '' article.content = '' article.source = '' article.date = datetime.datetime.now() article.bkup_authors = [] article.bkup_contents = [] article.bkup_sources = [] article.bkup_dates = [] article.bkup_lastupdate = datetime.datetime.min article.search_doc_id = '' article.show_flag = 1 else: article = articles[0] # ログインユーザー名をセット(今回未使用) # if users.get_current_user(): # article.author = users.get_current_user().nickname() # 送信されたデータを記事に設定 if self.request.get('delete') != '1' and self.request.get( 'rename') != '1': article.author = self.request.get('author').strip() article.content = self.request.get('content').strip() article.source = self.request.get('source') if datechg_flag == 1: article.date = datetime.datetime.now() # 記事の非表示(保守用) if write_enabled and article.author.startswith('=hide'): article.show_flag = 0 else: article.show_flag = 1 # 記事の削除(保守用) # if article.author.startswith('=delete'): if write_enabled and self.request.get('delete') == '1': if admin_login and article.bkup_dates: # (関連する全文検索用ドキュメントがあればそれも削除) if article.search_doc_id: search.Index(name=databook_indexname).delete( article.search_doc_id) article.key.delete() self.redirect(mainpage_url + '?' + urllib.urlencode({'db': databook_name})) return # 全文検索用ドキュメントの個別削除(保守用) if write_enabled and article.author.startswith('=index_delete'): if admin_login: doc_id = article.content if doc_id: search.Index(name=databook_indexname).delete(doc_id) self.redirect(mainpage_url + '?' + urllib.urlencode({'db': databook_name})) return # 全文検索用ドキュメントの全削除(保守用) if write_enabled and article.author.startswith('=all_index_delete'): if admin_login: search_index = search.Index(name=databook_indexname) while True: doc_ids = [ doc.doc_id for doc in search_index.get_range(ids_only=True) ] if not doc_ids: break search_index.delete(doc_ids) self.redirect(mainpage_url + '?' + urllib.urlencode({'db': databook_name})) return # 記事のタイトル変更(保守用) rename_flag = 0 if write_enabled and self.request.get('rename') == '1': new_title = self.request.get('newtitle').strip() if admin_login and new_title and new_title != article.title and article.bkup_dates: # 記事を検索(新タイトルで1件だけ) articles_query = Article.query( Article.title == new_title, ancestor=databook_key(databook_name)).order(-Article.date) articles_temp = articles_query.fetch(1) # 記事が存在しなければ、タイトルを変更できる if len(articles_temp) < 1: article.title = new_title rename_flag = 1 else: rename_flag = 2 else: rename_flag = 2 # バックアップの保存 # (10分以内のときは、バックアップを追加しないで上書きとする) if write_enabled and rename_flag == 0: time_diff_minutes = -1 if article.bkup_lastupdate: time_diff = datetime.datetime.now() - article.bkup_lastupdate time_diff_minutes = time_diff.days * 24 * 60 + time_diff.seconds / 60 if time_diff_minutes >= 0 and time_diff_minutes <= backup_time: # 最新のバックアップを上書き article.bkup_authors[0] = article.author article.bkup_contents[0] = article.content article.bkup_sources[0] = article.source article.bkup_dates[0] = article.date else: # バックアップを追加(最大10件) article.bkup_authors.insert(0, article.author) article.bkup_contents.insert(0, article.content) article.bkup_sources.insert(0, article.source) article.bkup_dates.insert(0, article.date) if len(article.bkup_dates) > backup_num: article.bkup_authors = article.bkup_authors[:backup_num] article.bkup_contents = article.bkup_contents[:backup_num] article.bkup_sources = article.bkup_sources[:backup_num] article.bkup_dates = article.bkup_dates[:backup_num] article.bkup_lastupdate = datetime.datetime.now() # 全文検索用ドキュメントを登録する if write_enabled and (rename_flag == 0 or rename_flag == 1): date_str = article.date.replace(tzinfo=UTC()).astimezone( JapanTZ()).strftime('%Y-%m-%d %H:%M:%S %Z') doc_content = article.title + ' ' + article.author + ' ' + article.content + ' ' + date_str if article.search_doc_id: # すでに登録されていれば上書き doc = search.Document(doc_id=article.search_doc_id, fields=[ search.TextField(name='title', value=article.title, language='ja'), search.TextField(name='content', value=doc_content, language='ja'), search.DateField(name='date', value=article.date) ]) put_result = search.Index(name=databook_indexname).put(doc) else: # 登録されていなければ新規作成(このときドキュメントIDを記憶しておく) doc = search.Document(fields=[ search.TextField( name='title', value=article.title, language='ja'), search.TextField( name='content', value=doc_content, language='ja'), search.DateField(name='date', value=article.date) ]) put_result = search.Index(name=databook_indexname).put(doc) # ↓これではドキュメントIDとれないので注意。putの戻り値から取得する必要がある # article.search_doc_id = doc.doc_id article.search_doc_id = put_result[0].id # 記事をデータブックに登録 if write_enabled: if rename_flag == 0: article.put() message_data = message_data + '(セーブしました)' elif rename_flag == 1: article.put() message_data = message_data + '(タイトルを変更しました)' else: message_data = message_data + '(タイトルを変更できません(名称が不正もしくは同名が存在する等))' else: message_data = message_data + '(書き込みが禁止されています)' # # メインページに戻る # self.redirect(mainpage_url + '?' + urllib.urlencode({'db': databook_name})) # 文字コード変換(表示用) message_data = message_data.decode('utf-8') write_disabled_message = write_disabled_message.decode('utf-8') # ローカル日時変換(表示用) article.date = article.date.replace(tzinfo=UTC()).astimezone(JapanTZ()) for i in range(len(article.bkup_dates)): article.bkup_dates[i] = article.bkup_dates[i].replace( tzinfo=UTC()).astimezone(JapanTZ()) # 編集ページのテンプレートに記事データを埋め込んで表示 template = jinja_environment.get_template(editpage_html) self.response.out.write( template.render(databook_name=databook_name, article=article, update_url=update_url, runpage_url=runpage_url, mainpage_url=mainpage_url, editpage_url=editpage_url, message_data=message_data, admin_login=admin_login, datechg_flag=datechg_flag, write_disabled_message=write_disabled_message))