diff --git a/drf_spectacular/openapi.py b/drf_spectacular/openapi.py index ff0e5e36..ed00a828 100644 --- a/drf_spectacular/openapi.py +++ b/drf_spectacular/openapi.py @@ -221,14 +221,18 @@ def _process_override_parameters(self, direction='request'): parameter = force_instance(parameter) mapped = self._map_serializer(parameter, 'request') for property_name, property_schema in mapped['properties'].items(): - field = parameter.fields.get(property_name) + try: + # be graceful when serializer might be non-DRF (via extension). + field = parameter.fields.get(property_name) + except Exception: + field = None result[property_name, OpenApiParameter.QUERY] = build_parameter_type( name=property_name, schema=property_schema, description=property_schema.pop('description', None), location=OpenApiParameter.QUERY, allow_blank=getattr(field, 'allow_blank', True), - required=field.required, + required=bool(property_name in mapped.get('required', [])), ) else: warn(f'could not resolve parameter annotation {parameter}. Skipping.') diff --git a/tests/contrib/test_pydantic.py b/tests/contrib/test_pydantic.py index 337d4ca4..49ade8cc 100644 --- a/tests/contrib/test_pydantic.py +++ b/tests/contrib/test_pydantic.py @@ -45,3 +45,22 @@ def post(self, request): schema = generate_schema('/x', view=XAPIView) assert_schema(schema, 'tests/contrib/test_pydantic.yml') + + +@pytest.mark.contrib('pydantic') +@pytest.mark.skipif(sys.version_info < (3, 7), reason='python 3.7+ is required by package') +def test_pydantic_as_query_parameters(no_warnings): + class QueryParams(BaseModel): + foo: int + bar: str + + class XAPIView(APIView): + @extend_schema(responses=str, parameters=[QueryParams]) + def get(self, request): + pass # pragma: no cover + + schema = generate_schema('/x', view=XAPIView) + assert schema['paths']['/x']['get']['parameters'] == [ + {'in': 'query', 'name': 'bar', 'required': True, 'schema': {'title': 'Bar', 'type': 'string'}}, + {'in': 'query', 'name': 'foo', 'required': True, 'schema': {'title': 'Foo', 'type': 'integer'}} + ]