diff --git a/docs/topics/browsable-api.md b/docs/topics/browsable-api.md index b2c78f3c6..e32db6958 100644 --- a/docs/topics/browsable-api.md +++ b/docs/topics/browsable-api.md @@ -115,6 +115,7 @@ The context that's available to the template: * `name` : The name of the resource * `post_form` : A form instance for use by the POST form (if allowed) * `put_form` : A form instance for use by the PUT form (if allowed) +* `display_edit_forms` : A boolean indicating whether or not POST, PUT and PATCH forms will be displayed * `request` : The request object * `response` : The response object * `version` : The version of Django REST Framework @@ -122,6 +123,8 @@ The context that's available to the template: * `FORMAT_PARAM` : The view can accept a format override * `METHOD_PARAM` : The view can accept a method override +You can override the `BrowsableAPIRenderer.get_context()` method to customise the context that gets passed to the template. + #### Not using base.html For more advanced customization, such as not having a Bootstrap basis or tighter integration with the rest of your site, you can simply choose not to have `api.html` extend `base.html`. Then the page content and capabilities are entirely up to you. diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index fca67eeeb..2ce51e97b 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -564,6 +564,49 @@ class BrowsableAPIRenderer(BaseRenderer): def get_breadcrumbs(self, request): return get_breadcrumbs(request.path) + def get_context(self, data, accepted_media_type, renderer_context): + """ + Returns the context used to render. + """ + view = renderer_context['view'] + request = renderer_context['request'] + response = renderer_context['response'] + + renderer = self.get_default_renderer(view) + + raw_data_put_form = self.get_raw_data_form(view, 'PUT', request) + raw_data_patch_form = self.get_raw_data_form(view, 'PATCH', request) + raw_data_put_or_patch_form = raw_data_put_form or raw_data_patch_form + + context = { + 'content': self.get_content(renderer, data, accepted_media_type, renderer_context), + 'view': view, + 'request': request, + 'response': response, + 'description': self.get_description(view), + 'name': self.get_name(view), + 'version': VERSION, + 'breadcrumblist': self.get_breadcrumbs(request), + 'allowed_methods': view.allowed_methods, + 'available_formats': [renderer.format for renderer in view.renderer_classes], + + 'put_form': self.get_rendered_html_form(view, 'PUT', request), + 'post_form': self.get_rendered_html_form(view, 'POST', request), + 'patch_form': self.get_rendered_html_form(view, 'PATCH', request), + 'delete_form': self.get_rendered_html_form(view, 'DELETE', request), + 'options_form': self.get_rendered_html_form(view, 'OPTIONS', request), + + 'raw_data_put_form': raw_data_put_form, + 'raw_data_post_form': self.get_raw_data_form(view, 'POST', request), + 'raw_data_patch_form': raw_data_patch_form, + 'raw_data_put_or_patch_form': raw_data_put_or_patch_form, + + 'display_edit_forms': bool(response.status_code != 403), + + 'api_settings': api_settings + } + return context + def render(self, data, accepted_media_type=None, renderer_context=None): """ Render the HTML for the browsable API representation. @@ -571,60 +614,15 @@ class BrowsableAPIRenderer(BaseRenderer): self.accepted_media_type = accepted_media_type or '' self.renderer_context = renderer_context or {} - view = renderer_context['view'] - request = renderer_context['request'] - response = renderer_context['response'] - - renderer = self.get_default_renderer(view) - content = self.get_content(renderer, data, accepted_media_type, renderer_context) - - put_form = self.get_rendered_html_form(view, 'PUT', request) - post_form = self.get_rendered_html_form(view, 'POST', request) - patch_form = self.get_rendered_html_form(view, 'PATCH', request) - delete_form = self.get_rendered_html_form(view, 'DELETE', request) - options_form = self.get_rendered_html_form(view, 'OPTIONS', request) - - raw_data_put_form = self.get_raw_data_form(view, 'PUT', request) - raw_data_post_form = self.get_raw_data_form(view, 'POST', request) - raw_data_patch_form = self.get_raw_data_form(view, 'PATCH', request) - raw_data_put_or_patch_form = raw_data_put_form or raw_data_patch_form - - name = self.get_name(view) - description = self.get_description(view) - breadcrumb_list = self.get_breadcrumbs(request) - template = loader.get_template(self.template) - context = RequestContext(request, { - 'content': content, - 'view': view, - 'request': request, - 'response': response, - 'description': description, - 'name': name, - 'version': VERSION, - 'breadcrumblist': breadcrumb_list, - 'allowed_methods': view.allowed_methods, - 'available_formats': [renderer.format for renderer in view.renderer_classes], - - 'put_form': put_form, - 'post_form': post_form, - 'patch_form': patch_form, - 'delete_form': delete_form, - 'options_form': options_form, - - 'raw_data_put_form': raw_data_put_form, - 'raw_data_post_form': raw_data_post_form, - 'raw_data_patch_form': raw_data_patch_form, - 'raw_data_put_or_patch_form': raw_data_put_or_patch_form, - - 'api_settings': api_settings - }) - + context = self.get_context(data, accepted_media_type, renderer_context) + context = RequestContext(renderer_context['request'], context) ret = template.render(context) # Munge DELETE Response code to allow us to return content # (Do this *after* we've rendered the template so that we include # the normal deletion response code in the output) + response = renderer_context['response'] if response.status_code == status.HTTP_204_NO_CONTENT: response.status_code = status.HTTP_200_OK diff --git a/rest_framework/templates/rest_framework/base.html b/rest_framework/templates/rest_framework/base.html index aa90e90c4..2776d5500 100644 --- a/rest_framework/templates/rest_framework/base.html +++ b/rest_framework/templates/rest_framework/base.html @@ -122,7 +122,7 @@ - {% if response.status_code != 403 %} + {% if display_edit_forms %} {% if post_form or raw_data_post_form %}