mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-07 13:54:47 +03:00
Coerce schema 'pk' in path to actual field name
This commit is contained in:
parent
7edee804aa
commit
b44ab76d2c
|
@ -16,6 +16,7 @@ from rest_framework.response import Response
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
from rest_framework.utils import formatting
|
from rest_framework.utils import formatting
|
||||||
from rest_framework.utils.field_mapping import ClassLookupDict
|
from rest_framework.utils.field_mapping import ClassLookupDict
|
||||||
|
from rest_framework.utils.model_meta import _get_pk
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,6 +36,11 @@ types_lookup = ClassLookupDict({
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def get_pk_name(model):
|
||||||
|
meta = model._meta.concrete_model._meta
|
||||||
|
return _get_pk(meta).name
|
||||||
|
|
||||||
|
|
||||||
def as_query_fields(items):
|
def as_query_fields(items):
|
||||||
"""
|
"""
|
||||||
Take a list of Fields and plain strings.
|
Take a list of Fields and plain strings.
|
||||||
|
@ -196,6 +202,9 @@ class SchemaGenerator(object):
|
||||||
'delete': 'destroy',
|
'delete': 'destroy',
|
||||||
}
|
}
|
||||||
endpoint_inspector_cls = EndpointInspector
|
endpoint_inspector_cls = EndpointInspector
|
||||||
|
# 'pk' isn't great as an externally exposed name for an identifier,
|
||||||
|
# so by default we prefer to use the actual model field name for schemas.
|
||||||
|
coerce_pk = True
|
||||||
|
|
||||||
def __init__(self, title=None, url=None, patterns=None, urlconf=None):
|
def __init__(self, title=None, url=None, patterns=None, urlconf=None):
|
||||||
assert coreapi, '`coreapi` must be installed for schema support.'
|
assert coreapi, '`coreapi` must be installed for schema support.'
|
||||||
|
@ -230,6 +239,7 @@ class SchemaGenerator(object):
|
||||||
links = OrderedDict()
|
links = OrderedDict()
|
||||||
for path, method, callback in self.endpoints:
|
for path, method, callback in self.endpoints:
|
||||||
view = self.create_view(callback, method, request)
|
view = self.create_view(callback, method, request)
|
||||||
|
path = self.coerce_path(path, method, view)
|
||||||
if not self.should_include_view(path, method, view):
|
if not self.should_include_view(path, method, view):
|
||||||
continue
|
continue
|
||||||
link = self.get_link(path, method, view)
|
link = self.get_link(path, method, view)
|
||||||
|
@ -280,6 +290,16 @@ class SchemaGenerator(object):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def coerce_path(self, path, method, view):
|
||||||
|
if not self.coerce_pk or '{pk}' not in path:
|
||||||
|
return path
|
||||||
|
model = getattr(getattr(view, 'queryset', None), 'model', None)
|
||||||
|
if model:
|
||||||
|
field_name = get_pk_name(model)
|
||||||
|
else:
|
||||||
|
field_name = 'id'
|
||||||
|
return path.replace('{pk}', '{%s}' % field_name)
|
||||||
|
|
||||||
# Methods for generating each individual `Link` instance...
|
# Methods for generating each individual `Link` instance...
|
||||||
|
|
||||||
def get_link(self, path, method, view):
|
def get_link(self, path, method, view):
|
||||||
|
|
|
@ -103,10 +103,10 @@ class TestRouterGeneratedSchema(TestCase):
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
'retrieve': coreapi.Link(
|
'retrieve': coreapi.Link(
|
||||||
url='/example/{pk}/',
|
url='/example/{id}/',
|
||||||
action='get',
|
action='get',
|
||||||
fields=[
|
fields=[
|
||||||
coreapi.Field('pk', required=True, location='path')
|
coreapi.Field('id', required=True, location='path')
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -142,19 +142,19 @@ class TestRouterGeneratedSchema(TestCase):
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
'retrieve': coreapi.Link(
|
'retrieve': coreapi.Link(
|
||||||
url='/example/{pk}/',
|
url='/example/{id}/',
|
||||||
action='get',
|
action='get',
|
||||||
fields=[
|
fields=[
|
||||||
coreapi.Field('pk', required=True, location='path')
|
coreapi.Field('id', required=True, location='path')
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
'custom_action': coreapi.Link(
|
'custom_action': coreapi.Link(
|
||||||
url='/example/{pk}/custom_action/',
|
url='/example/{id}/custom_action/',
|
||||||
action='post',
|
action='post',
|
||||||
encoding='application/json',
|
encoding='application/json',
|
||||||
description='A description of custom action.',
|
description='A description of custom action.',
|
||||||
fields=[
|
fields=[
|
||||||
coreapi.Field('pk', required=True, location='path'),
|
coreapi.Field('id', required=True, location='path'),
|
||||||
coreapi.Field('c', required=True, location='form', type='string'),
|
coreapi.Field('c', required=True, location='form', type='string'),
|
||||||
coreapi.Field('d', required=False, location='form', type='string'),
|
coreapi.Field('d', required=False, location='form', type='string'),
|
||||||
]
|
]
|
||||||
|
@ -174,30 +174,30 @@ class TestRouterGeneratedSchema(TestCase):
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
'update': coreapi.Link(
|
'update': coreapi.Link(
|
||||||
url='/example/{pk}/',
|
url='/example/{id}/',
|
||||||
action='put',
|
action='put',
|
||||||
encoding='application/json',
|
encoding='application/json',
|
||||||
fields=[
|
fields=[
|
||||||
coreapi.Field('pk', required=True, location='path'),
|
coreapi.Field('id', required=True, location='path'),
|
||||||
coreapi.Field('a', required=True, location='form', type='string', description='A field description'),
|
coreapi.Field('a', required=True, location='form', type='string', description='A field description'),
|
||||||
coreapi.Field('b', required=False, location='form', type='string')
|
coreapi.Field('b', required=False, location='form', type='string')
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
'partial_update': coreapi.Link(
|
'partial_update': coreapi.Link(
|
||||||
url='/example/{pk}/',
|
url='/example/{id}/',
|
||||||
action='patch',
|
action='patch',
|
||||||
encoding='application/json',
|
encoding='application/json',
|
||||||
fields=[
|
fields=[
|
||||||
coreapi.Field('pk', required=True, location='path'),
|
coreapi.Field('id', required=True, location='path'),
|
||||||
coreapi.Field('a', required=False, location='form', type='string', description='A field description'),
|
coreapi.Field('a', required=False, location='form', type='string', description='A field description'),
|
||||||
coreapi.Field('b', required=False, location='form', type='string')
|
coreapi.Field('b', required=False, location='form', type='string')
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
'destroy': coreapi.Link(
|
'destroy': coreapi.Link(
|
||||||
url='/example/{pk}/',
|
url='/example/{id}/',
|
||||||
action='delete',
|
action='delete',
|
||||||
fields=[
|
fields=[
|
||||||
coreapi.Field('pk', required=True, location='path')
|
coreapi.Field('id', required=True, location='path')
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -254,18 +254,18 @@ class TestSchemaGenerator(TestCase):
|
||||||
fields=[]
|
fields=[]
|
||||||
),
|
),
|
||||||
'retrieve': coreapi.Link(
|
'retrieve': coreapi.Link(
|
||||||
url='/example/{pk}/',
|
url='/example/{id}/',
|
||||||
action='get',
|
action='get',
|
||||||
fields=[
|
fields=[
|
||||||
coreapi.Field('pk', required=True, location='path')
|
coreapi.Field('id', required=True, location='path')
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
'sub': {
|
'sub': {
|
||||||
'list': coreapi.Link(
|
'list': coreapi.Link(
|
||||||
url='/example/{pk}/sub/',
|
url='/example/{id}/sub/',
|
||||||
action='get',
|
action='get',
|
||||||
fields=[
|
fields=[
|
||||||
coreapi.Field('pk', required=True, location='path')
|
coreapi.Field('id', required=True, location='path')
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user