Graphene: Share fields between mutation input and relay Node

Created on 9 Dec 2015  路  8Comments  路  Source: graphql-python/graphene

I want to share fields between a relay Node and a mutation input as shown in this example: http://graphene-python.org/playground/?schema=import%2520collections%250A%250Aimport%2520graphene%250Afrom%2520graphene%2520import%2520relay%250A%250Aclass%2520SharedUserFields(graphene.ObjectType)%253A%250A%2520%2520%2520%2520first_name%2520%253D%2520graphene.String()%250A%2520%2520%2520%2520last_name%2520%253D%2520graphene.String()%250A%250Aclass%2520User(relay.Node)%253A%250A%2520%2520%2520%2520user_id%2520%253D%2520graphene.ID()%250A%250A%2520%2520%2520%2520%2540classmethod%250A%2520%2520%2520%2520def%2520get_node(cls%252C%2520user_id)%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520user%2520%253D%2520%257B%27user_id%27%253A%2520%271%27%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520return%2520User(user)%250A%250AUser.extend_fields(%255BSharedUserFields%255D)%250A%250Aclass%2520UpdateCustomer(relay.ClientIDMutation)%253A%250A%2520%2520%2520%2520class%2520Input(SharedUserFields)%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520pass%250A%2509%250A%2520%2520%2520%2520user%2520%253D%2520graphene.Field(User)%250A%2520%2520%2520%2520%250A%2520%2520%2520%2520def%2520mutate_and_get_payload(cls%252C%2520mutation_input%252C%2520info)%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2523%2520update%2520stuff%2520here%250A%2520%2520%2520%2520%2520%2520%2520%2520return(User(first_name%253D%27Mutated%2520first_name%27))%250A%2520%2520%2520%2520%250Aclass%2520Query(graphene.ObjectType)%253A%250A%2520%2520%2520%2520user%2520%253D%2520graphene.Field(User)%250A%2520%2520%2520%2520%250A%2520%2520%2520%2520def%2520resolve_user(self%252C%2520args%252C%2520info)%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520user%2520%253D%2520%257B%27user_id%27%253A%2520%271%27%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520return%2520User(user)%250A%250Aschema%2520%253D%2520graphene.Schema(query%253DQuery)%250A&query=query%2520testQuery%2520%257B%250A%2520%2520user%2520%257B%250A%2520%2520%2520%2520firstName%250A%2520%2520%2520%2520%257D%250A%257D

For some reason extend_fields does not work on the playground but maybe the graphene version is outdated.

But how would it be possible to share graphene fields between the User relay Node and the UpdateCustomerInput to reduce duplication?

All 8 comments

I have also tried

class Input(object):
            __metaclass__ = TestCustomer
...

based on the example linked above, but then getting:

  File "third_party/python/graphene/core/classtypes/objecttype.py", line 60, in __init__
    raise IndexError("Number of args exceeds number of fields")
IndexError: Number of args exceeds number of fields

If I remove the check if args_len > len(fields): in the objecttype.py the code at least compiles. Still have to test what happens then, will try tomorrow.

@Globegitter The url is not working well (some error in the Graphene IDE?).
Meanwhile can you copy & paste here the code so I can see what's happening?

Outside of work already unfortunately. Will post tomorrow.

@syrusakbary here is the example:

import graphene
from graphene import relay

class SharedUserFields(graphene.ObjectType):
    first_name = graphene.String()
    last_name = graphene.String()

class User(relay.Node):
    user_id = graphene.ID()

    @classmethod
    def get_node(cls, user_id):
        user = {'user_id': '1'}
        return User(**user)

User.extend_fields([SharedUserFields])

class UpdateCustomer(relay.ClientIDMutation):
    class Input(SharedUserFields):
        pass

    user = graphene.Field(User)

    def mutate_and_get_payload(cls, mutation_input, info):
        # update stuff here
        return(User(first_name='Mutated first_name'))

class Query(graphene.ObjectType):
    user = graphene.Field(User)

    def resolve_user(self, args, info):
        user = {'user_id': '1'}
        return User(**user)

schema = graphene.Schema(query=Query)

Thanks for looking into this so quickly.

Edit: If I add it as a metaclass to the Input class as in the example above and I comment out the if check I am getting the following error on a mutation: GraphQLError: Variable "$input_0" expected value of type "UpdateCustomerInput!" but got: {"firstName": "Pete"}.

@syrusakbary any update on this?
I am just running into this again. Refactoring our queries and mutations and again have to copy and paste the shared fields between the two.

I also tried to use graphene.Interface but also does not seem to work.

Will work on that soon! :)

@syrusakbary I would also be happy to look into this myself. Do you have any starting pointers? Would love to give something back to this library, this issue just seems to be quite deeply rooted :)

This is now fixed in the master branch (1.0.dev version in PyPI), as you can make reusable AbstractType for sharing fields.

Closing the issue! :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

danpalmer picture danpalmer  路  4Comments

jloveric picture jloveric  路  4Comments

defrex picture defrex  路  3Comments

ghoshabhi picture ghoshabhi  路  3Comments

dfee picture dfee  路  4Comments