graphene 自体で完成しているわけではなく、実は graphene の下に graphql-core や graphql-relay といったライブラリが潜り込んでいる。GraphQL はその生い立ちから JavaScript 環境下でよく利用されているので、graphql-core は移植版になっている。そのコアライブラリである graphql を、さらに python 的に使いやすくしたものが graphene となる。graphene のドキュメントで「記述が不足してるな」と思ったときは、実は下位ライブラリの説明部分だったりする。最終的にはリファレンス実装まで遡ると答えが見つかったりする。
graphene のフィールド定義手順は mixin で追加しやすいようになっている。クラス継承を使おうとすると落とし穴にはまるので、mixin のスタイルがおすすめ。
graphene.relay : relay 自体は GraphQL をベースとした追加仕様。広く使われているので、基本的に対応したほうが混乱が少ない。Connection と Node というインターフェースが目立つ。
Node interface
Node では id から node query 経由で単体のオブジェクトが引ける。標準では見えないので、必要に応じて用意する。このようなアクセスパスが望ましくない場合(たとえばセキュリティ上の都合など)は、実装を省略すると良い。
graphene.relay.Node でアクセスしなくても graphene.Node でインポートできる。
Connection interface
Connection の total_count は、ライブラリで非対応。別途手当しておくとトラブルが少ない。例えば graphene-sqlalchemy で query object から導出しないといけない場合があるので、あえて隔離してあるのだろうと推測される。
https://github.com/graphql-python/graphene/issues/776
https://github.com/graphql-python/graphene-django/issues/162
relay.Connection 対応では relay.Node 側のメタデータで Node interfaces 対応していることを宣言することになっている。
graphene_sqlalchemy.SQLAlchemyConnection では Node interface 宣言をいれると、二重定義を引き起こすので、うまいことやる(現状はハック的な対応で乗り切るのがよさそう)。
ConnectionField の第一引数は lambda: で遅延させると宣言順序の罠を抜け出せる。