How change the Connection Arguments (after, before) in graphene-python (relay)?

1.3k Views Asked by At

Using:

  • Django 3.x [ Django-Filters 2.2.0, graphene-django 2.8.0, graphql-relay 2.0.1 ]
  • Vue 2.x [ Vue-Apollo ]

After applying some filters (iContains etc.) on my graphQL search i tried to change or manipulate the connection_args like firstor after. I can fetch a Dictionary on my resolver like {'first': 2, 'name__icontains': 'eagle'} with values i put in the IDE. As you can see (Example 1 /def resolve_all_birds2) i use that already for a logic. But i do not understand where do manipulate the GraphQLArgument states of the before. after first. last function which comes with relay?

Example 1

class ExtendedConnection(Connection):

    class Meta:
        abstract = True

    total_count = Int()
    edge_count = Int()

    def resolve_total_count(root, info, **kwargs):
        return root.length

    def resolve_edge_count(root, info, **kwargs):
        return len(root.edges)

class Birds2Node(DjangoObjectType):
    class Meta:
        model = Birds
        filter_fields =  {
            'id':  ['exact', 'icontains'],
            'name': ['exact', 'icontains', 'istartswith', 'iendswith'],
        }

        interfaces = (relay.Node, )
        connection_class = ExtendedConnection

    # --- CUSTOM FIELDS -->
    # pkey = _db primary key 
    pKey = Int()
    def resolve_pKey(parent, info):
        return parent.pk

    # qRank = Item Rank in Edge Array
    qRank = Int()
    def resolve_qRank(parent, info, **kwargs):
        return info.path[2]

class Birds2Query(ObjectType):
    birds2 = relay.Node.Field(Birds2Node)
    all_birds2 = DjangoFilterConnectionField(Birds2Node)


    def resolve_all_birds2(self, info, **kwargs):
        if 'name__icontains' in kwargs:
            nameIcon = kwargs['name__icontains']
            nameIconBool = bool(nameIcon.strip()) # if blanks turns False
            if nameIconBool == False: # has blanks         
                return Birds.objects.filter(name=None)
            pass

        if 'name__istartswith' in kwargs:
            nameIsta = kwargs['name__istartswith']
            nameIstaBool = bool(nameIsta.strip()) # if blanks turns False
            if nameIstaBool == False: # has blanks         
                return Birds.objects.filter(name=None)
            pass      

        return 

For example, in my IDE i declare allBirds2(first: 2, name_Icontains: "a")... i can fetch these values with my resolver as a Dictionary via **kwargs`` or via args def resolve_all_birds2(self, info, first, name_icontains): so far so good, i can manipulate my ModelQuery and it returned only 2 per Edge.

But Imagine i want to change first: 2 to first: 10 in my BackEnd? Can i update the Dictionary? The Documentation means yes, but it seems strict related to the ObjectTypes (Fields) you resolve. For Example i tried this...

Example 2

def resolve_all_birds2(self, info, **kwargs):
     <...>            
    return {'first': '20', 'name__icontains': 'd' }

Output IDE: "message": "'dict' object has no attribute 'model'"

Example 3

def resolve_all_birds2(self, info, first, **kwargs):
     <...>            
    return f'20, {first}!'

Output IDE: "message": "name 'first' is not defined",


Question

Unfortunately i found only parameter manipulation on the modelquery in the graphene-python docs. So my Question is how can i manipulate - in my backend - the Values of the Fields before. after first. last, that relay offers and that are already useable in my IDE. Do i have to declare them extra in my DjangoObjectType or create a custom Node to manipulate and change the values after a user sends a request?

1

There are 1 best solutions below

0
On

Adding a middleware would probably allow changing the input values after the request is made and before running the query. Graphene has an example at: https://docs.graphene-python.org/en/latest/execution/middleware/

However, it's not clear (to me) from the documentation which of the mentioned parameters would contain the first field you want to manipulate.

The middleware approach does not seem to be highly recommended, though, because this is an undesirable side effect: https://github.com/graphql-python/graphene/issues/1285