Graphene: Custom Directive and specifying the same on a Field and Type

Created on 11 Jun 2019  路  5Comments  路  Source: graphql-python/graphene

I've tried looking at the documentation to figure out how to accomplish this but got no where.

How do I define a schema like this using Graphene?

directive @unique(
  info: String = "Blah blah"
) on FIELD_DEFINITION | ENUM_VALUE

directive @ignore(
  info: String = Blah blah"
) on OBJECT

type ExampleType @ignore(info: "Blah"){
  newField: String
  oldField: String @unique(info: "Blah")
}

Most helpful comment

@jkimbo Thank you for the confirmation. I thought I was missing something. I believe there is merit in implementing directives as I find that a good way to signal behavior formally (rather than in comments) to both the user of the schema/service and the implementer of the resolver logic.

I quite liked the way that prisma (https://www.prisma.io/) uses directives to provide more expressiveness when using the SDL to describe ORM like interactions with a database.

For the moment, I am exploring using GraphQLS2S for defining the schema in an SDL superset (that support inheritance, generics etc to help reduce verbosity) and then transpiling it to standard SDL. After I have the final schema, I am using ariadne to implement the actual resolver logic.

All 5 comments

@prashanthellina it's not documented but you can pass directives when you create your schema:

from graphql.types.directives import specified_directives  # <== default directives
from graphene import Schema

schema = Schema(query=Query, directives=specified_directives + [MyDirective])

You'll have to define your own directives but you can see how the @skip and @include and defined here: https://github.com/graphql-python/graphql-core/blob/8f7c8f3351dd0a4580b87f293aed7bfcf9126bc4/graphql/type/directives.py#L69-L98

Thank you @jkimbo for the example above. I can understand how this will help in accomplishing this part of the schema.

directive @unique(
  info: String = "Blah blah"
) on FIELD_DEFINITION | ENUM_VALUE

directive @ignore(
  info: String = Blah blah"
) on OBJECT

What do I do to get this part:

type ExampleType @ignore(info: "Blah"){
  newField: String
  oldField: String @unique(info: "Blah")
}

i.e. Telling Graphene to apply the custom directives I defined, at a field / object / enum level.

I _believe_ decorating on the Query would be supported by the resolver argument info. You can get the arguments from the resolve info parameter:

https://docs.graphene-python.org/en/latest/api/#execution-metadata

You'd have to write your logic in a decorating function or in the resolver itself.

I don't think that there is currently support for applying decorators on Schema, but you can definitely emulate the desired behavior through a wrapping class (kind of like List and NonNull in graphene). I'd love to dig into this a bit more though!

Here's an example of how directives are implemented in graphql-tools for Js.

https://www.apollographql.com/docs/graphql-tools/schema-directives/

@prashanthellina thanks for your patience. So I've looked into this a bit more and it looks like it's not possible to apply directives on a field/object level. This is a conscious limitation of the reference GraphQL server implementation graphql-js. You can read more about the reasoning here: https://github.com/graphql/graphql-js/pull/746#issuecomment-301554231 and follow the ongoing discussion about it here: https://github.com/graphql/graphql-js/issues/1343

The relevant comments from leebyron are:

Right now directives are purely a feature of the GraphQL language and IDL, so a schema not created using IDL definitionally won't contain directives. When building a schema in code, you have the full power of the host programming environment, so directives shouldn't be necessary. Directives are a tool for supplying additional intent to be later interpreted by the host programming environment.

and

Directives are purely a feature of the GraphQL language and are not part of type definitions - this is because different tools will use and interpret directives in different ways.

(there is also a great long comment which explains things in detail)

Since Graphene is based on graphql-core which is a direct port of the graphql-js implementation, support for directives on fields/objects won't happen until that support is available in graphql-js.

I hope that's helpful. You might also want to checkout ariadne which is an alternative way of building a GraphQL server using the SDL.


I'm going to create an new issue to document adding custom directives to the schema and then close this one.

@jkimbo Thank you for the confirmation. I thought I was missing something. I believe there is merit in implementing directives as I find that a good way to signal behavior formally (rather than in comments) to both the user of the schema/service and the implementer of the resolver logic.

I quite liked the way that prisma (https://www.prisma.io/) uses directives to provide more expressiveness when using the SDL to describe ORM like interactions with a database.

For the moment, I am exploring using GraphQLS2S for defining the schema in an SDL superset (that support inheritance, generics etc to help reduce verbosity) and then transpiling it to standard SDL. After I have the final schema, I am using ariadne to implement the actual resolver logic.

Was this page helpful?
0 / 5 - 0 ratings