【问题标题】:Raising exceptions with django_rest_framework使用 django_rest_framework 引发异常
【发布时间】:2016-01-01 00:16:33
【问题描述】:

我编写了一个视图,它可以解密 GPG 加密文件并将其作为纯文本返回。这通常工作正常。问题是,如果文件为空或包含无效的 GPG 数据,gnupg 会返回空结果而不是抛出异常。

我需要能够在 decrypt_file 中执行类似的操作,以检查解密是否失败并引发错误:

if data.ok:
    return str(data)
else:
    raise APIException(data.status)

如果我这样做,我会在 Django 调试输出中看到 APIException,但它不会转换为对客户端的 500 响应。相反,客户端会收到 200 响应,但正文为空。我可以在我的 get 方法中引发 APIException,它会发送 500 响应,但我无法访问 gnupg 错误消息。

这是我的观点的一个非常简化的版本:

from rest_framework.views import APIView
from django.http import FileResponse
from django.core import files
from gnupg import GPG

class FileDownload(APIView):
    def decrypt_file(self, file):
        gpg = GPG()
        data = gpg.decrypt(file.read())
        return data

    def get(self, request, id, format=None):
        f = open('/tmp/foo', 'rb')
        file = files.File(f)
        return FileResponse(self.decrypt_file(file))

我已经阅读了有关 DRF 异常处理 here 的文档,但它似乎并没有为这个问题提供解决方案。一般来说,我对 Django 和 python 还很陌生,所以我完全有可能遗漏了一些明显的东西。有用的建议将不胜感激。谢谢。

【问题讨论】:

    标签: python django python-2.7 exception-handling django-rest-framework


    【解决方案1】:

    如果您在 python 中引发错误,跟踪中的每个函数都会重新引发它,直到有人发现它为止。你可以先声明一个异常:

    from rest_framework.exceptions import APIException
    
    class ServiceUnavailable(APIException):
        status_code = 503
        default_detail = 'Service temporarily unavailable, try again later.'
    

    然后在您的decrypt_file 函数中,如果解密不成功,则引发此异常。您可以传递参数来修改消息。然后,在get 方法中,您应该调用decrypt_file 函数并将您的文件作为参数传递。如果出现任何问题,您的函数会引发该异常,然后获取方法重新引发它,直到 Django Rest Framework 异常处理程序捕获它。
    编辑:
    在您的解密函数中,执行以下操作:

    from rest_framework.response import Response
    
    def decrypt_file(self, file):
        ... # your codes
        if data.ok:
            return str(data)
        else:
            raise ServiceUnavailable
    
    def get(self, request, id, format=None):
        f = open('/tmp/foo', 'rb')
        result = decrypt_file(f)
        f.close()
        return Response({'data': result})
    

    【讨论】:

    • 当我尝试使用 curl 进行操作时,我得到: curl: (52) Empty reply from server The django log shows: [30/Dec/2015 21:10:47] "GET /files /56833fe5e138236d46b1385c HTTP/1.1" 500 59 因此,它返回 500,但不是带有错误消息的 JSON 正文。
    • 实际上,它抛出的是 500,而不是异常类中设置的 503。在日志中,我看到“ServiceUnavailable:服务暂时不可用,稍后再试。”,所以它消失了,但是 500 是由于“AttributeError:'NoneType' 对象没有属性'split'”而发生的,因为 ServiceUnavailable 异常是不是致命的,并且该函数将空白结果传递回调用函数,该函数需要一些数据。
    • 我刚刚编辑了答案。检查一下并告诉我是否存在问题。
    猜你喜欢
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    • 1970-01-01
    • 2014-10-25
    • 2014-11-20
    • 1970-01-01
    • 2016-02-28
    • 1970-01-01
    相关资源
    最近更新 更多