def _resolve_path_parameters(self, variables): parameters = [] for variable in variables: schema = build_basic_type(OpenApiTypes.STR) description = '' resolved_parameter = resolve_regex_path_parameter( self.path_regex, variable, self.map_renderers('format'), ) if resolved_parameter: schema = resolved_parameter['schema'] elif get_view_model(self.view) is None: warn( f'could not derive type of path parameter "{variable}" because because it ' f'is untyped and obtaining queryset from {self.view.__class__} failed. ' f'consider adding a type to the path (e.g. <int:{variable}>) or annotating ' f'the parameter type with @extend_schema. defaulting to "string".' ) else: try: model = get_view_model(self.view) model_field = model._meta.get_field(variable) schema = self._map_model_field(model_field, direction=None) # strip irrelevant meta data irrelevant_field_meta = [ 'readOnly', 'writeOnly', 'nullable', 'default' ] schema = { k: v for k, v in schema.items() if k not in irrelevant_field_meta } if 'description' not in schema and model_field.primary_key: description = get_pk_description(model, model_field) except django_exceptions.FieldDoesNotExist: warn( f'could not derive type of path parameter "{variable}" because ' f'model "{model}" did contain no such field. consider annotating ' f'parameter with @extend_schema. defaulting to "string".' ) parameters.append( build_parameter_type(name=variable, location=OpenApiParameter.PATH, description=description, schema=schema)) return parameters
def get_schema_operation_parameters(self, auto_schema, *args, **kwargs): if issubclass(self.target_class, SpectacularDjangoFilterBackendMixin): warn( 'DEPRECATED - Spectacular\'s DjangoFilterBackend is superseded by extension. you ' 'can simply restore this to the original class, extensions will take care of the ' 'rest.') 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 [] parameters = [] for field_name, field in filterset_class.base_filters.items(): schema, description, enum = (self.resolve_filter_field( auto_schema, model, filterset_class, field)) parameters.append( build_parameter_type( name=field_name, required=field.extra['required'], location=OpenApiParameter.QUERY, description=description, schema=schema, enum=enum, )) return parameters
def get_schema_operation_parameters(self, auto_schema, *args, **kwargs): if issubclass(self.target_class, SpectacularDjangoFilterBackendMixin): warn( 'DEPRECATED - Spectacular\'s DjangoFilterBackend is superseded by extension. you ' 'can simply restore this to the original class, extensions will take care of the ' 'rest.') 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 [] parameters = [] for field_name, field in filterset_class.base_filters.items(): path = field.field_name.split('__') model_field = follow_field_source(model, path) parameters.append( build_parameter_type( name=field_name, required=field.extra['required'], location=OpenApiParameter.QUERY, description=field.label if field.label is not None else field_name, schema=auto_schema._map_model_field(model_field, direction=None), enum=[c for c, _ in field.extra.get('choices', [])], )) return parameters
def get_schema_operation_parameters(self, view): model = get_view_model(view) if not model: return [] filterset_class = self.get_filterset_class(view, model.objects.none()) if not filterset_class: return [] parameters = [] for field_name, field in filterset_class.base_filters.items(): path = field.field_name.split('__') model_field = follow_field_source(model, path) parameters.append( build_parameter_type( name=field_name, required=field.extra['required'], location=OpenApiParameter.QUERY, description=field.label if field.label is not None else field_name, schema=view.schema._map_model_field(model_field, direction=None), enum=[c for c, _ in field.extra.get('choices', [])], )) return parameters
def coerce_path(self, path, method, view): """ Customized coerce_path which also considers the `_pk` suffix in URL paths of nested routers. """ path = super().coerce_path(path, method, view) # take care of {pk} model = get_view_model(view, emit_warnings=False) if not self.coerce_path_pk or not model: return path for match in RELATED_MODEL_PARAMETER_RE.findall(path): if hasattr(model, match): path = path.replace(f'{match}_pk', f'{match}_id') return path
def _resolve_path_parameters(self, variables): object_path = "uuid" if variables == [object_path] and self.view.basename == "object": model = get_view_model(self.view) object_field = model._meta.get_field("object") uuid_field = object_field.related_model._meta.get_field("uuid") schema = self._map_model_field(uuid_field, direction=None) return [ build_parameter_type(name=object_path, location=OpenApiParameter.PATH, schema=schema) ] return super()._resolve_path_parameters(variables)
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 = [] 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
def get_schema_operation_parameters(self, auto_schema, *args, **kwargs): if issubclass(self.target_class, SpectacularDjangoFilterBackendMixin): warn( 'DEPRECATED - Spectacular\'s DjangoFilterBackend is superseded by extension. you ' 'can simply restore this to the original class, extensions will take care of the ' 'rest.') 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 [] return [ self.resolve_filter_field(auto_schema, model, filterset_class, field_name, filter_field) for field_name, filter_field in filterset_class.base_filters.items() ]