mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-25 11:04:02 +03:00
Fixes BrowsableAPIRenderer
for usage with ListSerializer
. (#7530)
Renders list of items in raw_data_form and does not renders form in template while using with `ListSerializer` (`many=True`).
This commit is contained in:
parent
376a5cbbba
commit
02d9bfc2dd
|
@ -506,6 +506,9 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
return self.render_form_for_serializer(serializer)
|
return self.render_form_for_serializer(serializer)
|
||||||
|
|
||||||
def render_form_for_serializer(self, serializer):
|
def render_form_for_serializer(self, serializer):
|
||||||
|
if isinstance(serializer, serializers.ListSerializer):
|
||||||
|
return None
|
||||||
|
|
||||||
if hasattr(serializer, 'initial_data'):
|
if hasattr(serializer, 'initial_data'):
|
||||||
serializer.is_valid()
|
serializer.is_valid()
|
||||||
|
|
||||||
|
@ -555,10 +558,13 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
context['indent'] = 4
|
context['indent'] = 4
|
||||||
|
|
||||||
# strip HiddenField from output
|
# strip HiddenField from output
|
||||||
|
is_list_serializer = isinstance(serializer, serializers.ListSerializer)
|
||||||
|
serializer = serializer.child if is_list_serializer else serializer
|
||||||
data = serializer.data.copy()
|
data = serializer.data.copy()
|
||||||
for name, field in serializer.fields.items():
|
for name, field in serializer.fields.items():
|
||||||
if isinstance(field, serializers.HiddenField):
|
if isinstance(field, serializers.HiddenField):
|
||||||
data.pop(name, None)
|
data.pop(name, None)
|
||||||
|
data = [data] if is_list_serializer else data
|
||||||
content = renderer.render(data, accepted, context)
|
content = renderer.render(data, accepted, context)
|
||||||
# Renders returns bytes, but CharField expects a str.
|
# Renders returns bytes, but CharField expects a str.
|
||||||
content = content.decode()
|
content = content.decode()
|
||||||
|
|
|
@ -633,6 +633,9 @@ class BrowsableAPIRendererTests(URLPatternsTestCase):
|
||||||
class AuthExampleViewSet(ExampleViewSet):
|
class AuthExampleViewSet(ExampleViewSet):
|
||||||
permission_classes = [permissions.IsAuthenticated]
|
permission_classes = [permissions.IsAuthenticated]
|
||||||
|
|
||||||
|
class SimpleSerializer(serializers.Serializer):
|
||||||
|
name = serializers.CharField()
|
||||||
|
|
||||||
router = SimpleRouter()
|
router = SimpleRouter()
|
||||||
router.register('examples', ExampleViewSet, basename='example')
|
router.register('examples', ExampleViewSet, basename='example')
|
||||||
router.register('auth-examples', AuthExampleViewSet, basename='auth-example')
|
router.register('auth-examples', AuthExampleViewSet, basename='auth-example')
|
||||||
|
@ -640,6 +643,62 @@ class BrowsableAPIRendererTests(URLPatternsTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.renderer = BrowsableAPIRenderer()
|
self.renderer = BrowsableAPIRenderer()
|
||||||
|
self.renderer.accepted_media_type = ''
|
||||||
|
self.renderer.renderer_context = {}
|
||||||
|
|
||||||
|
def test_render_form_for_serializer(self):
|
||||||
|
with self.subTest('Serializer'):
|
||||||
|
serializer = BrowsableAPIRendererTests.SimpleSerializer(data={'name': 'Name'})
|
||||||
|
form = self.renderer.render_form_for_serializer(serializer)
|
||||||
|
assert isinstance(form, str), 'Must return form for serializer'
|
||||||
|
|
||||||
|
with self.subTest('ListSerializer'):
|
||||||
|
list_serializer = BrowsableAPIRendererTests.SimpleSerializer(data=[{'name': 'Name'}], many=True)
|
||||||
|
form = self.renderer.render_form_for_serializer(list_serializer)
|
||||||
|
assert form is None, 'Must not return form for list serializer'
|
||||||
|
|
||||||
|
def test_get_raw_data_form(self):
|
||||||
|
with self.subTest('Serializer'):
|
||||||
|
class DummyGenericViewsetLike(APIView):
|
||||||
|
def get_serializer(self, **kwargs):
|
||||||
|
return BrowsableAPIRendererTests.SimpleSerializer(**kwargs)
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
response = Response()
|
||||||
|
response.view = self
|
||||||
|
return response
|
||||||
|
|
||||||
|
post = get
|
||||||
|
|
||||||
|
view = DummyGenericViewsetLike.as_view()
|
||||||
|
_request = APIRequestFactory().get('/')
|
||||||
|
request = Request(_request)
|
||||||
|
response = view(_request)
|
||||||
|
view = response.view
|
||||||
|
|
||||||
|
raw_data_form = self.renderer.get_raw_data_form({'name': 'Name'}, view, 'POST', request)
|
||||||
|
assert raw_data_form['_content'].initial == '{\n "name": ""\n}'
|
||||||
|
|
||||||
|
with self.subTest('ListSerializer'):
|
||||||
|
class DummyGenericViewsetLike(APIView):
|
||||||
|
def get_serializer(self, **kwargs):
|
||||||
|
return BrowsableAPIRendererTests.SimpleSerializer(many=True, **kwargs) # returns ListSerializer
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
response = Response()
|
||||||
|
response.view = self
|
||||||
|
return response
|
||||||
|
|
||||||
|
post = get
|
||||||
|
|
||||||
|
view = DummyGenericViewsetLike.as_view()
|
||||||
|
_request = APIRequestFactory().get('/')
|
||||||
|
request = Request(_request)
|
||||||
|
response = view(_request)
|
||||||
|
view = response.view
|
||||||
|
|
||||||
|
raw_data_form = self.renderer.get_raw_data_form([{'name': 'Name'}], view, 'POST', request)
|
||||||
|
assert raw_data_form['_content'].initial == '[\n {\n "name": ""\n }\n]'
|
||||||
|
|
||||||
def test_get_description_returns_empty_string_for_401_and_403_statuses(self):
|
def test_get_description_returns_empty_string_for_401_and_403_statuses(self):
|
||||||
assert self.renderer.get_description({}, status_code=401) == ''
|
assert self.renderer.get_description({}, status_code=401) == ''
|
||||||
|
|
Loading…
Reference in New Issue
Block a user