Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions rest_framework/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,9 @@ def get_rendered_html_form(self, data, view, method, request):
return self.render_form_for_serializer(serializer)

def render_form_for_serializer(self, serializer):
if isinstance(serializer, serializers.ListSerializer):
return None

if hasattr(serializer, 'initial_data'):
serializer.is_valid()

Expand Down Expand Up @@ -555,10 +558,13 @@ def get_raw_data_form(self, data, view, method, request):
context['indent'] = 4

# strip HiddenField from output
is_list_serializer = isinstance(serializer, serializers.ListSerializer)
serializer = serializer.child if is_list_serializer else serializer
data = serializer.data.copy()
for name, field in serializer.fields.items():
if isinstance(field, serializers.HiddenField):
data.pop(name, None)
data = [data] if is_list_serializer else data
content = renderer.render(data, accepted, context)
# Renders returns bytes, but CharField expects a str.
content = content.decode()
Expand Down
59 changes: 59 additions & 0 deletions tests/test_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,13 +633,72 @@ def list_action(self, request):
class AuthExampleViewSet(ExampleViewSet):
permission_classes = [permissions.IsAuthenticated]

class SimpleSerializer(serializers.Serializer):
name = serializers.CharField()

router = SimpleRouter()
router.register('examples', ExampleViewSet, basename='example')
router.register('auth-examples', AuthExampleViewSet, basename='auth-example')
urlpatterns = [path('api/', include(router.urls))]

def setUp(self):
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):
assert self.renderer.get_description({}, status_code=401) == ''
Expand Down