Skip to content

Commit 3c0d17c

Browse files
committed
Adjust ManualSchema to take fields
… and `description`. Allows `url` and `action` to remain dynamic
1 parent 21b4d78 commit 3c0d17c

File tree

3 files changed

+102
-26
lines changed

3 files changed

+102
-26
lines changed

docs/api-guide/schemas.md

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -199,17 +199,28 @@ To customise the `Link` generation you may:
199199

200200
This provides complete control over view introspection.
201201

202-
* Instantiate `ManualSchema` on your view, providing the Core API `Link`
203-
explicitly:
202+
* Instantiate `ManualSchema` on your view, providing the Core API `Fields` for
203+
the view explicitly:
204204

205205
from rest_framework.views import APIView
206206
from rest_framework.schemas import ManualSchema
207207

208208
class CustomView(APIView):
209209
...
210-
schema = ManualSchema(
211-
coreapi.Link(...)
212-
)
210+
schema = ManualSchema(fields=[
211+
coreapi.Field(
212+
"first_field",
213+
required=True,
214+
location="path",
215+
schema=coreschema.String()
216+
),
217+
coreapi.Field(
218+
"second_field",
219+
required=True,
220+
location="path",
221+
schema=coreschema.String()
222+
),
223+
])
213224

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

581592
## ManualSchema
582593

583-
Allows specifying a manual schema for a view:
594+
Allows manually providing a list of `coreapi.Field` instances for the schema,
595+
plus an optional description.
584596

585597
class MyView(APIView):
586-
schema = ManualSchema(coreapi.Link(
587-
url='/example/',
588-
action='get',
589-
fields=[]
590-
))
591-
592-
The `ManualSchema` constructor takes a single parameter `link`,
593-
the `coreapi.Link` instance for the view.
598+
schema = ManualSchema(fields=[
599+
coreapi.Field(
600+
"first_field",
601+
required=True,
602+
location="path",
603+
schema=coreschema.String()
604+
),
605+
coreapi.Field(
606+
"second_field",
607+
required=True,
608+
location="path",
609+
schema=coreschema.String()
610+
),
611+
]
612+
)
613+
614+
The `ManualSchema` constructor takes two arguments:
615+
616+
**`fields`**: A list of `coreapi.Field` instances. Required.
617+
618+
**`description`**: A string description. Optional.
594619

595620
---
596621

rest_framework/schemas/inspectors.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -364,11 +364,31 @@ def get_encoding(self, path, method):
364364

365365
class ManualSchema(ViewInspector):
366366
"""
367-
Overrides get_link to return manually specified schema.
367+
Allows providing a list of coreapi.Fields,
368+
plus an optional description.
368369
"""
369-
def __init__(self, link):
370-
assert isinstance(link, coreapi.Link)
371-
self._link = link
370+
def __init__(self, fields, description=''):
371+
"""
372+
Parameters:
373+
374+
* `fields`: list of `coreapi.Field` instances.
375+
* `descripton`: String description for view. Optional.
376+
"""
377+
assert all(isinstance(f, coreapi.Field) for f in fields), "`fields` must be a list of coreapi.Field instances"
378+
self._fields = fields
379+
self._description = description
380+
381+
def get_link(self, path, method, base_url):
382+
383+
if base_url and path.startswith('/'):
384+
path = path[1:]
385+
386+
return coreapi.Link(
387+
url=urlparse.urljoin(base_url, path),
388+
action=method.lower(),
389+
encoding=None,
390+
fields=self._fields,
391+
description=self._description
392+
)
372393

373-
def get_link(self, *args):
374394
return self._link

tests/test_schemas.py

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -534,15 +534,46 @@ class CustomView(APIView):
534534

535535
def test_view_with_manual_schema(self):
536536

537-
expected = coreapi.Link(
538-
url='/example/',
539-
action='get',
540-
fields=[]
541-
)
537+
path = '/example'
538+
method = 'get'
539+
base_url = None
540+
541+
fields = [
542+
coreapi.Field(
543+
"first_field",
544+
required=True,
545+
location="path",
546+
schema=coreschema.String()
547+
),
548+
coreapi.Field(
549+
"second_field",
550+
required=True,
551+
location="path",
552+
schema=coreschema.String()
553+
),
554+
coreapi.Field(
555+
"third_field",
556+
required=True,
557+
location="path",
558+
schema=coreschema.String()
559+
),
560+
]
561+
description = "A test endpoint"
542562

543563
class CustomView(APIView):
544-
schema = ManualSchema(expected)
564+
"""
565+
ManualSchema takes list of fields for endpoint.
566+
- Provides url and action, which are always dynamic
567+
"""
568+
schema = ManualSchema(fields, description)
569+
570+
expected = coreapi.Link(
571+
url=path,
572+
action=method,
573+
fields=fields,
574+
description=description
575+
)
545576

546577
view = CustomView()
547-
link = view.schema.get_link()
578+
link = view.schema.get_link(path, method, base_url)
548579
assert link == expected

0 commit comments

Comments
 (0)