Skip to content

Commit

Permalink
Merge pull request #1237 from w00kie/nested-pagination
Browse files Browse the repository at this point in the history
handle examples with nested properties pagination
  • Loading branch information
tfranzel authored May 16, 2024
2 parents 9730d39 + a0b0ce6 commit 2501bfd
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 4 deletions.
16 changes: 12 additions & 4 deletions drf_spectacular/plumbing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1416,11 +1416,19 @@ def build_listed_example_value(value: Any, paginator, direction):
if schema is sentinel:
return [value]

def drilldown_schema_example(schema, sentinel):
# Recursively travel schema properties to build example.
if schema is sentinel:
return [value]
if 'properties' in schema.keys():
return {
field_name: drilldown_schema_example(field_schema, sentinel)
for field_name, field_schema in schema['properties'].items()
}
return schema['example']

try:
return {
field_name: [value] if field_schema is sentinel else field_schema['example']
for field_name, field_schema in schema['properties'].items()
}
return drilldown_schema_example(schema, sentinel)
except (AttributeError, KeyError):
warn(
f"OpenApiExample could not be paginated because {paginator.__class__} either "
Expand Down
57 changes: 57 additions & 0 deletions tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,62 @@ class PaginatedExamplesViewSet(ExampleTestWithExtendedViewSet):
}


@pytest.mark.skipif(DRF_VERSION < '3.12', reason='DRF pagination schema broken')
def test_example_nested_pagination(no_warnings):
class NestedPagination(pagination.LimitOffsetPagination):
def get_paginated_response_schema(self, schema):
return {
'type': 'object',
'required': ['pagination', 'results'],
'properties': {
'pagination': {
'type': 'object',
'required': ['next', 'previous'],
'properties': {
'count': {
'type': 'integer',
'example': 123,
},
'next': {
'type': 'string',
'nullable': True,
'format': 'uri',
'example': 'http://api.example.org/accounts/?{offset_prm}=400&{limit_prm}=100'.format(
offset_prm=self.offset_query_param, limit_prm=self.limit_query_param),
},
'previous': {
'type': 'string',
'nullable': True,
'format': 'uri',
'example': 'http://api.example.org/accounts/?{offset_prm}=200&{limit_prm}=100'.format(
offset_prm=self.offset_query_param, limit_prm=self.limit_query_param),
},
}
},
'results': schema,
},
}

class PaginatedExamplesViewSet(ExampleTestWithExtendedViewSet):
pagination_class = NestedPagination

schema = generate_schema('e', PaginatedExamplesViewSet)
operation = schema['paths']['/e/']['get']
assert operation['responses']['200']['content']['application/json']['examples'] == {
'SerializerCExampleRO': {
'value': {
'pagination': {
'count': 123,
'next': 'http://api.example.org/accounts/?offset=400&limit=100',
'previous': 'http://api.example.org/accounts/?offset=200&limit=100',
},
'results': [{'field': 111}],
},
'summary': 'Serializer C Example RO'
}
}


def test_example_request_response_listed_examples(no_warnings):
@extend_schema(
request=ASerializer(many=True),
Expand Down Expand Up @@ -306,6 +362,7 @@ def test_plain_pagination_example(no_warnings):

class PlainPagination(pagination.LimitOffsetPagination):
""" return a (unpaginated) basic list, while other might happen in the headers """

def get_paginated_response_schema(self, schema):
return schema

Expand Down

0 comments on commit 2501bfd

Please sign in to comment.