Call APIView get_ methods instead of direct attribute access

queryset -> get_queryset
renderer_classes -> get_renderers
parser_classes -> get_parsers
This commit is contained in:
Cristi Vîjdea
2018-12-23 16:57:01 +02:00
parent 04d61b9d97
commit bebcc982e6
8 changed files with 124 additions and 43 deletions
+47 -6
View File
@@ -4,7 +4,7 @@ import logging
from rest_framework import serializers
from .. import openapi
from ..utils import force_real_str, get_field_default, is_list_view
from ..utils import force_real_str, get_field_default, get_object_classes, is_list_view
#: Sentinel value that inspectors must return to signal that they do not know how to handle an object
NotHandled = object()
@@ -12,14 +12,38 @@ NotHandled = object()
logger = logging.getLogger(__name__)
def call_view_method(view, method_name, fallback_attr=None, default=None):
"""Call a view method which might throw an exception. If an exception is thrown, log an informative error message
and return the value of fallback_attr, or default if not present.
:param rest_framework.views.APIView view:
:param str method_name: name of a method on the view
:param str fallback_attr: name of an attribute on the view to fall back on, if calling the method fails
:param default: default value if all else fails
:return: view method's return value, or value of view's fallback_attr, or default
"""
if hasattr(view, method_name):
try:
return getattr(view, method_name)()
except Exception: # pragma: no cover
logger.warning("view's %s.get_parsers raised exception during schema generation; use "
"`getattr(self, 'swagger_fake_view', False)` to detect and short-circuit this",
type(view).__name__, exc_info=True)
if fallback_attr and hasattr(view, fallback_attr):
return getattr(view, fallback_attr)
return default
class BaseInspector(object):
def __init__(self, view, path, method, components, request):
"""
:param view: the view associated with this endpoint
:param rest_framework.views.APIView view: the view associated with this endpoint
:param str path: the path component of the operation URL
:param str method: the http method of the operation
:param openapi.ReferenceResolver components: referenceable components
:param Request request: the request made against the schema view; can be None
:param rest_framework.request.Request request: the request made against the schema view; can be None
"""
self.view = view
self.path = path
@@ -81,6 +105,22 @@ class BaseInspector(object):
return result
def get_renderer_classes(self):
"""Get the renderer classes of this view by calling `get_renderers`.
:return: renderer classes
:rtype: list[type[rest_framework.renderers.BaseRenderer]]
"""
return get_object_classes(call_view_method(self.view, 'get_renderers', 'renderer_classes', []))
def get_parser_classes(self):
"""Get the parser classes of this view by calling `get_parsers`.
:return: parser classes
:rtype: list[type[rest_framework.parsers.BaseParser]]
"""
return get_object_classes(call_view_method(self.view, 'get_parsers', 'parser_classes', []))
class PaginatorInspector(BaseInspector):
"""Base inspector for paginators.
@@ -335,7 +375,7 @@ class ViewInspector(BaseInspector):
return []
fields = []
for filter_backend in self.view.filter_backends:
for filter_backend in getattr(self.view, 'filter_backends'):
fields += self.probe_inspectors(self.filter_inspectors, 'get_filter_parameters', filter_backend()) or []
return fields
@@ -361,7 +401,8 @@ class ViewInspector(BaseInspector):
if not self.should_page():
return []
return self.probe_inspectors(self.paginator_inspectors, 'get_paginator_parameters', self.view.paginator) or []
return self.probe_inspectors(self.paginator_inspectors, 'get_paginator_parameters',
getattr(self.view, 'paginator')) or []
def serializer_to_schema(self, serializer):
"""Convert a serializer to an OpenAPI :class:`.Schema`.
@@ -394,4 +435,4 @@ class ViewInspector(BaseInspector):
:rtype: openapi.Schema
"""
return self.probe_inspectors(self.paginator_inspectors, 'get_paginated_response',
self.view.paginator, response_schema=response_schema)
getattr(self.view, 'paginator'), response_schema=response_schema)