Source code for nautilus.api.util.walk_query

[docs]async def walk_query(obj, object_resolver, connection_resolver, errors, current_user=None, __naut_name=None, obey_auth=True, **filters): """ This function traverses a query and collects the corresponding information in a dictionary. """ # if the object has no selection set if not hasattr(obj, 'selection_set'): # yell loudly raise ValueError("Can only resolve objects, not primitive types") # the name of the node node_name = __naut_name or obj.name.value if obj.name else obj.operation # the selected fields selection_set = obj.selection_set.selections def _build_arg_tree(arg): """ This function recursively builds the arguments for lists and single values """ # TODO: what about object arguments?? # if there is a single value if hasattr(arg, 'value'): # assign the value to the filter return arg.value # otherwise if there are multiple values for the argument elif hasattr(arg, 'values'): return [_build_arg_tree(node) for node in arg.values] # for each argument on this node for arg in obj.arguments: # add it to the query filters filters[arg.name.value] = _build_arg_tree(arg.value) # the fields we have to ask for fields = [field for field in selection_set if not field.selection_set] # the links between objects connections = [field for field in selection_set if field.selection_set] try: # resolve the model with the given fields models = await object_resolver(node_name, [field.name.value for field in fields], current_user=current_user, obey_auth=obey_auth, **filters) # if something went wrong resolving the object except Exception as e: # add the error as a string errors.append(e.__str__()) # stop here return None # add connections to each matching model for model in models: # if is an id for the model if 'pk' in model: # for each connection for connection in connections: # the name of the connection connection_name = connection.name.value # the target of the connection node = { 'name': node_name, 'pk': model['pk'] } try: # go through the connection connected_ids, next_target = await connection_resolver( connection_name, node, ) # if there are connections if connected_ids: # add the id filter to the list filters['pk_in'] = connected_ids # add the connection field value = await walk_query( connection, object_resolver, connection_resolver, errors, current_user=current_user, obey_auth=obey_auth, __naut_name=next_target, **filters ) # there were no connections else: value = [] # if something went wrong except Exception as e: # add the error as a string errors.append(e.__str__()) # stop here value = None # set the connection to the appropriate value model[connection_name] = value # return the list of matching models return models