如何为石墨烯/ django-graphene中的错误返回定制的JSON响应?

Aiv*_*ven 5 graphene-python

我想将状态字段添加到错误响应中,所以要这样做:

{
  "errors": [
    {
      "message": "Authentication credentials were not provided",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ]
    }
  ],
  "data": {
    "viewer": null
  }
}
Run Code Online (Sandbox Code Playgroud)

应该是这样的:

{
  "errors": [
    {
      "status": 401,  # or 400 or 403 or whatever error status suits
      "message": "Authentication credentials were not provided",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ]
    }
  ],
  "data": {
    "viewer": null
  }
}
Run Code Online (Sandbox Code Playgroud)

我发现只能通过在resolver:中引发Exception来更改消息raise Error('custom error message'),但是如何添加字段?

代码示例:

class Query(UsersQuery, graphene.ObjectType):
    me = graphene.Field(SelfUserNode)

    def resolve_me(self, info: ResolveInfo):
        user = info.context.user
        if not user.is_authenticated:
            # but status attr doesn't exist...
            raise GraphQLError('Authentication credentials were not provided', status=401)  
        return user
Run Code Online (Sandbox Code Playgroud)

dsp*_*ejs 8

GraphQLView使用以下内容更新默认值:

from graphene_django.views import GraphQLView as BaseGraphQLView


class GraphQLView(BaseGraphQLView):

    @staticmethod
    def format_error(error):
        formatted_error = super(GraphQLView, GraphQLView).format_error(error)

        try:
            formatted_error['context'] = error.original_error.context
        except AttributeError:
            pass

        return formatted_error


urlpatterns = [
    path('api', GraphQLView.as_view()),
]
Run Code Online (Sandbox Code Playgroud)

这将context在引发的任何异常中查找该属性。如果它存在,它将使用此数据填充错误。

现在,您可以为填充context属性的不同用例创建例外。在这种情况下,您想将状态代码添加到错误中,这是您如何执行此操作的示例:

class APIException(Exception):

    def __init__(self, message, status=None):
        self.context = {}
        if status:
            self.context['status'] = status
        super().__init__(message)
Run Code Online (Sandbox Code Playgroud)

你会像这样使用它:

raise APIException('Something went wrong', status=400)
Run Code Online (Sandbox Code Playgroud)


Mau*_*zar 1

我没有找到按照您建议的方式解决您的问题的方法,否则我将LoginRequiredMixin像这样扩展该类:

class LoginRequiredMixin:
    def dispatch(self, info, *args, **kwargs):
        if not info.user.is_authenticated:
            e =  HttpError(HttpResponse(status=401, content_type='application/json'), 'Please log in first')
            response = e.response
            response.content = self.json_encode(info, [{'errors': [self.format_error(e)]}])
            return response

            return super().dispatch(info, *args, **kwargs)

class PrivateGraphQLView(LoginRequiredMixin, GraphQLView):
    schema=schema
Run Code Online (Sandbox Code Playgroud)

并在您的网址中:

from django.views.decorators.csrf import csrf_exempt
from educor.schema import PrivateGraphQLView
url(r'^graphql', csrf_exempt(PrivateGraphQLView.as_view(batch=True)))
Run Code Online (Sandbox Code Playgroud)

您无法使用 graphiql 查看状态,但在您的客户端中,您可以在标题中获取它,或者您可以修改此行以添加到响应中response.content = self.json_encode(info, [{'errors': [self.format_error(e)]}]) 。希望它能有所帮助,无论如何我会给你留下另一个可能的解决方案https://github.com/graphql-python/graphene-django/issues/252