2

I've recently started learning how to use python and i'm having some trouble with a graphQL api call.

I'm trying to set up a loop to grab all the information using pagination, and my first request is working just fine.

values = """
      {"query" : "{organizations(ids:) {pipes {id name phases {id name cards_count cards(first:30){pageInfo{endCursor hasNextPage} edges {node {id title current_phase{name} assignees {name} due_date createdAt finished_at fields{name value filled_at updated_at} } } } } }}}"}
    """

but the second call using the end cursor as a variable isn't working for me. I assume that it's because i'm not understanding how to properly escape the string of the variable. But for the life of me I'm unable to understand how it should be done.

Here's what I've got for it so far...

values = """
      {"query" : "{phase(id: """ + phaseID+ """ ){id name cards_count cards(first:30, after:"""\" + pointer + "\"""){pageInfo{endCursor hasNextPage} edges {node {id title assignees {name} due_date createdAt finished_at fields{name value datetime_value updated_at phase_field { id label }  } } } } } }"}
        """ 

the second one as it loops just returns a 400 bad request.

Any help would be greatly appreciated.

2 Answers 2

7

As a general rule you should avoid building up queries using string manipulation like this.

In the GraphQL query itself, GraphQL allows variables that can be placeholders in the query for values you will plug in later. You need to declare the variables at the top of the query, and then can reference them anywhere inside the query. The query itself, without the JSON wrapper, would look something like

query = """
  query MoreCards($phase: ID!, $cursor: String) {
    phase(id: $phase) {
      id, name, cards_count
      cards(first: 30, after: $cursor) {
        ... CardConnectionData
      }
    }
  }
"""

To actually supply the variable values, they get passed as an ordinary dictionary

variables = {
  "phase": phaseID,
  "cursor": pointer
}

The actual request body is a straightforward JSON structure. You can construct this as a dictionary too:

body = {
  "query": query,
  "variables": variables
}

Now you can use the standard json module to format it to a string

print(json.dumps(body))

or pass it along to something like the requests package that can directly accept the object and encode it for you.

Sign up to request clarification or add additional context in comments.

2 Comments

Ah this is excellent thank you! Is it advisable to not use string manipulation due to the problem I was having or are there other reasons I should be aware of?
Incidents such as xkcd.com/327 are possible if you build up queries via string concatenation. That’s SQL but the same principle applies in GraphQL, XML, JSON, ...
0

I had a similar situation where I had to aggregate data through paginating from a GraphQL endpoint. Trying the above solution didn't work for me that well.

to start my header config for graphql was like this:

 headers = {
        "Authorization":f"Bearer {token}",
        "Content-Type":"application/graphql"
}

for my query string, I used the triple quote with a variable placeholder:

  user_query = 
   """
         {
           user(
                limit:100,
                page:$page,
                sort:[{field:"email",order:"ASC"}]
            ){
                list{
                    email, 
                    count
                 }
            }
   """

Basically, I had my loop here for the pages:

for page in range(1, 9):
    formatted_query = user_query.replace("$page",f'{page}')
    response = requests.post(api_url, data=formatted_query, 
    headers=headers)
    status_code, json = response.status_code, response.json()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.