Skip to content

Commit a0eeaa3

Browse files
committed
Add 'description' to Core API fields.
1 parent abc62af commit a0eeaa3

File tree

2 files changed

+72
-6
lines changed

2 files changed

+72
-6
lines changed

rest_framework/pagination.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from django.core.paginator import InvalidPage
1313
from django.template import loader
1414
from django.utils import six
15+
from django.utils.encoding import force_text
1516
from django.utils.six.moves.urllib import parse as urlparse
1617
from django.utils.translation import ugettext_lazy as _
1718

@@ -178,10 +179,12 @@ class PageNumberPagination(BasePagination):
178179

179180
# Client can control the page using this query parameter.
180181
page_query_param = 'page'
182+
page_query_description = _('A page number within the paginated result set.')
181183

182184
# Client can control the page size using this query parameter.
183185
# Default is 'None'. Set to eg 'page_size' to enable usage.
184186
page_size_query_param = None
187+
page_size_query_description = _('Number of results to return per page.')
185188

186189
# Set to an integer to limit the maximum page size the client may request.
187190
# Only relevant if 'page_size_query_param' has also been set.
@@ -287,11 +290,21 @@ def to_html(self):
287290
def get_schema_fields(self, view):
288291
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
289292
fields = [
290-
coreapi.Field(name=self.page_query_param, required=False, location='query')
293+
coreapi.Field(
294+
name=self.page_query_param,
295+
required=False,
296+
location='query',
297+
description=force_text(self.page_query_description)
298+
)
291299
]
292300
if self.page_size_query_param is not None:
293301
fields.append(
294-
coreapi.Field(name=self.page_size_query_param, required=False, location='query')
302+
coreapi.Field(
303+
name=self.page_size_query_param,
304+
required=False,
305+
location='query',
306+
description=force_text(self.page_size_query_description)
307+
)
295308
)
296309
return fields
297310

@@ -305,7 +318,9 @@ class LimitOffsetPagination(BasePagination):
305318
"""
306319
default_limit = api_settings.PAGE_SIZE
307320
limit_query_param = 'limit'
321+
limit_query_description = _('Number of results to return per page.')
308322
offset_query_param = 'offset'
323+
offset_query_description = _('The initial index from which to return the results.')
309324
max_limit = None
310325
template = 'rest_framework/pagination/numbers.html'
311326

@@ -425,8 +440,18 @@ def to_html(self):
425440
def get_schema_fields(self, view):
426441
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
427442
return [
428-
coreapi.Field(name=self.limit_query_param, required=False, location='query'),
429-
coreapi.Field(name=self.offset_query_param, required=False, location='query')
443+
coreapi.Field(
444+
name=self.limit_query_param,
445+
required=False,
446+
location='query',
447+
description=force_text(self.limit_query_description)
448+
),
449+
coreapi.Field(
450+
name=self.offset_query_param,
451+
required=False,
452+
location='query',
453+
description=force_text(self.offset_query_description)
454+
)
430455
]
431456

432457

@@ -437,6 +462,7 @@ class CursorPagination(BasePagination):
437462
http://cramer.io/2011/03/08/building-cursors-for-the-disqus-api
438463
"""
439464
cursor_query_param = 'cursor'
465+
cursor_query_description = _('The pagination cursor value.')
440466
page_size = api_settings.PAGE_SIZE
441467
invalid_cursor_message = _('Invalid cursor')
442468
ordering = '-created'
@@ -739,5 +765,10 @@ def to_html(self):
739765
def get_schema_fields(self, view):
740766
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
741767
return [
742-
coreapi.Field(name=self.cursor_query_param, required=False, location='query')
768+
coreapi.Field(
769+
name=self.cursor_query_param,
770+
required=False,
771+
location='query',
772+
description=force_text(self.cursor_query_description)
773+
)
743774
]

rest_framework/schemas.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
from django.conf import settings
66
from django.contrib.admindocs.views import simplify_regex
77
from django.core.exceptions import PermissionDenied
8+
from django.db import models
89
from django.http import Http404
910
from django.utils import six
1011
from django.utils.encoding import force_text, smart_text
12+
from django.utils.translation import ugettext_lazy as _
1113

1214
from rest_framework import exceptions, renderers, serializers
1315
from rest_framework.compat import (
@@ -113,6 +115,19 @@ def endpoint_ordering(endpoint):
113115
return (path, method_priority)
114116

115117

118+
def get_pk_description(model, model_field):
119+
if isinstance(model_field, models.AutoField):
120+
value_type = _('unique integer value')
121+
elif isinstance(model_field, models.UUIDField):
122+
value_type = _('UUID string')
123+
else:
124+
value_type = _('unique value')
125+
126+
return _('A {value_type} identifying this {name}.').format(
127+
value_type=value_type,
128+
name=model._meta.verbose_name,
129+
)
130+
116131
class EndpointInspector(object):
117132
"""
118133
A class to determine the available API endpoints that a project exposes.
@@ -450,10 +465,30 @@ def get_path_fields(self, path, method, view):
450465
Return a list of `coreapi.Field` instances corresponding to any
451466
templated path variables.
452467
"""
468+
model = getattr(getattr(view, 'queryset', None), 'model', None)
453469
fields = []
454470

455471
for variable in uritemplate.variables(path):
456-
field = coreapi.Field(name=variable, location='path', required=True)
472+
description = None
473+
if model is not None:
474+
# Attempt to infer a field description if possible.
475+
try:
476+
model_field = model._meta.get_field(variable)
477+
except:
478+
pass
479+
480+
if model_field is not None and model_field.help_text:
481+
description = force_text(model_field.help_text)
482+
elif model_field is not None and model_field.primary_key:
483+
description = get_pk_description(model, model_field)
484+
485+
486+
field = coreapi.Field(
487+
name=variable,
488+
location='path',
489+
required=True,
490+
description='' if (description is None) else description
491+
)
457492
fields.append(field)
458493

459494
return fields

0 commit comments

Comments
 (0)