mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-03 05:04:31 +03:00
Merge pull request #850 from tomchristie/dynamic-forms
Forms in Broseable API support dynamic serializers based on request method
This commit is contained in:
commit
b950b025bc
|
@ -336,7 +336,7 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
return # Cannot use form overloading
|
return # Cannot use form overloading
|
||||||
|
|
||||||
try:
|
try:
|
||||||
view.check_permissions(clone_request(request, method))
|
view.check_permissions(request)
|
||||||
except exceptions.APIException:
|
except exceptions.APIException:
|
||||||
return False # Doesn't have permissions
|
return False # Doesn't have permissions
|
||||||
return True
|
return True
|
||||||
|
@ -372,6 +372,30 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
|
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
|
def _get_form(self, view, method, request):
|
||||||
|
# We need to impersonate a request with the correct method,
|
||||||
|
# so that eg. any dynamic get_serializer_class methods return the
|
||||||
|
# correct form for each method.
|
||||||
|
restore = view.request
|
||||||
|
request = clone_request(request, method)
|
||||||
|
view.request = request
|
||||||
|
try:
|
||||||
|
return self.get_form(view, method, request)
|
||||||
|
finally:
|
||||||
|
view.request = restore
|
||||||
|
|
||||||
|
def _get_raw_data_form(self, view, method, request, media_types):
|
||||||
|
# We need to impersonate a request with the correct method,
|
||||||
|
# so that eg. any dynamic get_serializer_class methods return the
|
||||||
|
# correct form for each method.
|
||||||
|
restore = view.request
|
||||||
|
request = clone_request(request, method)
|
||||||
|
view.request = request
|
||||||
|
try:
|
||||||
|
return self.get_raw_data_form(view, method, request, media_types)
|
||||||
|
finally:
|
||||||
|
view.request = restore
|
||||||
|
|
||||||
def get_form(self, view, method, request):
|
def get_form(self, view, method, request):
|
||||||
"""
|
"""
|
||||||
Get a form, possibly bound to either the input or output data.
|
Get a form, possibly bound to either the input or output data.
|
||||||
|
@ -465,15 +489,15 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
renderer = self.get_default_renderer(view)
|
renderer = self.get_default_renderer(view)
|
||||||
content = self.get_content(renderer, data, accepted_media_type, renderer_context)
|
content = self.get_content(renderer, data, accepted_media_type, renderer_context)
|
||||||
|
|
||||||
put_form = self.get_form(view, 'PUT', request)
|
put_form = self._get_form(view, 'PUT', request)
|
||||||
post_form = self.get_form(view, 'POST', request)
|
post_form = self._get_form(view, 'POST', request)
|
||||||
patch_form = self.get_form(view, 'PATCH', request)
|
patch_form = self._get_form(view, 'PATCH', request)
|
||||||
delete_form = self.get_form(view, 'DELETE', request)
|
delete_form = self._get_form(view, 'DELETE', request)
|
||||||
options_form = self.get_form(view, 'OPTIONS', request)
|
options_form = self._get_form(view, 'OPTIONS', request)
|
||||||
|
|
||||||
raw_data_put_form = self.get_raw_data_form(view, 'PUT', request, media_types)
|
raw_data_put_form = self._get_raw_data_form(view, 'PUT', request, media_types)
|
||||||
raw_data_post_form = self.get_raw_data_form(view, 'POST', request, media_types)
|
raw_data_post_form = self._get_raw_data_form(view, 'POST', request, media_types)
|
||||||
raw_data_patch_form = self.get_raw_data_form(view, 'PATCH', request, media_types)
|
raw_data_patch_form = self._get_raw_data_form(view, 'PATCH', request, media_types)
|
||||||
raw_data_put_or_patch_form = raw_data_put_form or raw_data_patch_form
|
raw_data_put_or_patch_form = raw_data_put_form or raw_data_patch_form
|
||||||
|
|
||||||
name = self.get_name(view)
|
name = self.get_name(view)
|
||||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import unicode_literals
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from rest_framework import generics, serializers, status
|
from rest_framework import generics, renderers, serializers, status
|
||||||
from rest_framework.tests.utils import RequestFactory
|
from rest_framework.tests.utils import RequestFactory
|
||||||
from rest_framework.tests.models import BasicModel, Comment, SlugBasedModel
|
from rest_framework.tests.models import BasicModel, Comment, SlugBasedModel
|
||||||
from rest_framework.compat import six
|
from rest_framework.compat import six
|
||||||
|
@ -476,3 +476,35 @@ class TestFilterBackendAppliedToViews(TestCase):
|
||||||
response = instance_view(request, pk=1).render()
|
response = instance_view(request, pk=1).render()
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
self.assertEqual(response.data, {'id': 1, 'text': 'foo'})
|
self.assertEqual(response.data, {'id': 1, 'text': 'foo'})
|
||||||
|
|
||||||
|
|
||||||
|
class TwoFieldModel(models.Model):
|
||||||
|
field_a = models.CharField(max_length=100)
|
||||||
|
field_b = models.CharField(max_length=100)
|
||||||
|
|
||||||
|
|
||||||
|
class DynamicSerializerView(generics.ListCreateAPIView):
|
||||||
|
model = TwoFieldModel
|
||||||
|
renderer_classes = (renderers.BrowsableAPIRenderer, renderers.JSONRenderer)
|
||||||
|
|
||||||
|
def get_serializer_class(self):
|
||||||
|
if self.request.method == 'POST':
|
||||||
|
class DynamicSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = TwoFieldModel
|
||||||
|
fields = ('field_b',)
|
||||||
|
return DynamicSerializer
|
||||||
|
return super(DynamicSerializerView, self).get_serializer_class()
|
||||||
|
|
||||||
|
|
||||||
|
class TestFilterBackendAppliedToViews(TestCase):
|
||||||
|
|
||||||
|
def test_dynamic_serializer_form_in_browsable_api(self):
|
||||||
|
"""
|
||||||
|
GET requests to ListCreateAPIView should return filtered list.
|
||||||
|
"""
|
||||||
|
view = DynamicSerializerView.as_view()
|
||||||
|
request = factory.get('/')
|
||||||
|
response = view(request).render()
|
||||||
|
self.assertContains(response, 'field_b')
|
||||||
|
self.assertNotContains(response, 'field_a')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user