Esempio n. 1
0
 def args_selection_search(self, selection_set, variables, parent_type,
                           arg_name, arg_value):
     """Recursively search through feild/fragment selection set fields."""
     for field in selection_set.selections:
         if isinstance(field, ast.FragmentSpread):
             if field.name.value in self.visited_fragments:
                 continue
             frag_def = self.fragment_defs[field.name.value]
             frag_type = type_from_ast(self.schema, frag_def.type_condition)
             if self.args_selection_search(frag_def.selection_set,
                                           variables, frag_type, arg_name,
                                           arg_value):
                 return True
             self.visited_fragments.add(frag_def.name)
             continue
         field_def = get_field_def(self.schema, parent_type,
                                   field.name.value)
         if field_def is None:
             continue
         arg_vals = get_argument_values(field_def.args, field.arguments,
                                        variables)
         if arg_vals.get(arg_name) == arg_value:
             return True
         if field.selection_set is None:
             continue
         if self.args_selection_search(field.selection_set, variables,
                                       get_named_type(field_def.type),
                                       arg_name, arg_value):
             return True
     return False
def resolve_prefetch(
        exe_context,  # type: ExecutionContext
        operation,  # type: OperationDefinition
        root_type=None,  # type: Any
        type_=None,
        path=None,
        selection_set=None,  # type: Optional[SelectionSet]
        action_id=None):
    if path is None:
        path = []
    if type_ is None:
        type_ = get_operation_root_type(exe_context.schema, operation)
    if isinstance(type_, GraphQLList):
        type_ = type_.of_type
    if root_type is None:
        root_type = type_.graphene_type
    if selection_set is None:
        selection_set = operation.selection_set
    fields = collect_fields(exe_context, type_, selection_set,
                            DefaultOrderedDict(list), set())
    try:
        prefetch_fn = getattr(type_.graphene_type, "prefetch_fn")
    except AttributeError:
        prefetch_fn = None
    for response_name, field_asts in fields.items():
        # todo: 这里可能有bug
        field_ast = field_asts[0]
        field_name = field_ast.name.value
        try:
            field_def = get_field_def(exe_context.schema, type_, field_name)
        except:
            field_def = None
        path_name = SKIP
        if prefetch_fn:
            try:
                # 在 prefetch_fn 中进行类似于select_related prefetch_related等操作
                # 告诉orm应该加载关系
                # 返回的东西会被拼凑到path里面,如果返回SKIP,那么不会拼路径,如果不返回,那么字段名将拼凑到路径中
                new_action_id = action_id

                def set_action_id(x):
                    nonlocal new_action_id
                    new_action_id = x

                def add_prefetch_info(x):
                    exe_context.context_value["prefetch"][action_id].append(x)

                path_name = prefetch_fn(action_id=action_id,
                                        prefetch_name=field_name,
                                        prefetch_field_def=field_def,
                                        path=path,
                                        add_prefetch_info=add_prefetch_info,
                                        set_action_id=set_action_id)
            except:
                traceback.print_exc()
        if field_def and field_ast.selection_set:
            if path_name == SKIP:
                new_path = path
            else:
                new_path = path + [path_name]
            resolve_prefetch(exe_context, operation, root_type, field_def.type,
                             new_path, field_ast.selection_set, new_action_id)