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 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)
def create_resources(json, db): try: # Resources to return in the response created_resources = [] # Serialized Resources to send to Algolia created_resources_algolia = [] # Resource IDs to delete if Algolia fails to index resource_id_cache = [] # Create each Resource in the database one by one for resource in json: langs, categ = get_attributes(resource) paid_bool = ensure_bool(resource.get('paid')) new_resource = Resource(name=resource.get('name'), url=resource.get('url'), category=categ, languages=langs, paid=paid_bool, notes=resource.get('notes')) try: db.session.add(new_resource) db.session.commit() created_resources_algolia.append( new_resource.serialize_algolia_search) resource_id_cache.append(new_resource.id) 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) created_resources.append(new_resource.serialize) # Take all the created resources and save them in Algolia with one API call try: index.save_objects(created_resources_algolia) except (AlgoliaUnreachableHostException, AlgoliaException) as e: if (environ.get("FLASK_ENV") != 'development'): logger.exception(e) # Remove created resources from the db to stay in sync with Algolia for res_id in resource_id_cache: res = Resource.query.get(res_id) res.languages.clear() db.session.delete(res) db.session.commit() msg = "Algolia failed to index resources" error = {'errors': [{"algolia-failed": {"message": msg}}]} return utils.standardize_response(payload=error, status_code=500) # Success return utils.standardize_response(payload=dict(data=created_resources), datatype="resources") except Exception as e: logger.exception(e) return utils.standardize_response(status_code=500)