diff --git a/conf/run.sh b/conf/run.sh index ea16ba054..570a39ffd 100755 --- a/conf/run.sh +++ b/conf/run.sh @@ -40,7 +40,19 @@ nvm use v10 echo "Starting archgraph server at $ROOT_DIR" cd "$ROOT_DIR" -python "$ROOT_DIR/src/Routes/routes.py" --neo4j="$NEO4J_CONNECTION_STRING" --mongodb="$MONGODB_CONNECTION_STRING" & +if [[ "$NEO4J_CONNECTION_STRING" != "" ]]; then + echo "Neo4j Server at $NEO4J_CONNECTION_STRING"; +fi + +if [[ "$MONGODB_CONNECTION_STRING" != "" ]]; then + echo "MongoDB Server at $MONGODB_CONNECTION_STRING"; +fi + +if [[ "$CUSTOM_HOST_FOR_SERVER_BIND" != "" ]]; then + echo "Flask Server binding to host with address $CUSTOM_HOST_FOR_SERVER_BIND"; +fi + +python "$ROOT_DIR/src/Routes/routes.py" --neo4j="$NEO4J_CONNECTION_STRING" --mongodb="$MONGODB_CONNECTION_STRING" --host="$CUSTOM_HOST_FOR_SERVER_BIND" & SERVER_PID=$! cd "$ROOT_DIR/frontend" || ( echo "folder missing " && exit 1 ) if [[ "$RUN_IN_PRODUCTION" != "" ]] ; then diff --git a/docker-compose.yml b/docker-compose.yml index c86efb968..b5dbbb1fd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,7 @@ services: mongodb: container_name: archgraph-mongodb image: mongo:latest + command: ["--bind_ip_all"] environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: rootpassword @@ -32,11 +33,12 @@ services: dockerfile: Dockerfile args: SOURCE_BRANCH: master - PRELOAD_GRAPH: "true" + PRELOAD_GRAPH: "1" context: . environment: - - "NEO4J_CONNECTION_STRING=bolt://neo4j:password@neo4j:7687" - - "MONGODB_CONNECTION_STRING=mongodb://root:rootpassword@mongodb:27017" + - "NEO4J_CONNECTION_STRING=bolt://neo4j:password@archgraph-neo4j:7687" + - "MONGODB_CONNECTION_STRING=mongodb://root:rootpassword@archgraph-mongodb:27017" + - "CUSTOM_HOST_FOR_SERVER_BIND=0.0.0.0" - "RUN_IN_PRODUCTION=1" ports: - published: 4200 diff --git a/src/Models/CRM/v5_0_2/NodeEntities/E1_CRM_Entity.py b/src/Models/CRM/v5_0_2/NodeEntities/E1_CRM_Entity.py index 9a04d3dcc..5154ac1f0 100644 --- a/src/Models/CRM/v5_0_2/NodeEntities/E1_CRM_Entity.py +++ b/src/Models/CRM/v5_0_2/NodeEntities/E1_CRM_Entity.py @@ -1,11 +1,10 @@ from marshmallow import Schema, fields from neomodel import ( - One, RelationshipTo, StringProperty, StructuredNode, UniqueIdProperty, - db, ZeroOrOne, + ZeroOrOne, ) from src.GCF.decorators.OntologyClass import ontology_class, decorator_schema from src.Models.CRM.v5_0_2.NodeProperties.has_value import has_value @@ -32,7 +31,7 @@ class E1_CRM_EntitySchema(Schema): P137_exemplifies = fields.List(fields.Nested("src.Models.CRM.v5_0_2.NodeEntities.E55_Type.E55_TypeSchema")) P48_has_preferred_identifier = fields.Nested("src.Models.CRM.v5_0_2.NodeEntities.E42_Identifier.E42_IdentifierSchema") P139_has_alternative_form = fields.List(fields.Nested("src.Models.CRM.v5_0_2.NodeEntities.E41_Appellation.E41_AppellationSchema")) - P1_is_identified_by = fields.Nested("src.Models.CRM.v5_0_2.NodeEntities.E55_Type.E55_TypeSchema") + P1_is_identified_by = fields.Nested("src.Models.CRM.v5_0_2.NodeEntities.E41_Appellation.E41_AppellationSchema") has_value = fields.List( fields.Nested("src.Models.DataObject.v0_0_2.DataObject.DataObjectSchema") ) diff --git a/src/Models/DataObject/v0_0_2/RegexString.py b/src/Models/DataObject/v0_0_2/RegexString.py index 8e43a8a1a..cd8bdface 100644 --- a/src/Models/DataObject/v0_0_2/RegexString.py +++ b/src/Models/DataObject/v0_0_2/RegexString.py @@ -26,7 +26,7 @@ def __init__(self, schema=None, *args, **kwargs): expression = "" if kwargs.get("expression") is None: - # TODO falta arranjar isto + # todo falta arranjar isto expression = "regex/[a-zA-Z]([a-zA-Z 0-9])*$" else: expression = json.dumps(kwargs.get("expression")) diff --git a/src/Models/DataObject/v0_0_2/SuperClass.py b/src/Models/DataObject/v0_0_2/SuperClass.py index a709eebf0..90c20b8cd 100644 --- a/src/Models/DataObject/v0_0_2/SuperClass.py +++ b/src/Models/DataObject/v0_0_2/SuperClass.py @@ -7,11 +7,12 @@ class SuperClass: def __init__(self, schema): self.schema = schema + """The function returns the node schema""" def getSchema(self): json_schema = JSONSchema() return json_schema.dump(self.schema) - # Json to string + """The function returns the node information in string""" def encodeJSON(self): data = {} for key, val in self.__properties__.items(): @@ -24,18 +25,21 @@ def my_converter(o): return json.dumps(data, default=my_converter) - # string to json + """The function returns the node information at format json""" def decodeJSON(self): return json.loads(self.encodeJSON()) + """The function returns the property of entity with name property_name""" def get_property_from_entity(self, property_name): schema_node = self.getSchema() class_name = self.__class__.__name__ + "Schema" return schema_node['definitions'][class_name]['properties'][property_name] + """The function returns its superclasses names""" def get_superclasses_name(self): return list(set(self.labels())) + """The function returns the schema according to the template provided""" def get_schema_with_template(self, template): jsonSchema = self.getSchema() newJsonSchema = { @@ -46,6 +50,7 @@ def get_schema_with_template(self, template): self.__get_schema_with_template_aux(jsonSchema["definitions"], template, newJsonSchema) return newJsonSchema + """Auxiliary function - The function returns the schema according to the template provided""" def __get_schema_with_template_aux(self, definitions, json_template, new_json_schema): if isinstance(json_template, str): entity_name = json_template @@ -69,7 +74,7 @@ def __get_schema_with_template_aux(self, definitions, json_template, new_json_sc properties = definitions[current_entity]['properties'] - self.__get_entity_properties_without_ref(definitions[current_entity], entity) + self.__set_entity_properties_without_ref(definitions[current_entity], entity) if isinstance(json_template, str): return @@ -81,7 +86,7 @@ def __get_schema_with_template_aux(self, definitions, json_template, new_json_sc self.__get_schema_with_template_aux(definitions, next_entity, new_json_schema) - def __get_entity_properties_without_ref(self, current_entity, entity): + def __set_entity_properties_without_ref(self, current_entity, entity): for property_name in current_entity['properties']: property_entity = current_entity['properties'][property_name] @@ -97,6 +102,7 @@ def __get_entity_properties_without_ref(self, current_entity, entity): # 'type': 'string'} # changed_property['title'] = property_entity['title'] + """The function merges between node and customer data, then saves the node""" def merge_node(self, updated_node): merged_node = dict(self.decodeJSON(), **updated_node) field_type_date = self.__get_field_of_type_date() @@ -111,30 +117,26 @@ def merge_node(self, updated_node): self.save() except BaseException: return None - - # array_uid = read_relationships(node_name, relationship_name) - # - # for uid in array_uid: - # node = get_node_by_uid(uid) - return True - def node_self_build(self, updated_node): - object = {'self_node': {}, + """The function returns the node with updated fields and relationships""" + def build_node(self, data): + node = {'self_node': {}, 'relationships': {}} - for property in updated_node.keys(): - if isinstance(updated_node[property], str): - object['self_node'][property] = updated_node[property] - elif isinstance(updated_node[property], dict): - object['relationships'][property] = [] - object['relationships'][property].append(updated_node[property]) - elif isinstance(updated_node[property], list): + for property in data.keys(): + if isinstance(data[property], str): + node['self_node'][property] = data[property] + elif isinstance(data[property], dict): + node['relationships'][property] = [] + node['relationships'][property].append(data[property]) + elif isinstance(data[property], list): relationships = [] - for element in updated_node[property]: + for element in data[property]: relationships.append(element) - object['relationships'][property] = relationships - return object + node['relationships'][property] = relationships + return node + """The function returns entity's fields of type date""" def __get_field_of_type_date(self): result = [] get_schema = self.getSchema() @@ -146,10 +148,3 @@ def __get_field_of_type_date(self): result.append(field["title"]) return result - # def get_labels(target, base_class): - # return ( - # c.__name__ - # for c in target.__mro__ - # if issubclass(c, base_class) - # ) - diff --git a/src/Routes/mongo.py b/src/Routes/mongo.py index 4ebbd8f4f..f9594eb65 100644 --- a/src/Routes/mongo.py +++ b/src/Routes/mongo.py @@ -1,18 +1,22 @@ import json from datetime import datetime -from pymongo import MongoClient -import argparse +from pymongo import MongoClient, uri_parser -parser = argparse.ArgumentParser(description="Starts the archgraph server.") -parser.add_argument("--mongodb", nargs="?", help="Address of the mongodb server") -parser.add_argument("--neo4j", nargs="?", help="Address of the neo4j server") -args = parser.parse_args() +import src.Utils.ArgParser as ArgParser +args = ArgParser.parse() -if args.mongodb is not None: +MONGODB_URL = "mongodb://root:rootpassword@localhost:27017" + +if args.mongodb is not None and args.mongodb != "": + # mongodb_arguments = uri_parser.parse_uri(args.mongodb) + # client = MongoClient(host=mongodb_arguments.nodelist.first(), + # port= mongodb_arguments.port, + # username=mongodb_arguments.username, + # password=mongodb_arguments.password, + # server_selection_timeout=1 + # ) MONGODB_URL = args.mongodb -else: - MONGODB_URL = "mongodb://root:rootpassword@localhost:27017" client = MongoClient(MONGODB_URL) db = client.mydatabase diff --git a/src/Routes/routes.py b/src/Routes/routes.py index 7bca55fa5..4b418783e 100644 --- a/src/Routes/routes.py +++ b/src/Routes/routes.py @@ -1,7 +1,6 @@ import json from pathlib import Path import os, sys -import argparse # returns the project root path (assumes that the script is started from src/Routes/routes.py) @@ -15,10 +14,6 @@ def get_project_root(): print("Archgraph running at " + get_project_root().as_posix()) sys.path.append(get_project_root().as_posix()) -parser = argparse.ArgumentParser(description="Starts the archgraph server.") -parser.add_argument("--neo4j", nargs="?", help="Address of the neo4j server") -parser.add_argument("--mongodb", nargs="?", help="Address of the mongodb server") -args = parser.parse_args() from flask import Flask, Response, jsonify, make_response, request, send_from_directory @@ -28,20 +23,35 @@ def get_project_root(): from src.Utils.JsonEncoder import search_cidoc, search_specific_cidoc from src.Utils.Utils import get_node_by_uid, build_next_json, updated_node, make_result -if args.neo4j: +import src.Utils.ArgParser as ArgParser +args = ArgParser.parse() + +if args.neo4j and args.neo4j != "": config.DATABASE_URL = args.neo4j else: config.DATABASE_URL = "bolt://neo4j:password@localhost:7687" -from src.Routes.mongo import insert_template_in_mongo, get_all_records_from_collection, get_schema_from_mongo, \ - get_templates_from_mongo_by_classes_name +from src.Routes.mongo import insert_template_in_mongo, get_all_records_from_collection, get_schema_from_mongo, get_templates_from_mongo_by_classes_name app = Flask(__name__) CORS(app) cors = CORS(app, resources={r"/*": {"origins": "*"}}) app = Flask(__name__, static_url_path="") +app.debug = True + +@app.before_request +def log_request_info(): + app.logger.debug('Headers: %s', request.headers) + app.logger.debug('Body: %s', request.get_data()) +@app.after_request +def after(response): + # todo with response + print(response.status) + print(response.headers) + print(response.get_data()) + return response @app.route("/favicon.ico") def favicon(): @@ -234,6 +244,9 @@ def search_specific(class_name, query): # json = read_file("../Utils/defaultTemplates.json") # populate_template_collection(json) # get_all_records_from_collection("createdTemplate") - if __name__ == "__main__": - app.run(host='127.0.0.1') + if args.host is not None and args.host != "": + app.logger.debug('Archgraph running with a custom host setting: %s', args.host) + app.run(host=args.host) + else: + app.run(host='127.0.0.1') diff --git a/src/Utils/ArgParser.py b/src/Utils/ArgParser.py new file mode 100644 index 000000000..2ec8fb9a9 --- /dev/null +++ b/src/Utils/ArgParser.py @@ -0,0 +1,16 @@ +import argparse + + +def parse(): + parser = argparse.ArgumentParser(description="Starts the archgraph server.") + parser.add_argument("--mongodb", nargs="?", help="Address of the mongodb server") + parser.add_argument("--neo4j", nargs="?", help="Address of the neo4j server") + parser.add_argument("--host", nargs="?", help="Address of the neo4j server") + + args = parser.parse_args() + + return args + + +class ArgParser: + pass diff --git a/src/Utils/Utils.py b/src/Utils/Utils.py index ff0eac9d0..6790a85d8 100644 --- a/src/Utils/Utils.py +++ b/src/Utils/Utils.py @@ -41,9 +41,12 @@ E10_Transfer_of_CustodySchema from src.Models.CRM.v5_0_2.NodeEntities.E11_Modification import E11_Modification, E11_ModificationSchema from src.Models.CRM.v5_0_2.NodeEntities.E12_Production import E12_Production, E12_ProductionSchema -from src.Models.CRM.v5_0_2.NodeEntities.E13_Attribute_Assignment import E13_Attribute_Assignment, E13_Attribute_AssignmentSchema -from src.Models.CRM.v5_0_2.NodeEntities.E14_Condition_Assessment import E14_Condition_Assessment, E14_Condition_AssessmentSchema -from src.Models.CRM.v5_0_2.NodeEntities.E15_Identifier_Assignment import E15_Identifier_Assignment, E15_Identifier_AssignmentSchema +from src.Models.CRM.v5_0_2.NodeEntities.E13_Attribute_Assignment import E13_Attribute_Assignment, \ + E13_Attribute_AssignmentSchema +from src.Models.CRM.v5_0_2.NodeEntities.E14_Condition_Assessment import E14_Condition_Assessment, \ + E14_Condition_AssessmentSchema +from src.Models.CRM.v5_0_2.NodeEntities.E15_Identifier_Assignment import E15_Identifier_Assignment, \ + E15_Identifier_AssignmentSchema from src.Models.CRM.v5_0_2.NodeEntities.E16_Measurement import E16_Measurement, E16_MeasurementSchema from src.Models.CRM.v5_0_2.NodeEntities.E17_Type_Assignment import E17_Type_Assignment, E17_Type_AssignmentSchema from src.Models.CRM.v5_0_2.NodeEntities.E18_Physical_Thing import E18_Physical_Thing, E18_Physical_ThingSchema @@ -51,15 +54,19 @@ from src.Models.CRM.v5_0_2.NodeEntities.E20_Biological_Object import E20_Biological_Object, E20_Biological_ObjectSchema from src.Models.CRM.v5_0_2.NodeEntities.E21_Person import E21_Person, E21_PersonSchema from src.Models.CRM.v5_0_2.NodeEntities.E22_Human_Made_Object import E22_Human_Made_Object, E22_Human_Made_ObjectSchema -from src.Models.CRM.v5_0_2.NodeEntities.E24_Physical_Human_Made_Thing import E24_Physical_Human_Made_Thing, E24_Physical_Human_Made_ThingSchema -from src.Models.CRM.v5_0_2.NodeEntities.E25_Human_Made_Feature import E25_Human_Made_Feature, E25_Human_Made_FeatureSchema +from src.Models.CRM.v5_0_2.NodeEntities.E24_Physical_Human_Made_Thing import E24_Physical_Human_Made_Thing, \ + E24_Physical_Human_Made_ThingSchema +from src.Models.CRM.v5_0_2.NodeEntities.E25_Human_Made_Feature import E25_Human_Made_Feature, \ + E25_Human_Made_FeatureSchema from src.Models.CRM.v5_0_2.NodeEntities.E26_Physical_Feature import E26_Physical_Feature, E26_Physical_FeatureSchema from src.Models.CRM.v5_0_2.NodeEntities.E27_Site import E27_Site, E27_SiteSchema from src.Models.CRM.v5_0_2.NodeEntities.E28_Conceptual_Object import E28_Conceptual_Object, E28_Conceptual_ObjectSchema -from src.Models.CRM.v5_0_2.NodeEntities.E29_Design_or_Procedure import E29_Design_or_Procedure, E29_Design_or_ProcedureSchema +from src.Models.CRM.v5_0_2.NodeEntities.E29_Design_or_Procedure import E29_Design_or_Procedure, \ + E29_Design_or_ProcedureSchema from src.Models.CRM.v5_0_2.NodeEntities.E30_Right import E30_Right, E30_RightSchema from src.Models.CRM.v5_0_2.NodeEntities.E31_Document import E31_Document, E31_DocumentSchema -from src.Models.CRM.v5_0_2.NodeEntities.E32_Authority_Document import E32_Authority_Document, E32_Authority_DocumentSchema +from src.Models.CRM.v5_0_2.NodeEntities.E32_Authority_Document import E32_Authority_Document, \ + E32_Authority_DocumentSchema from src.Models.CRM.v5_0_2.NodeEntities.E33_Linguistic_Object import E33_Linguistic_Object, E33_Linguistic_ObjectSchema from src.Models.CRM.v5_0_2.NodeEntities.E34_Inscription import E34_Inscription, E34_InscriptionSchema from src.Models.CRM.v5_0_2.NodeEntities.E35_Title import E35_Title, E35_TitleSchema @@ -75,7 +82,8 @@ from src.Models.CRM.v5_0_2.NodeEntities.E56_Language import E56_Language, E56_LanguageSchema from src.Models.CRM.v5_0_2.NodeEntities.E57_Material import E57_Material, E57_MaterialSchema from src.Models.CRM.v5_0_2.NodeEntities.E58_Measurement_Unit import E58_Measurement_Unit, E58_Measurement_UnitSchema -from src.Models.CRM.v5_0_2.NodeEntities.E63_Beggining_of_Existence import E63_Beggining_of_Existence, E63_Beggining_of_ExistenceSchema +from src.Models.CRM.v5_0_2.NodeEntities.E63_Beggining_of_Existence import E63_Beggining_of_Existence, \ + E63_Beggining_of_ExistenceSchema from src.Models.CRM.v5_0_2.NodeEntities.E64_End_of_Existence import E64_End_of_Existence, E64_End_of_ExistenceSchema from src.Models.CRM.v5_0_2.NodeEntities.E65_Creation import E65_Creation, E65_CreationSchema from src.Models.CRM.v5_0_2.NodeEntities.E66_Formation import E66_Formation, E66_FormationSchema @@ -85,7 +93,8 @@ from src.Models.CRM.v5_0_2.NodeEntities.E70_Thing import E70_Thing, E70_ThingSchema from src.Models.CRM.v5_0_2.NodeEntities.E71_Human_Made_Thing import E71_Human_Made_Thing, E71_Human_Made_ThingSchema from src.Models.CRM.v5_0_2.NodeEntities.E72_Legal_Object import E72_Legal_Object, E72_Legal_ObjectSchema -from src.Models.CRM.v5_0_2.NodeEntities.E73_Information_Object import E73_Information_Object, E73_Information_ObjectSchema +from src.Models.CRM.v5_0_2.NodeEntities.E73_Information_Object import E73_Information_Object, \ + E73_Information_ObjectSchema from src.Models.CRM.v5_0_2.NodeEntities.E74_Group import E74_Group, E74_GroupSchema from src.Models.CRM.v5_0_2.NodeEntities.E77_Persistent_Item import E77_Persistent_Item, E77_Persistent_ItemSchema from src.Models.CRM.v5_0_2.NodeEntities.E78_Curated_Holding import E78_Curated_Holding, E78_Curated_HoldingSchema @@ -96,7 +105,8 @@ from src.Models.CRM.v5_0_2.NodeEntities.E85_Joining import E85_Joining, E85_JoiningSchema from src.Models.CRM.v5_0_2.NodeEntities.E86_Leaving import E86_Leaving, E86_LeavingSchema from src.Models.CRM.v5_0_2.NodeEntities.E87_Curation_Activity import E87_Curation_Activity, E87_Curation_ActivitySchema -from src.Models.CRM.v5_0_2.NodeEntities.E89_Propositional_Object import E89_Propositional_Object, E89_Propositional_ObjectSchema +from src.Models.CRM.v5_0_2.NodeEntities.E89_Propositional_Object import E89_Propositional_Object, \ + E89_Propositional_ObjectSchema from src.Models.CRM.v5_0_2.NodeEntities.E90_Symbolic_Object import E90_Symbolic_Object, E90_Symbolic_ObjectSchema from src.Models.CRM.v5_0_2.NodeEntities.E92_Spacetime_Volume import E92_Spacetime_Volume, E92_Spacetime_VolumeSchema from src.Models.CRM.v5_0_2.NodeEntities.E93_Presence import E93_Presence, E93_PresenceSchema @@ -117,8 +127,8 @@ def get_driver(): return self.driver -# reads all relation of a node with a given name def read_relationships(search_node, search_node_uid, relationship_name): + """The function reads all relation of a node with a given name""" def read(tx, search_node, search_node_uid, relationship_name): array_uids = [] records = tx.run( @@ -142,8 +152,8 @@ def read(tx, search_node, search_node_uid, relationship_name): ) -# builds information block for a node with a given template def build_next_json(node, template): + """The function builds information block for a node with a given template""" if isinstance(template, str): return node.decodeJSON() @@ -181,8 +191,8 @@ def build_next_json(node, template): return dict(node.decodeJSON(), **new_object) -# get node from database with a given uid def get_node_by_uid(uid): + """The function get node from database with a given uid""" try: return DataObject.nodes.get(uid=uid) except: @@ -192,8 +202,8 @@ def get_node_by_uid(uid): return None -# delete node from database with a given uid def delete_node_by_uid(uid): + """The function delete node from database with a given uid""" try: node = DataObject.nodes.get(uid=uid) node.delete() @@ -207,8 +217,8 @@ def delete_node_by_uid(uid): return None -# given a template and a node, the node and next nodes information is updated def updated_node(node, data, template): + """The function given a template and a node, the node and next nodes information is updated""" db.begin() result = updated_node_aux(node, data, template[list(template.keys())[0]]) if result is None: @@ -219,9 +229,9 @@ def updated_node(node, data, template): return True -# auxiliary function - given a template and a node, the node and next nodes information is updated def updated_node_aux(current_node, data, template): - new_node = current_node.node_self_build(data) + """Auxiliary function - The function given a template and a node, the node and next nodes information is updated""" + new_node = current_node.build_node(data) if current_node.merge_node(new_node['self_node']): for relationship_name in template: relationship_of_node = getattr(current_node, relationship_name) @@ -237,8 +247,9 @@ def updated_node_aux(current_node, data, template): return None -# given a template and the current node, the function add all relations to the current node def add_all_relationships(relationships, node, template): + """The function given a template and the current node, the function add all relations to the current node""" + def update_node_and_call_next(new_instance, next_node, template): for attr in next_node: if new_instance.schema.fields[attr].__class__ == fields.Date: @@ -285,8 +296,8 @@ def make_result(result): return response_array -# given a classes name array, the function return the class instance def find_name_of_classes_in_project(classes_name): + """The function given a classes name array, the function return the class instance""" classes = [] error = False for class_name in classes_name: @@ -316,8 +327,8 @@ def find_name_of_classes_in_project(classes_name): return classes -# given a model class names array, the function return the schema class instance def find_name_of_schema_classes_in_project(classes_name): + """The function given a model class names array, the function return the schema class instance""" schemas_classes = [] error = False diff --git a/test/Unit/test_relations.py b/test/Unit/test_relations.py index 172ee2abd..4961c7443 100644 --- a/test/Unit/test_relations.py +++ b/test/Unit/test_relations.py @@ -507,5 +507,4 @@ def test_insert_template(self): templates_E2 = [{"classes_name": class_name_E2, "template": template_E2, "schema": json.dumps(schemaE2)}] insert_default_templates(templates_E2) - get_all_records_from_collection("defaultTemplate")