From c5d6ecc84c5a40f5410bfd89b5a80c4e5a549d25 Mon Sep 17 00:00:00 2001 From: Zoltan Szalai Date: Sat, 25 Apr 2015 16:33:44 +0200 Subject: [PATCH 1/2] pass instance to view.get_serializer in metadata's determine_actions method since choices (especially querysets of related fields) can often depend on the instance --- rest_framework/metadata.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/rest_framework/metadata.py b/rest_framework/metadata.py index b2c48b816..afef00fe6 100644 --- a/rest_framework/metadata.py +++ b/rest_framework/metadata.py @@ -74,19 +74,23 @@ class SimpleMetadata(BaseMetadata): actions = {} for method in set(['PUT', 'POST']) & set(view.allowed_methods): view.request = clone_request(request, method) + instance = None try: # Test global permissions if hasattr(view, 'check_permissions'): view.check_permissions(view.request) # Test object permissions if method == 'PUT' and hasattr(view, 'get_object'): - view.get_object() + instance = view.get_object() except (exceptions.APIException, PermissionDenied, Http404): pass else: # If user has appropriate permissions for the view, include # appropriate metadata about the fields that should be supplied. - serializer = view.get_serializer() + kwargs = {} + if instance is not None: + kwargs['instance'] = instance + serializer = view.get_serializer(**kwargs) actions[method] = self.get_serializer_info(serializer) finally: view.request = request From e52df6b5492aed16614fb9b8b5c3c85a0cd5c4c9 Mon Sep 17 00:00:00 2001 From: Zoltan Szalai Date: Sat, 25 Apr 2015 16:56:02 +0200 Subject: [PATCH 2/2] add TestMetadata.test_instance_passed_to_serializer --- tests/test_metadata.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 731aedba3..747ef817d 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -212,3 +212,27 @@ class TestMetadata: options = metadata.SimpleMetadata() field_info = options.get_field_info(serializers.NullBooleanField()) assert field_info['type'] == 'boolean' + + def test_instance_passed_to_serializer(self): + dummy_obj = object() + + class ExampleSerializer(serializers.Serializer): + def __init__(self, *args, **kwargs): + super(ExampleSerializer, self).__init__(*args, **kwargs) + assert self.instance == dummy_obj + + class ExampleView(views.APIView): + """Example view.""" + def put(self, request): + pass + + def get_object(self): + return dummy_obj + + def get_serializer(self, *args, **kwargs): + assert kwargs['instance'] == self.get_object() + return ExampleSerializer(*args, **kwargs) + + view = ExampleView.as_view() + response = view(request=request) + assert response.status_code == status.HTTP_200_OK