-
Notifications
You must be signed in to change notification settings - Fork 255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
is_patched_serializer
fails with DictField
#413
Comments
hi. i cannot reproduce this issue. also this does not look like the newest version. the following example has worked for me. def test_list_dict_field(no_warnings):
class XAPIView(APIView):
@extend_schema(responses=serializers.ListSerializer(child=serializers.DictField()))
def get(self, request):
pass # pragma: no cover
schema = generate_schema('x', view=XAPIView) |
Thanks for the example. That helped me write the reproduction test. The problem manifests itself for a def test_list_dict_field(no_warnings):
from django.urls import path
from drf_spectacular.generators import SchemaGenerator
from drf_spectacular.utils import extend_schema
from drf_spectacular.validation import validate_schema
from rest_framework.generics import ListAPIView
from rest_framework.serializers import DictField, ListSerializer
class XAPIView(ListAPIView):
@extend_schema(responses=ListSerializer(child=DictField()))
def get(self, request):
pass # pragma: no cover
generator = SchemaGenerator(patterns=[path('v1/x', XAPIView.as_view())])
schema = generator.get_schema(request=None, public=True)
validate_schema(schema) |
hey @mblayman, i still cannot reproduce the issue. at least on the current are you using the most recent version there? although i cannot remember any fixes there in the past couple of releases. |
We weren't when I reported this. I can try again on 0.17.0 (hopefully later today) and report if I can replicate the issue still. |
I ran this same test that I have above with 0.17.0 and it still fails for me. Is there anything else I could provide to help replicate this? def test_list_dict_field(no_warnings):
from django.urls import path
from drf_spectacular.generators import SchemaGenerator
from drf_spectacular.utils import extend_schema
from drf_spectacular.validation import validate_schema
from rest_framework.generics import ListAPIView
from rest_framework.serializers import DictField, ListSerializer
class XAPIView(ListAPIView):
@extend_schema(responses=ListSerializer(child=DictField()))
def get(self, request):
pass # pragma: no cover
generator = SchemaGenerator(patterns=[path('v1/x', XAPIView.as_view())])
> schema = generator.get_schema(request=None, public=True)
bhps/tests/test_views.py:1952:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.7/site-packages/drf_spectacular/generators.py:257: in get_schema
paths=self.parse(request, public),
/usr/local/lib/python3.7/site-packages/drf_spectacular/generators.py:232: in parse
path, path_regex, path_prefix, method, self.registry
/usr/local/lib/python3.7/site-packages/drf_spectacular/utils.py:274: in get_operation
return super().get_operation(path, path_regex, path_prefix, method, registry)
/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py:84: in get_operation
operation['responses'] = self._get_response_bodies()
/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py:1001: in _get_response_bodies
return {'200': self._get_response_for_code(response_serializers, '200')}
/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py:1075: in _get_response_for_code
paginated_name = f'Paginated{self._get_serializer_name(serializer, "response")}List'
/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py:1155: in _get_serializer_name
return self._get_serializer_name(serializer.child, direction)
/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py:1162: in _get_serializer_name
if is_patched_serializer(serializer, direction):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
serializer = DictField(), direction = 'response'
def is_patched_serializer(serializer, direction):
return bool(
spectacular_settings.COMPONENT_SPLIT_PATCH
> and serializer.partial
and not serializer.read_only
and not (spectacular_settings.COMPONENT_SPLIT_REQUEST and direction == 'response')
)
E AttributeError: 'DictField' object has no attribute 'partial'
/usr/local/lib/python3.7/site-packages/drf_spectacular/plumbing.py:97: AttributeError |
the stacktrace contains a line that is only reached by using pagination. Since you have no pagination class in your example, i have to assume that you have a global default setting. with a added pagination class i can reproduce the error. |
That's right. We're using the REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
...
} |
that was a small but important detail |
so i analyzed this issue. it's definitely an edge case. in theory this is not supported. theoretically the more correct version would have been on the other hand i can see the need for this. since there is no other way expressing what you need and its a very reasonable ask, i think it's acceptable to be lenient here and "do the right thing" even though it would be technically incorrect. |
strictly speaking this is not correct but it's the only way to specify a unnamed list with extend_schema. also the unpaginated version we do already support.
this should fix it. i also noticed that we support this for unpaginated endpoints. so having parity again is another benefit. |
Thank you for digging into this and fixing it up. I appreciate your attention to detail. |
closing this issue for now. feel free to comment if anything is missing or not working and we will follow-up. |
Describe the bug
My team has a list endpoint that returns a dictionary values that are generated by methods that aren't serializers. We'd like to document at least that this endpoint returns a list of objects. I tried adding the following
extend_schema
:drf-spectacular raised the following exception:
Expected behavior
Since this should be a valid serializer (test proving that is below), I'd expect the
is_patched_serializer
to handle aDictField
.The text was updated successfully, but these errors were encountered: