diff --git a/readthedocs/v3/renderer.py b/readthedocs/v3/renderer.py index 6f0b976ebfb..fad520f9c61 100644 --- a/readthedocs/v3/renderer.py +++ b/readthedocs/v3/renderer.py @@ -2,27 +2,7 @@ from rest_framework.compat import ( INDENT_SEPARATORS, LONG_SEPARATORS, SHORT_SEPARATORS, ) -from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer - - -class BuildsBrowsableAPIRenderer(BrowsableAPIRenderer): - """ - APIRenderer that does not render a raw/html form for POST. - - Builds endpoint accept the creation of a new Build object, but does not - accept any data on body. So, we omit rendering the raw and html forms when - browsing it. - """ - - def get_raw_data_form(self, data, view, method, request): - if method == 'POST': - return None - return super().get_raw_data_form(data, view, method, request) - - def get_rendered_html_form(self, data, view, method, request): - if method == 'POST': - return None - return super().get_rendered_html_form(data, view, method, request) +from rest_framework.renderers import JSONRenderer class AlphaneticalSortedJSONRenderer(JSONRenderer): diff --git a/readthedocs/v3/serializers.py b/readthedocs/v3/serializers.py index 46a752baf59..2813153535a 100644 --- a/readthedocs/v3/serializers.py +++ b/readthedocs/v3/serializers.py @@ -39,6 +39,13 @@ def _absolute_url(self, path): return urllib.parse.urlunparse((scheme, domain, path, '', '', '')) +class BuildTriggerSerializer(serializers.ModelSerializer): + + class Meta: + model = Build + fields = [] + + class BuildLinksSerializer(BaseLinksSerializer): _self = serializers.SerializerMethodField() version = serializers.SerializerMethodField() diff --git a/readthedocs/v3/views.py b/readthedocs/v3/views.py index 2065a9fd176..fb78887cfa8 100644 --- a/readthedocs/v3/views.py +++ b/readthedocs/v3/views.py @@ -19,8 +19,8 @@ from rest_framework.metadata import SimpleMetadata from rest_framework_simplejwt.authentication import JWTAuthentication from .filters import ProjectFilter, VersionFilter, BuildFilter -from .renderer import BuildsBrowsableAPIRenderer, AlphaneticalSortedJSONRenderer -from .serializers import ProjectSerializer, VersionSerializer, VersionUpdateSerializer, BuildSerializer, UserSerializer +from .renderer import AlphaneticalSortedJSONRenderer +from .serializers import ProjectSerializer, VersionSerializer, VersionUpdateSerializer, BuildTriggerSerializer, BuildSerializer, UserSerializer class APIv3Settings: @@ -152,7 +152,6 @@ class VersionsViewSet(APIv3Settings, NestedViewSetMixin, FlexFieldsMixin, ListMo # Allow ``.`` (dots) on version slug lookup_value_regex = r'[^/]+' - serializer_class = VersionSerializer filterset_class = VersionFilter queryset = Version.objects.all() permit_list_expands = [ @@ -164,6 +163,14 @@ class VersionsViewSet(APIv3Settings, NestedViewSetMixin, FlexFieldsMixin, ListMo # does not exist it does not return 404, but 200 instead: # /api/v3/projects/nonexistent/versions/ + def get_serializer_class(self): + """ + Return correct serializer depending on the action (GET or PUT/PATCH/POST). + """ + if self.action in ('list', 'retrieve'): + return VersionSerializer + return VersionUpdateSerializer + def get_queryset(self): # ``super().get_queryset`` produces the filter by ``NestedViewSetMixin`` queryset = super().get_queryset() @@ -175,7 +182,8 @@ def get_queryset(self): def partial_update(self, request, pk=None, **kwargs): version = self.get_object() - serializer = VersionUpdateSerializer( + serializer_class = self.get_serializer_class() + serializer = serializer_class( version, data=request.data, partial=True, @@ -191,13 +199,11 @@ class BuildsViewSet(APIv3Settings, NestedViewSetMixin, FlexFieldsMixin, ListMode model = Build lookup_field = 'pk' lookup_url_kwarg = 'build_pk' - serializer_class = BuildSerializer filterset_class = BuildFilter queryset = Build.objects.all() permit_list_expands = [ 'config', ] - renderer_classes = (AlphaneticalSortedJSONRenderer, BuildsBrowsableAPIRenderer) def get_queryset(self): # ``super().get_queryset`` produces the filter by ``NestedViewSetMixin`` @@ -208,6 +214,11 @@ def get_queryset(self): queryset = queryset.filter(project__users=user) return queryset + def get_serializer_class(self): + if self.action in ('list', 'retrieve'): + return BuildSerializer + return BuildTriggerSerializer + def create(self, request, **kwargs): parent_lookup_project__slug = kwargs.get('parent_lookup_project__slug') parent_lookup_version__slug = kwargs.get('parent_lookup_version__slug') @@ -226,6 +237,9 @@ def create(self, request, **kwargs): ) _, build = trigger_build(project, version=version) + + # TODO: refactor this to be a serializer + # BuildTriggeredSerializer(build, project, version).data data = { 'build': BuildSerializer(build).data, 'project': ProjectSerializer(project).data,