def update_resource(id, json, db): resource = Resource.query.get(id) if not resource: return redirect('/404') langs, categ = get_attributes(json) index_object = {'objectID': id} try: logger.info(f"Updating resource. Old data: {resource.serialize}") if json.get('languages'): resource.languages = langs index_object['languages'] = resource.serialize['languages'] if json.get('category'): resource.category = categ index_object['category'] = categ.name if json.get('name'): resource.name = json.get('name') index_object['name'] = json.get('name') if json.get('url'): resource.url = json.get('url') index_object['url'] = json.get('url') if 'paid' in json: paid = json.get('paid') # Converts "false" and "true" to their bool if type(paid) is str and paid.lower() in ["true", "false"]: paid = paid.lower().strip() == "true" resource.paid = paid index_object['paid'] = paid if 'notes' in json: resource.notes = json.get('notes') index_object['notes'] = json.get('notes') try: index.partial_update_object(index_object) except (AlgoliaUnreachableHostException, AlgoliaException) as e: if environ.get("FLASK_ENV") != 'development': logger.exception(e) msg = f"Algolia failed to update index for resource '{resource.name}'" logger.warn(msg) error = {'errors': [{"algolia-failed": {"message": msg}}]} return utils.standardize_response(payload=error, status_code=500) # Wait to commit the changes until we know that Aloglia was updated db.session.commit() return utils.standardize_response(payload=dict( data=resource.serialize)) except IntegrityError as e: logger.exception(e) return utils.standardize_response(status_code=422) except Exception as e: logger.exception(e) return utils.standardize_response(status_code=500)
def search_results(): term = request.args.get('q', '', str) page = request.args.get('page', 0, int) page_size = request.args.get('page_size', Config.RESOURCE_PAGINATOR.per_page, int) # Fetch the filter params from the url, if they were provided. free = request.args.get('free') category = request.args.get('category') languages = request.args.getlist('languages') filters = [] # Filter on free if free: free = free.lower() # algolia filters boolean attributes with either 0 or 1 if free == 'true': filters.append('free=1') elif free == 'false': filters.append('free=0') # Filter on category if category: # to not let double quotes conflict with algolia filter format category = category.replace('"', "'") filters.append( f'category: "{category}"' ) # Filter on languages if languages and '' not in languages: for i, _ in enumerate(languages): # to not let double quotes conflict with algolia filter format languages[i] = 'languages:"{}"'.format(languages[i].replace('"', "'")) # joining all possible language values to algolia filter query filters.append(f"( {' OR '.join(languages)} )") try: search_result = index.search(f'{term}', { 'filters': " AND ".join(filters), 'page': page, 'hitsPerPage': page_size }) except (AlgoliaUnreachableHostException, AlgoliaException) as e: logger.exception(e) msg = "Failed to get resources from Algolia" logger.warn(msg) error = {'errors': [{"algolia-failed": {"message": msg}}]} return utils.standardize_response(payload=error, status_code=500) if page >= int(search_result['nbPages']): return redirect('/404') results = [utils.format_resource_search(result) for result in search_result['hits']] details = { "details": { "page": search_result['page'], "number_of_pages": search_result['nbPages'], "records_per_page": search_result['hitsPerPage'], "total_count": search_result['nbHits'], } } return utils.standardize_response( payload=dict(data=results, **details), datatype="resources")
def update_resource(id, json, db): resource = Resource.query.get(id) api_key = g.auth_key.apikey if not resource: return redirect('/404') langs, categ = get_attributes(json) index_object = {'objectID': id} def get_unique_resource_categories_as_strings(): resources = Resource.query.all() return {resource.category.name for resource in resources} def get_unique_resource_languages_as_strings(): resources = Resource.query.all() return { language.name for resource in resources for language in resource.languages } try: logger.info(f"Updating resource. Old data: " f"{json_module.dumps(resource.serialize(api_key))}") if json.get('languages') is not None: old_languages = resource.languages[:] resource.languages = langs index_object['languages'] = resource.serialize( api_key)['languages'] resource_languages = get_unique_resource_languages_as_strings() for language in old_languages: if language.name not in resource_languages: db.session.delete(language) if json.get('category'): old_category = resource.category resource.category = categ index_object['category'] = categ.name resource_categories = get_unique_resource_categories_as_strings() if old_category.name not in resource_categories: db.session.delete(old_category) if json.get('name'): resource.name = json.get('name') index_object['name'] = json.get('name') if json.get('url'): resource.url = json.get('url') index_object['url'] = json.get('url') if 'free' in json: free = ensure_bool(json.get('free')) resource.free = free index_object['free'] = free if 'notes' in json: resource.notes = json.get('notes') index_object['notes'] = json.get('notes') try: index.partial_update_object(index_object) except (AlgoliaUnreachableHostException, AlgoliaException) as e: if environ.get("FLASK_ENV") != 'development': logger.exception(e) msg = f"Algolia failed to update index for resource '{resource.name}'" logger.warn(msg) error = {'errors': [{"algolia-failed": {"message": msg}}]} return utils.standardize_response(payload=error, status_code=500) # Wait to commit the changes until we know that Aloglia was updated db.session.commit() return utils.standardize_response( payload=dict(data=resource.serialize(api_key)), datatype="resource") except IntegrityError as e: logger.exception(e) return utils.standardize_response(status_code=422) except Exception as e: logger.exception(e) return utils.standardize_response(status_code=500)