在Django REST框架中找不到资源时如何返回404

cig3rfwq  于 2023-05-01  发布在  Go
关注(0)|答案(4)|浏览(119)

当用户输入错误的URL时,Django应用程序会返回HTML错误。如何让DRF返回JSON格式的错误?
目前我的网址是

from django.conf.urls import url
from snippets import views

urlpatterns = [
    url(r'^snippets/$', views.snippet_list),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]

但是如果用户访问 www.example.com 他们得到的是html格式错误,而不是json格式错误。

9jyewag0

9jyewag01#

简单地说,你可以使用raise Http404,这里是你的views.py

from django.http import Http404

from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView

from yourapp.models import Snippet
from yourapp.serializer import SnippetSerializer

class SnippetDetailView(APIView):

    def get_object(self, pk):
        try:
            return Snippet.objects.get(pk=pk)
        except Snippet.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data, status=status.HTTP_200_OK)

你也可以用Response(status=status.HTTP_404_NOT_FOUND)来处理它,下面的答案是如何处理它:https://stackoverflow.com/a/24420524/6396981
但是之前,在您的serializer.py

from rest_framework import serializers

from yourapp.models import Snippet

class SnippetSerializer(serializers.ModelSerializer):
    user = serializers.CharField(
        source='user.pk',
        read_only=True
    )
    photo = serializers.ImageField(
        max_length=None,
        use_url=True
    )
    ....

    class Meta:
        model = Snippet
        fields = ('user', 'title', 'photo', 'description')

    def create(self, validated_data):
        return Snippet.objects.create(**validated_data)

为了测试它,一个例子使用curl命令;

$ curl -X GET http://localhost:8000/snippets/<pk>/

# example;

$ curl -X GET http://localhost:8000/snippets/99999/

希望能有所帮助。.

更新

如果你想用DRF处理所有错误404 URL,DRF也提供了APIException,这个答案可能会对你有所帮助;https://stackoverflow.com/a/30628065/6396981
我将给予一个例子说明如何使用它;

1. views.py

from rest_framework.exceptions import NotFound

def error404(request):
    raise NotFound(detail="Error 404, page not found", code=404)

2. urls.py

from django.conf.urls import (
  handler400, handler403, handler404, handler500)

from yourapp.views import error404

handler404 = error404

制作您的DEBUG = False

gstyhher

gstyhher2#

from rest_framework import status    
from rest_framework.response import Response

# return 404 status code    
return Response({'status': 'details'}, status=status.HTTP_404_NOT_FOUND)
7jmck4yq

7jmck4yq3#

更简单的方法是在django中使用get_object_or_404方法:
如本链接所述:
get_object_or_404(klass,*args,kwargs)
-
在给定的模型管理器上调用get(),但它引发Http 404而不是模型的DoesNotExist异常。
-
klass:获取对象的Model类、Manager或QuerySet示例。
举个例子,注意

obj = get_object_or_404(Snippet, pk=pk)
return obj

在下面的代码中:

from django.shortcuts import get_object_or_404
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.views import APIView
from rest_framework.response import Response

class SnippetDetail(APIView):
    """
    Retrieve, update or delete a snippet instance.
    """
    def get_object(self, pk):
        obj = get_object_or_404(Snippet, pk=pk)
        return obj

    def get(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)
    ...
mklgxw1f

mklgxw1f4#

或者简单地说,您可以使用相同的DRF结构,而不会丢失I18N并保持相同的DRF错误消息:

from rest_framework import viewsets, status, exceptions
from rest_framework.decorators import action
from rest_framework.response import Response

try:
  codename = get_or_bad_request(self.request.query_params, 'myparam')
  return Response(self.get_serializer(MyModel.objects.get(myparam=codename), many=False).data)
except MyModel.DoesNotExist as ex:
  exc = exceptions.NotFound()
  data = {'detail': exc.detail}
  return Response(data, exc.status_code)

相关问题