graphene icon indicating copy to clipboard operation
graphene copied to clipboard

Exception handeling in query

Open nrbnlulu opened this issue 2 years ago • 1 comments

#513

all the solution mentioned in this issue are for mutation, is there a way to send custom output for a query?

I am trying to handle permissions for different queries and have decorators that will filter premonitions from resolver example code would be like this:



class OutputMixin:
    """
    A class to all public classes extend to
    padronize the output
    """

    success = graphene.Boolean(default_value=True)
    errors = graphene.Field(ExpectedErrorType)


class ServerStatusType(DjangoObjectType, OutputMixin):
    class Meta:
        model = models.ServerStatusRecord



def admin_only(fn):
    def wrapper(root, info  *args, **kwargs):
        user = info.context.user
        if user.is_admin:
            return fn(*args, **kwargs)
        return cls(success=False, errors=Messages.NOT_VERIFIED)

    return wrapper


class StatusQuery(graphene.ObjectType):
    current_status = graphene.Field(ServerStatusType)


    @admin_only
    def resolve_current_status(cls, root, info, **kwargs):
        return models.ServerStatusRecord.objects.latest()


While this code works flawlessly with mutations it doesn't work with queries because the the resolve function isn't accepting the object type as the first argument the object exists under info.return_type.graphene_type(success=False, errors="fdsaf") but its seems like a terrible hack and all the fields are required so i cant return just that.

nrbnlulu avatar Mar 16 '22 11:03 nrbnlulu

Is there a specific reason for you to use a custom type for errors instead of referring to the inbuilt exception handling? When you throw an exception in graphene, these errors are incorporated into your response:

{
    "data": {
       your response data/query data
    },
    "errors": [
        {
            "message": "Exception",
            "locations": [
                {
                    "line": 2,
                    "column": 3
                }
            ],
            "path": [
                "name of your query/mutation"
            ]
        }
    ]
}

Your wrappers could look like this:


def admin_only(fn):
    def wrapper(root, info  *args, **kwargs):
        user = info.context.user
        if user.is_admin:
            return fn(*args, **kwargs)
        raise GraphQLError(Messages.NOT_VERIFIED)

    return wrapper

The advantage of this approach is, that clients like Apollo support error handlers for this notation by default.

This does also work for queries, but you have to annotate the resolvers correctly. If for other reasons you still want to stick to your approach, please send an example that includes a query that is also annotated. Maybe I can help you find the reason of failure then.

erikwrede avatar Apr 01 '22 12:04 erikwrede