File: queries.rst

package info (click to toggle)
graphql-core 3.2.6-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,384 kB
  • sloc: python: 45,812; makefile: 26; sh: 13
file content (129 lines) | stat: -rw-r--r-- 3,920 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
Executing Queries
-----------------

.. currentmodule:: graphql.execution

Now that we have defined the schema and breathed life into it with our resolver
functions, we can execute arbitrary query against the schema.

The :mod:`graphql` package provides the :func:`graphql.graphql` function to execute
queries. This is the main feature of GraphQL-core.

Note however that this function is actually a coroutine intended to be used in
asynchronous code running in an event loop.

Here is one way to use it::

    import asyncio
    from graphql import graphql

    async def query_artoo():
        result = await graphql(schema, """
        {
          droid(id: "2001") {
            name
            primaryFunction
          }
        }
        """)
        print(result)

    asyncio.run(query_artoo())

In our query, we asked for the droid with the id 2001, which is R2-D2, and its primary
function, Astromech. When everything has been implemented correctly as shown above, you
should get the expected result::

    ExecutionResult(
        data={'droid': {'name': 'R2-D2', 'primaryFunction': 'Astromech'}},
        errors=None)

The :class:`ExecutionResult` has a ``data`` attribute with the actual result, and an
``errors`` attribute with a list of errors if there were any.

If all your resolvers work synchronously, as in our case, you can also use the
:func:`graphql.graphql_sync` function to query the result in ordinary synchronous code::

    from graphql import graphql_sync

    result = graphql_sync(schema, """
      query FetchHuman($id: String!) {
        human(id: $id) {
          name
          homePlanet
        }
      }
      """, variable_values={'id': '1000'})
    print(result)

Here we asked for the human with the id 1000, Luke Skywalker, and his home planet,
Tatooine. So the output of the code above is::

    ExecutionResult(
        data={'human': {'name': 'Luke Skywalker', 'homePlanet': 'Tatooine'}},
        errors=None)

Let's see what happens when we make a mistake in the query, by querying a non-existing
``homeTown`` field::

    result = graphql_sync(schema, """
        {
          human(id: "1000") {
            name
            homePlace
          }
        }
        """)
    print(result)

You will get the following result as output::

    ExecutionResult(data=None, errors=[GraphQLError(
        "Cannot query field 'homePlace' on type 'Human'. Did you mean 'homePlanet'?",
        locations=[SourceLocation(line=5, column=9)])])

This is very helpful. Not only do we get the exact location of the mistake in the query,
but also a suggestion for correcting the bad field name.

GraphQL also allows to request the meta field ``__typename``. We can use this to verify
that the hero of "The Empire Strikes Back" episode is Luke Skywalker and that he is in
fact a human::

    result = graphql_sync(schema, """
        {
          hero(episode: EMPIRE) {
            __typename
            name
          }
        }
        """)
    print(result)

This gives the following output::

    ExecutionResult(
        data={'hero': {'__typename': 'Human', 'name': 'Luke Skywalker'}},
        errors=None)

Finally, let's see what happens when we try to access the secret backstory of our hero::

    result = graphql_sync(schema, """
        {
          hero(episode: EMPIRE) {
            name
            secretBackstory
          }
        }
        """)
    print(result)

While we get the name of the hero, the secret backstory fields remains empty, since its
resolver function raises an error. However, we get the error that has been raised by the
resolver in the ``errors`` attribute of the result::

    ExecutionResult(
        data={'hero': {'name': 'Luke Skywalker', 'secretBackstory': None}},
        errors=[GraphQLError('secretBackstory is secret.',
                locations=[SourceLocation(line=5, column=9)],
                path=['hero', 'secretBackstory'])])