Skip to content

Commit

Permalink
Adjust ManualSchema to take fields
Browse files Browse the repository at this point in the history
… and `description`.

Allows `url` and `action` to remain dynamic
  • Loading branch information
carltongibson committed Sep 14, 2017
1 parent 21b4d78 commit 3c0d17c
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 26 deletions.
53 changes: 39 additions & 14 deletions docs/api-guide/schemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,17 +199,28 @@ To customise the `Link` generation you may:

This provides complete control over view introspection.

* Instantiate `ManualSchema` on your view, providing the Core API `Link`
explicitly:
* Instantiate `ManualSchema` on your view, providing the Core API `Fields` for
the view explicitly:

from rest_framework.views import APIView
from rest_framework.schemas import ManualSchema

class CustomView(APIView):
...
schema = ManualSchema(
coreapi.Link(...)
)
schema = ManualSchema(fields=[
coreapi.Field(
"first_field",
required=True,
location="path",
schema=coreschema.String()
),
coreapi.Field(
"second_field",
required=True,
location="path",
schema=coreschema.String()
),
])

This allows manually specifying the schema for some views whilst maintaining
automatic generation elsewhere.
Expand Down Expand Up @@ -580,17 +591,31 @@ Return a list of `coreapi.Link()` instances, as returned by the `get_schema_fiel

## ManualSchema

Allows specifying a manual schema for a view:
Allows manually providing a list of `coreapi.Field` instances for the schema,
plus an optional description.

class MyView(APIView):
schema = ManualSchema(coreapi.Link(
url='/example/',
action='get',
fields=[]
))

The `ManualSchema` constructor takes a single parameter `link`,
the `coreapi.Link` instance for the view.
schema = ManualSchema(fields=[
coreapi.Field(
"first_field",
required=True,
location="path",
schema=coreschema.String()
),
coreapi.Field(
"second_field",
required=True,
location="path",
schema=coreschema.String()
),
]
)

The `ManualSchema` constructor takes two arguments:

**`fields`**: A list of `coreapi.Field` instances. Required.

**`description`**: A string description. Optional.

---

Expand Down
30 changes: 25 additions & 5 deletions rest_framework/schemas/inspectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,11 +364,31 @@ def get_encoding(self, path, method):

class ManualSchema(ViewInspector):
"""
Overrides get_link to return manually specified schema.
Allows providing a list of coreapi.Fields,
plus an optional description.
"""
def __init__(self, link):
assert isinstance(link, coreapi.Link)
self._link = link
def __init__(self, fields, description=''):
"""
Parameters:
* `fields`: list of `coreapi.Field` instances.
* `descripton`: String description for view. Optional.
"""
assert all(isinstance(f, coreapi.Field) for f in fields), "`fields` must be a list of coreapi.Field instances"
self._fields = fields
self._description = description

def get_link(self, path, method, base_url):

if base_url and path.startswith('/'):
path = path[1:]

return coreapi.Link(
url=urlparse.urljoin(base_url, path),
action=method.lower(),
encoding=None,
fields=self._fields,
description=self._description
)

def get_link(self, *args):
return self._link
45 changes: 38 additions & 7 deletions tests/test_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,15 +534,46 @@ class CustomView(APIView):

def test_view_with_manual_schema(self):

expected = coreapi.Link(
url='/example/',
action='get',
fields=[]
)
path = '/example'
method = 'get'
base_url = None

fields = [
coreapi.Field(
"first_field",
required=True,
location="path",
schema=coreschema.String()
),
coreapi.Field(
"second_field",
required=True,
location="path",
schema=coreschema.String()
),
coreapi.Field(
"third_field",
required=True,
location="path",
schema=coreschema.String()
),
]
description = "A test endpoint"

class CustomView(APIView):
schema = ManualSchema(expected)
"""
ManualSchema takes list of fields for endpoint.
- Provides url and action, which are always dynamic
"""
schema = ManualSchema(fields, description)

expected = coreapi.Link(
url=path,
action=method,
fields=fields,
description=description
)

view = CustomView()
link = view.schema.get_link()
link = view.schema.get_link(path, method, base_url)
assert link == expected

0 comments on commit 3c0d17c

Please sign in to comment.