From a6732e25ecaaed706d1c76aa1be79ffa0d868213 Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Tue, 29 Mar 2016 13:25:26 -0400 Subject: [PATCH] Fixed #3751 -- Stopped listing related field choices through metadata. Listing related fields can leak sensitive data and result in poor performance when dealing with large result sets. Large result sets should be exposed by a dedicated endpoint instead. --- rest_framework/metadata.py | 4 +++- tests/test_metadata.py | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/rest_framework/metadata.py b/rest_framework/metadata.py index 6c4f176923..673aa962c3 100644 --- a/rest_framework/metadata.py +++ b/rest_framework/metadata.py @@ -137,7 +137,9 @@ def get_field_info(self, field): elif getattr(field, 'fields', None): field_info['children'] = self.get_serializer_info(field) - if not field_info.get('read_only') and hasattr(field, 'choices'): + if (not field_info.get('read_only') and + not isinstance(field, serializers.RelatedField) and + hasattr(field, 'choices')): field_info['choices'] = [ { 'value': choice_value, diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 6819f15046..109dd3f7cc 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -11,6 +11,8 @@ from rest_framework.request import Request from rest_framework.test import APIRequestFactory +from .models import BasicModel + request = Request(APIRequestFactory().options('/')) @@ -261,10 +263,21 @@ def get_serializer(self): view = ExampleView.as_view(versioning_class=scheme) view(request=request) + +class TestSimpleMetadataFieldInfo(TestCase): def test_null_boolean_field_info_type(self): options = metadata.SimpleMetadata() field_info = options.get_field_info(serializers.NullBooleanField()) - assert field_info['type'] == 'boolean' + self.assertEqual(field_info['type'], 'boolean') + + def test_related_field_choices(self): + options = metadata.SimpleMetadata() + BasicModel.objects.create() + with self.assertNumQueries(0): + field_info = options.get_field_info( + serializers.RelatedField(queryset=BasicModel.objects.all()) + ) + self.assertNotIn('choices', field_info) class TestModelSerializerMetadata(TestCase):