33

I'm trying to do this (see title), but it's a bit complicated since the string I'm trying to build has to have the following properties:

  • mulitiline
  • contains curly braces
  • I want to inject variables into it

Using a normal '''''' multiline string makes injecting variables difficult. Using multiple f-strings makes injecting variables easy, but every curly brace, of which there are a lot, has to be doubled. And an f has to be prepended to each line. On the other hand, if I try using format, it also gets confused by all the curly braces.

Are there even more ways that I haven't considered yet? Which?

3
  • Maybe template strings, or a full blown template library? Or write yourself a library to construct your graphql in a functional way, and hide the details. Commented Jun 15, 2020 at 8:32
  • 2
    I only found this lib pypi.org/project/gql-query-builder Commented Dec 27, 2021 at 18:57
  • 30 upvotes and closed as opinion-based. Stackoverflow has become so irrelevant :D Commented Aug 19 at 14:21

4 Answers 4

45

You can use the """ multiline string method. For injecting variables, make sure to use the $ sign while defining the string and use the variables object in the JSON parameter of the requests.post method.

Here is an example. ContactInput is one of the types I defined in my GraphQL schema.

query = """
  mutation ($input:[ContactInput!]!) {
    AddContacts(contacts: $input) {
      user_id
    }
  }
"""
variables = {'input': my_arrofcontacts}
r = requests.post(url, json={'query': query , 'variables': variables})
Sign up to request clarification or add additional context in comments.

2 Comments

How can syntax highlighting be applied to this multiline string?
It does not work In my case, (python 3.8). This link is the solution by @chris-lindseth. With string format like as, Just use multiline string (""") with f prefix and for variable use '{variable}'. for brace ('{', '}') use double for that like as ('{{', '}}')
4

you can use the following package graphql-query

For example, for the query

{
  leftComparison: hero(episode: EMPIRE) {
    ...comparisonFields
  }
  rightComparison: hero(episode: JEDI) {
    ...comparisonFields
  }
}

fragment comparisonFields on Character {
  name
  appearsIn
  friends {
    name
  }
}

we have the following code

from graphql_query import Argument, Operation, Query, Fragment, Field

comparisonFields = Fragment(
    name="comparisonFields",
    type="Character",
    fields=["name", "appearsIn", Field(name="friends", fields=["name"])]
)

leftComparison = Query(
    name="hero",
    alias="leftComparison",
    arguments=[Argument(name="episode", value="EMPIRE")],
    fields=[comparisonFields]
)

rightComparison = Query(
    name="hero",
    alias="rightComparison",
    arguments=[Argument(name="episode", value="JEDI")],
    fields=[comparisonFields]
)

operation = Operation(
    type="query",
    queries=[leftComparison, rightComparison],
    fragments=[comparisonFields]
)
print(operation.render())
# query {
#   leftComparison: hero(
#     episode: EMPIRE
#   ) {
#     ...comparisonFields
#   }
#
#   rightComparison: hero(
#     episode: JEDI
#   ) {
#     ...comparisonFields
#   }
# }
#
# fragment comparisonFields on Character {
#   name
#   appearsIn
#   friends {
#     name
#   }
# }

2 Comments

Full documentation can be found at this link denisart.github.io/graphql-query
Please mention your affiliation with the project.
0

One way to avoid having to escape all the curly brackets in your JSON might be to use the older-style Python string formatting...?

"""
{
   'ultimate': 'The %(foo)s is %(bar)s'
}
""" % {'foo':'answer', 'bar':42}

1 Comment

I think the OP mentioned that
-8

There is no need to construct graphQL strings to inject variables.

This is even abusing graphQL as it was designed to separate query definition and variables (arguments). It's safer, easier to validate etc.

Just learn how to use query variables to pass arguments. This is described in docs and many tutorials. You should know and use in practice this technique. Trying to use string injections can at least prove lack of your knowledge.

If you aren't writting a graphql editor or other tool then you shouldn't use string operations at all. BTW even editor shouldn't operate on strings but on AST.

It's rarely required to operate on strings in graphql, f.e. to let user choose required answer (response part of query) elements/fragments.

Update

Operating using objects is more elastic/usable - e.g. easily solves conditional problems: How to conditionally include an argument in a GraphQL query?

2 Comments

It would be extremely helpful for less experienced programmers to provide a working example of the best practices mentioned in your 'answer' instead of just sharing a single link (which not necessarily people will understand), and saying what NOT to do, and what to learn.
@lowercase00 Not working with python ... you have a working example in accepted answer ... this answer extends this, explains general graphql rules, why question (requirements), in general, is misleading ... passing variables is not 'best practice', it's a basic graphql knowledge ... look for more tutorials if still not understood or ask own, specific problem question, not about 'best practice' as asking for PERSONAL OPINIONS are off-topic on SO

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.