django DRF ViewSet始终返回HTTP 200

mitkmikd  于 2023-11-20  发布在  Go
关注(0)|答案(1)|浏览(150)

我刚加入DRF。
这是我的ViewSet(基于DRF官方文档的示例):

class AccountViewSet(viewsets.ViewSet):
    def list(self, request):
        queryset = User.objects.all()
        serializer = AccountSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, email=None):
        queryset = User.objects.all()
        user = get_object_or_404(queryset, email=email)
        serializer = AccountSerializer(user)
        return Response(serializer.data)

字符串
数据库里有两个邮箱地址。
我的API客户端是httpie
当我向http://127.0.0.1:8000/api/accounts/发送GET请求时,我会收到这两封电子邮件。所以这部分工作正常。
然而,当我提供一个在数据库中不存在的电子邮件地址(如ParamsHeaders)时,我再次得到这两封电子邮件,而不是404
我做了一点研究,把代码改成这样:

class AccountViewSet(viewsets.ViewSet):
    def list(self, request):
        queryset = User.objects.all()
        serializer = AccountSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, email=None):
        queryset = User.objects.all()
        try:
            user = get_object_or_404(queryset, email=email)
        except User.DoesNotExist:
            return Response(status=404)
        serializer = AccountSerializer(user)
        return Response(serializer.data)


再一次,200与这两封电子邮件。
即使我提供了一个电子邮件,确实存在,我得到了两个回应。
我不知道我错过了什么。
P.S:我的URL模式定义如下:

from rest_framework.routers import DefaultRouter

from .views import AccountViewSet

router = DefaultRouter()
router.register(r'accounts', AccountViewSet, basename='accounts')

urlpatterns = router.urls

bogh5gae

bogh5gae1#

email在URL路由中没有被定义为关键字参数,因此当您尝试通过email获取单个用户时,retrieve方法永远不会被调用。
您应该(解决方案1)覆盖ViewSet级别上的lookup_field定义:

class AccountViewSet(viewsets.ViewSet):
    # The rest of the code is kept intact

    lookup_field = "email"

字符串
或者(解决方案2)在ViewSet中定义一个自定义的route/action(然后你用route/action代替retrieve):

from rest_framework.decorators import action

class AccountViewSet(viewsets.ViewSet):
    # The rest of the code is kept intact

    @action(detail=False, methods=["GET"])
    def get_by_email(self, request):
        email = request.query_params.get("email", None)
        if email is None:
            return Response(status=400, data={"message": "Email parameter is required"})

        try:
            user = User.objects.get(email=email)
        except User.DoesNotExist:
            return Response(status=404)

        serializer = AccountSerializer(user)
        return Response(serializer.data)


或者(解决方案3),您可以定义URL模式如下:

from django.urls import path
from .views import AccountViewSet

urlpatterns = [
    path("accounts/", AccountViewSet.as_view({"get": "list"}), name="account-list"),
    path("accounts/<str:email>/", AccountViewSet.as_view({"get": "retrieve"}), name="account-detail"),
]

相关问题