Exemple #1
0
    def get_schema_operation_parameters(self, auto_schema, *args, **kwargs):
        model = get_view_model(auto_schema.view)
        if not model:
            return []

        filterset_class = self.target.get_filterset_class(
            auto_schema.view, model.objects.none())
        if not filterset_class:
            return []

        result = []
        with add_trace_message(filterset_class.__name__):
            for field_name, filter_field in filterset_class.base_filters.items(
            ):
                result += self.resolve_filter_field(auto_schema, model,
                                                    filterset_class,
                                                    field_name, filter_field)
        return result
Exemple #2
0
    def parse(self, input_request, public):
        """ Iterate endpoints generating per method path operations. """
        result = {}
        self._initialise_endpoints()
        endpoints = self._get_paths_and_endpoints(
            None if public else input_request)

        if spectacular_settings.SCHEMA_PATH_PREFIX is None:
            # estimate common path prefix if none was given. only use it if we encountered more
            # than one view to prevent emission of erroneous and unnecessary fallback names.
            non_trivial_prefix = len(
                set([view.__class__ for _, _, _, view in endpoints])) > 1
            if non_trivial_prefix:
                path_prefix = os.path.commonpath(
                    [path for path, _, _, _ in endpoints])
            else:
                path_prefix = '/'
        else:
            path_prefix = spectacular_settings.SCHEMA_PATH_PREFIX
        if not path_prefix.startswith('^'):
            path_prefix = '^' + path_prefix  # make sure regex only matches from the start

        for path, path_regex, method, view in endpoints:
            if not self.has_view_permissions(path, method, view):
                continue

            if input_request:
                request = input_request
            else:
                # mocked request to allow certain operations in get_queryset and get_serializer[_class]
                # without exceptions being raised due to no request.
                request = spectacular_settings.GET_MOCK_REQUEST(
                    method, path, view, input_request)

            view.request = request

            if view.versioning_class and not is_versioning_supported(
                    view.versioning_class):
                warn(
                    f'using unsupported versioning class "{view.versioning_class}". view will be '
                    f'processed as unversioned view.')
            elif view.versioning_class:
                version = (
                    self.api_version  # generator was explicitly versioned
                    or getattr(request, 'version',
                               None)  # incoming request was versioned
                    or view.versioning_class.default_version  # fallback
                )
                if not version:
                    continue
                path = modify_for_versioning(self.inspector.patterns, method,
                                             path, view, version)
                if not operation_matches_version(view, version):
                    continue

            assert isinstance(view.schema, AutoSchema), (
                f'Incompatible AutoSchema used on View {view.__class__}. Is DRF\'s '
                f'DEFAULT_SCHEMA_CLASS pointing to "drf_spectacular.openapi.AutoSchema" '
                f'or any other drf-spectacular compatible AutoSchema?')
            with add_trace_message(getattr(view, '__class__', view).__name__):
                operation = view.schema.get_operation(path, path_regex,
                                                      path_prefix, method,
                                                      self.registry)

            # operation was manually removed via @extend_schema
            if not operation:
                continue

            if spectacular_settings.SCHEMA_PATH_PREFIX_TRIM:
                path = re.sub(pattern=path_prefix,
                              repl='',
                              string=path,
                              flags=re.IGNORECASE)

            if not path.startswith('/'):
                path = '/' + path

            if spectacular_settings.CAMELIZE_NAMES:
                path, operation = camelize_operation(path, operation)

            result.setdefault(path, {})
            result[path][method.lower()] = operation

        return result
    def parse(self, input_request, public):
        """ Iterate endpoints generating per method path operations. """
        result = {}
        self._initialise_endpoints()

        for path, path_regex, method, view in self._get_paths_and_endpoints(
                None if public else input_request):
            if not self.has_view_permissions(path, method, view):
                continue

            if input_request:
                request = input_request
            else:
                # mocked request to allow certain operations in get_queryset and get_serializer[_class]
                # without exceptions being raised due to no request.
                request = spectacular_settings.GET_MOCK_REQUEST(
                    method, path, view, input_request)

            view.request = request

            if view.versioning_class and not is_versioning_supported(
                    view.versioning_class):
                warn(
                    f'using unsupported versioning class "{view.versioning_class}". view will be '
                    f'processed as unversioned view.')
            elif view.versioning_class:
                version = (
                    self.api_version  # generator was explicitly versioned
                    or getattr(request, 'version',
                               None)  # incoming request was versioned
                    or view.versioning_class.default_version  # fallback
                )
                if not version:
                    continue
                path = modify_for_versioning(self.inspector.patterns, method,
                                             path, view, version)
                if not operation_matches_version(view, version):
                    continue

            assert isinstance(view.schema, AutoSchema), (
                f'Incompatible AutoSchema used on View {view.__class__}. Is DRF\'s '
                f'DEFAULT_SCHEMA_CLASS pointing to "drf_spectacular.openapi.AutoSchema" '
                f'or any other drf-spectacular compatible AutoSchema?')
            if hasattr(view, '__class__'):
                trace_message = view.__class__.__name__
            elif hasattr(view, '__name__'):
                trace_message = view.__name__
            else:
                trace_message = None
            with add_trace_message(trace_message):
                operation = view.schema.get_operation(path, path_regex, method,
                                                      self.registry)

            # operation was manually removed via @extend_schema
            if not operation:
                continue

            # Normalise path for any provided mount url.
            if path.startswith('/'):
                path = path[1:]
            path = urljoin(self.url or '/', path)

            if spectacular_settings.CAMELIZE_NAMES:
                path, operation = camelize_operation(path, operation)

            result.setdefault(path, {})
            result[path][method.lower()] = operation

        return result