首页 > 解决方案 > 具有类似 url_path 的 drf 操作视图未在 drf swagger 上显示

问题描述

我有两个具有相同 url_path('favorite')但处理检索和删除对象的方法不同的操作视图。这些动作视图中只有一个被映射并显示在 swagger API 上(使用 drf-yasg)。

from django.utils.decorators import method_decorator
from drf_yasg.utils import no_body, swagger_auto_schema
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework.status import (HTTP_201_CREATED,
                                HTTP_204_NO_CONTENT,
                                HTTP_404_NOT_FOUND,
                                HTTP_200_OK
                                )
from rest_framework.viewsets import GenericViewSet

from housery.house.models import House
from utils.drf_params import app_id
from utils.mixins import FilterQueryByHouse

from .serializers import HouseSerializer


@method_decorator(name="list", decorator=swagger_auto_schema(
    manual_parameters=[app_id]
    ))
class HouseViewSet(FilterQueryByHouse, ListModelMixin, GenericViewSet):
    queryset = House.objects.filter().prefetch_related(
        "opening_hours", "special_opening_hours__opening_hours",
    )
    serializer_class = HouseSerializer

    def get_permissions(self):
        if self.action in ["list"]:
            return [AllowAny()]
        return [IsAuthenticated()]

    @action(methods=["get"], detail=True, url_path="favorite", url_name="favorite-read")
    def retrieve_favorite(self, request):
        """Retrieve favorite house"""
        if request.user.favorite_house_id:
            instance = request.user.favorite_house
            Response(self.get_serializer(instance=instance).data, status=HTTP_200_OK)
        return Response(status=HTTP_404_NOT_FOUND)

    @action(methods=["delete"], detail=False, url_path="favorite", url_name="favorite-remove")
    def unset_favorite(self, request):
        """Remove favorite house"""
        request.user.favorite_house = None
        request.user.save()
        return Response(status=HTTP_204_NO_CONTENT)

    @swagger_auto_schema(request_body=no_body)
    @action(methods=["post"], detail=True)
    def favorite(self, request, pk):
        """set given house id as favorite house"""
        instance = self.get_object()
        request.user.favorite_house = instance
        request.user.save()
        return Response(self.get_serializer(instance=instance).data, status=HTTP_201_CREATED)

在此处输入图像描述

我只会得到“get”(retrieve_favorite)或“delete”(unset_favorite),但不能同时得到。我确信我正在做一些我还没有意识到的愚蠢行为,我将不胜感激。

标签: pythondjangodjango-rest-frameworkswaggerdrf-yasg

解决方案


也许那会奏效?

https://www.django-rest-framework.org/api-guide/viewsets/#routing-additional-http-methods-for-extra-actions

...
class HouseViewSet(FilterQueryByHouse, ListModelMixin, GenericViewSet):
    queryset = House.objects.filter().prefetch_related(
        "opening_hours", "special_opening_hours__opening_hours",
    )
    serializer_class = HouseSerializer

    def get_permissions(self):
        if self.action in ["list"]:
            return [AllowAny()]
        return [IsAuthenticated()]

    @action(methods=["get"], detail=True, url_path="favorite", url_name="favorite-detail")
    def favorite_detail(self, request, *args, **kwargs):
        """Retrieve favorite house"""
        if request.user.favorite_house_id:
            instance = request.user.favorite_house
            Response(self.get_serializer(instance=instance).data, status=HTTP_200_OK)
        return Response(status=HTTP_404_NOT_FOUND)

    @favorite_detail.mapping.delete
    def unset_favorite(self, request, *args, **kwargs):
        """Remove favorite house"""
        request.user.favorite_house = None
        request.user.save()
        return Response(status=HTTP_204_NO_CONTENT)

    @swagger_auto_schema(request_body=no_body)
    @action(methods=["post"], detail=True)
    def favorite(self, request, pk):
        """set given house id as favorite house"""
        instance = self.get_object()
        request.user.favorite_house = instance
        request.user.save()
        return Response(self.get_serializer(instance=instance).data, status=HTTP_201_CREATED)

我认为处理收藏夹的新视图集对于这种情况会是更好的解决方案——它更干净。


推荐阅读