【问题标题】:Django rest framework browsable api is rendering both a PUT and a POST form when it should only be rendering a POST formDjango rest framework browsable api 在应该只呈现 POST 表单时同时呈现 PUT 和 POST 表单
【发布时间】:2018-10-20 18:20:45
【问题描述】:

通常,当我使用 ModelViewSet 导航到 url http://localhost:8000/api/v1/public_profiles/ 时,我只会得到一个 POST 表单,而当我导航到 http://localhost:8000/api/v1/public_profiles/123456/ 等特定资源时,我只会得到一个 PUT/PATCH 表单。 目前这两个表单都在两个位置呈现。

对于我的许多路线,我需要对视图进行更多控制,因此我选择了通用视图。我还想利用路由器,所以我混合了一个通用的视图集。上图是实现以下视图的结果:

class PublicProfileViewSet(viewsets.GenericViewSet, generics.ListCreateAPIView, generics.RetrieveUpdateAPIView):
    queryset = PublicProfile.objects.all()

    def get_serializer_class(self):
        if self.action == 'list':
            return PublicProfileReadSerializer
        elif self.action == 'retrieve':
            return PublicProfileReadSerializer
        elif self.action == 'create':
            return PublicProfileCreateSerializer
        elif self.action == 'update':
            return PublicProfileUpdateSerializer
        else:
            return PublicProfileReadSerializer

我能做些什么来解决这个问题,以便 POST 表单在 LIST 操作上呈现,而 PUT/PATCH 表单在 RETRIEVE 操作上呈现?

我尝试过的一件事是使用 ViewSet,但由于没有“serializer_class”,因此我没有生成任何表单:

class PublicProfileViewSet(viewsets.ViewSet):

     def list(self, request):
         queryset = PublicProfile.objects.all()
         serializer = PublicProfileReadSerializer(queryset, many=True, context={'request': request})
         return Response(serializer.data)

     def retrieve(self, request, pk=None):
         queryset = PublicProfile.objects.all()
         public_profile = get_object_or_404(PublicProfile, pk=pk)
         serializer = PublicProfileReadSerializer(public_profile, context={'request': request})
         return Response(serializer.data)

     def create(self, request):
         serializer = PublicProfileCreateSerializer(data=request.data, context={'request': request})
         if serializer.is_valid(raise_exception=True):
             serializer.save()
             return Response(serializer.data)

     def update(self, request, pk=None):
         instance = get_object_or_404(PublicProfile, pk=pk)
         serializer = PublicProfileUpdateSerializer(instance, data=request.data, context={'request': request})
         if serializer.is_valid(raise_exception=True):
             serializer.save()
             return Response(serializer.data)

     def partial_update(self, request, pk=None):
         instance = get_object_or_404(PublicProfile, pk=pk)
         serializer = PublicProfileUpdateSerializer(instance, data=request.data, context={'request': request}, partial=True)
         if serializer.is_valid(raise_exception=True):
             serializer.save()
             return Response(serializer.data)

     def destroy(self, request, pk=None):
         instance = get_object_or_404(PublicProfile, pk=pk)
         instance.user.is_active = False
         instance.user.save()
         return Response(status=status.HTTP_200_OK)

【问题讨论】:

  • 为什么不将视图分成 2 个视图。一个用于ListCreate,另一个用于RetrieveUpdate
  • @PeterSobhi 这会如何影响我的路由器?

标签: django django-rest-framework


【解决方案1】:

这些表单是从 Django Rest Framework 的默认非 JSON 可浏览 API 传播的,因为 JSON-API 仅指定 JSON 媒体类型。但是制作一个可浏览的 JSON-API 接口可能是值得的,虽然我个人更喜欢使用 Postman。

查看解析器和渲染器类的设置:

REST_FRAMEWORK = {
    'PAGE_SIZE': 10,
    'EXCEPTION_HANDLER': 'rest_framework_json_api.exceptions.exception_handler',
    'DEFAULT_PAGINATION_CLASS': 'rest_framework_json_api.pagination.PageNumberPagination',
    # 'DEFAULT_PAGINATION_CLASS': 'rest_framework_json_api.pagination.LimitOffsetPagination',
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework_json_api.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser',
    ),
    'DEFAULT_RENDERER_CLASSES': (
        # application/vnd.api+json
        'rest_framework_json_api.renderers.JSONRenderer',
        # text/html: ?format=api
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata',
    'TEST_REQUEST_DEFAULT_FORMAT': 'vnd.api+json',
    'TEST_REQUEST_RENDERER_CLASSES': (
        'rest_framework_json_api.renderers.JSONRenderer',
        'rest_framework.renderers.MultiPartRenderer',
        'rest_framework.renderers.TemplateHTMLRenderer'
    ),
}

【讨论】:

    【解决方案2】:

    首先确保您已登录。那是我的问题。

    当您从 {{url}}/admin 登录时

    当我登录时

    【讨论】:

      猜你喜欢
      • 2019-09-07
      • 2016-05-06
      • 1970-01-01
      • 2012-04-01
      • 1970-01-01
      • 2017-11-07
      • 2021-04-14
      • 2022-08-07
      相关资源
      最近更新 更多