Skip to content

Commit d3620b1

Browse files
committed
Add manual_fields kwarg to AutoSchema
1 parent a803345 commit d3620b1

File tree

3 files changed

+58
-8
lines changed

3 files changed

+58
-8
lines changed

docs/api-guide/schemas.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,7 @@ appropriate Core API `Link` object for the view, request method and path:
164164
auto_schema = view.schema
165165
coreapi_link = auto_schema.get_link(...)
166166

167-
168-
(Aside: In compiling the schema, `SchemaGenerator` calls `view.schema.get_link()` for
167+
(In compiling the schema, `SchemaGenerator` calls `view.schema.get_link()` for
169168
each view, allowed method and path.)
170169

171170
To customise the `Link` generation you may:
@@ -178,9 +177,9 @@ To customise the `Link` generation you may:
178177
class CustomView(APIView):
179178
...
180179
schema = AutoSchema(
181-
manual_fields= {
182-
"extra_field": coreapi.Field(...)
183-
}
180+
manual_fields=[
181+
coreapi.Field("extra_field", ...),
182+
]
184183
)
185184

186185
This allows extension for the most common case without subclassing.
@@ -512,9 +511,22 @@ A class that deals with introspection of individual views for schema generation.
512511

513512
`AutoSchema` is attached to `APIView` via the `schema` attribute.
514513

515-
Typically you will subclass `AutoSchema` to customise schema generation
516-
and then set your subclass on your view.
514+
The `AutoSchema` constructor takes a single keyword argument `manual_fields`.
515+
516+
**`manual_fields`**: a `list` of `coreapi.Field` instances that will be added to
517+
the generated fields. Generated fields with a matching `name` will be overwritten.
517518

519+
class CustomView(APIView):
520+
schema = AutoSchema(manual_fields=[
521+
coreapi.Field(
522+
"my_extra_field",
523+
required=True,
524+
location="path",
525+
schema=coreschema.String()
526+
),
527+
])
528+
529+
For more advanced customisation subclass `AutoSchema` to customise schema generation.
518530

519531
class CustomViewSchema(AutoSchema):
520532
"""
@@ -529,10 +541,13 @@ and then set your subclass on your view.
529541
class MyView(APIView):
530542
schema = CustomViewSchema()
531543

544+
The following methods are available to override.
545+
532546
### get_link(self, path, method, base_url)
533547

534548
Returns a `coreapi.Link` instance corresponding to the given view.
535549

550+
This is the main entry point.
536551
You can override this if you need to provide custom behaviors for particular views.
537552

538553
### get_description(self, path, method)
@@ -565,7 +580,7 @@ Return a list of `coreapi.Link()` instances, as returned by the `get_schema_fiel
565580

566581
## ManualSchema
567582

568-
`APIViewSchemaDescriptor` subclass for specifying a manual schema.
583+
Allows specifying a manual schema for a view:
569584

570585
class MyView(APIView):
571586
schema = ManualSchema(coreapi.Link(

rest_framework/schemas.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,12 +301,28 @@ class AutoSchema(ViewInspector):
301301
302302
Responsible for per-view instrospection and schema generation.
303303
"""
304+
def __init__(self, manual_fields=None):
305+
"""
306+
Parameters:
307+
308+
* `manual_fields`: list of `coreapi.Field` instances that
309+
will be added to auto-generated fields, overwriting on `Field.name`
310+
"""
311+
312+
self._manual_fields = manual_fields
313+
304314
def get_link(self, path, method, base_url):
305315
fields = self.get_path_fields(path, method)
306316
fields += self.get_serializer_fields(path, method)
307317
fields += self.get_pagination_fields(path, method)
308318
fields += self.get_filter_fields(path, method)
309319

320+
if self._manual_fields is not None:
321+
by_name = {f.name: f for f in fields}
322+
for f in self._manual_fields:
323+
by_name[f.name] = f
324+
fields = list(by_name.values())
325+
310326
if fields and any([field.location in ('form', 'body') for field in fields]):
311327
encoding = self.get_encoding(path, method)
312328
else:

tests/test_schemas.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,25 @@ def test_get_link_requires_instance(self):
513513
with pytest.raises(AssertionError):
514514
descriptor.get_link(None, None, None) # ???: Do the dummy arguments require a tighter assert?
515515

516+
def test_manual_fields(self):
517+
518+
class CustomView(APIView):
519+
schema = AutoSchema(manual_fields=[
520+
coreapi.Field(
521+
"my_extra_field",
522+
required=True,
523+
location="path",
524+
schema=coreschema.String()
525+
),
526+
])
527+
528+
view = CustomView()
529+
link = view.schema.get_link('/a/url/{id}/', 'GET', '')
530+
fields = link.fields
531+
532+
assert len(fields) == 2
533+
assert "my_extra_field" in [f.name for f in fields]
534+
516535
def test_view_with_manual_schema(self):
517536

518537
expected = coreapi.Link(

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy