【问题标题】:How to return customized JSON response for an error in graphene / django-graphene?如何为石墨烯/django-graphene 中的错误返回自定义 JSON 响应?
【发布时间】:2018-08-27 05:30:22
【问题描述】:

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

{
  "errors": [
    {
      "message": "Authentication credentials were not provided",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ]
    }
  ],
  "data": {
    "viewer": null
  }
}

应该是这样的:

{
  "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
  }
}

我发现我只能通过在解析器中引发异常来更改消息: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

【问题讨论】:

  • 你能提供一些代码吗,这是突变吗?
  • @MauricioCortazar,已添加

标签: graphene-python


【解决方案1】:

使用以下内容更新默认 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()),
]

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

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

class APIException(Exception):

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

你会这样使用它:

raise APIException('Something went wrong', status=400)

【讨论】:

    【解决方案2】:

    我没有找到按照您建议的方式解决您的问题的方法,否则我像这样扩展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
    

    在你的网址中:

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

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

    【讨论】:

    • 据我所知(现在)根error 字段用于服务器错误,我需要在data 中引入自定义error 字段。但这不是最佳实践,graphql 社区如何处理用户错误仍然是一个开放的问题。现在我只是在data 中添加额外的字段:成功、状态、错误。而且按照规范,graphql 服务器应该只返回 500 和 200 状态码,所以我不能接受你的回答):
    • @Aiven 我知道,正如我所说我没有找到,所以我不希望你接受答案,但我给你这个可能对你有用的解决方案,我会添加到如果有人能回答就收藏
    猜你喜欢
    • 2018-05-17
    • 2019-01-19
    • 2022-10-25
    • 2019-12-20
    • 2018-03-22
    • 2018-02-21
    • 2021-12-02
    • 1970-01-01
    • 2020-06-16
    相关资源
    最近更新 更多