mirror of
https://github.com/graphql-python/graphene.git
synced 2025-09-21 19:32:33 +03:00
Initial work refactoring class Meta to class arguments.
Initial work refactoring class Meta to class arguments. Refactoring firehose imports to explicit imports. More blackening of example code. More refactoring of `class Meta` into class arguments.
This commit is contained in:
parent
67c4310c78
commit
eefcf40360
|
@ -106,10 +106,10 @@ leaner code and at most 4 database requests, and possibly fewer if there are cac
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class User(graphene.ObjectType):
|
class User(ObjectType):
|
||||||
name = graphene.String()
|
name = String()
|
||||||
best_friend = graphene.Field(lambda: User)
|
best_friend = Field(lambda: User)
|
||||||
friends = graphene.List(lambda: User)
|
friends = List(lambda: User)
|
||||||
|
|
||||||
def resolve_best_friend(self, info):
|
def resolve_best_friend(self, info):
|
||||||
return user_loader.load(self.best_friend_id)
|
return user_loader.load(self.best_friend_id)
|
||||||
|
|
|
@ -7,8 +7,8 @@ For executing a query a schema, you can directly call the ``execute`` method on
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
schema = graphene.Schema(...)
|
schema = Schema(...)
|
||||||
result = schema.execute('{ name }')
|
result = schema.execute("{ name }")
|
||||||
|
|
||||||
``result`` represents the result of execution. ``result.data`` is the result of executing the query, ``result.errors`` is ``None`` if no errors occurred, and is a non-empty list if an error occurred.
|
``result`` represents the result of execution. ``result.data`` is the result of executing the query, ``result.errors`` is ``None`` if no errors occurred, and is a non-empty list if an error occurred.
|
||||||
|
|
||||||
|
@ -21,14 +21,15 @@ You can pass context to a query via ``context``.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(ObjectType):
|
||||||
name = graphene.String()
|
name = String()
|
||||||
|
|
||||||
def resolve_name(root, info):
|
def resolve_name(root, info):
|
||||||
return info.context.get('name')
|
return info.context.get("name")
|
||||||
|
|
||||||
schema = graphene.Schema(Query)
|
|
||||||
result = schema.execute('{ name }', context={'name': 'Syrus'})
|
schema = Schema(Query)
|
||||||
|
result = schema.execute("{ name }", context={"name": "Syrus"})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,15 +41,16 @@ You can pass variables to a query via ``variables``.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(ObjectType):
|
||||||
user = graphene.Field(User, id=graphene.ID(required=True))
|
user = Field(User, id=ID(required=True))
|
||||||
|
|
||||||
def resolve_user(root, info, id):
|
def resolve_user(root, info, id):
|
||||||
return get_user_by_id(id)
|
return get_user_by_id(id)
|
||||||
|
|
||||||
schema = graphene.Schema(Query)
|
|
||||||
|
schema = Schema(Query)
|
||||||
result = schema.execute(
|
result = schema.execute(
|
||||||
'''
|
"""
|
||||||
query getUser($id: ID) {
|
query getUser($id: ID) {
|
||||||
user(id: $id) {
|
user(id: $id) {
|
||||||
id
|
id
|
||||||
|
@ -56,6 +58,6 @@ You can pass variables to a query via ``variables``.
|
||||||
lastName
|
lastName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
''',
|
""",
|
||||||
variables={'id': 12},
|
variables={"id": 12},
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,7 +12,7 @@ Let’s build a basic GraphQL schema from scratch.
|
||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
- Python (2.7, 3.4, 3.5, 3.6, pypy)
|
- Python (3.6+, pypy)
|
||||||
- Graphene (2.0)
|
- Graphene (2.0)
|
||||||
|
|
||||||
Project setup
|
Project setup
|
||||||
|
@ -35,15 +35,17 @@ one field: ``hello`` and an input name. And when we query it, it should return `
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ObjectType, Schema, String
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
|
||||||
hello = graphene.String(argument=graphene.String(default_value="stranger"))
|
class Query(ObjectType):
|
||||||
|
hello = String(argument=String(default_value="stranger"))
|
||||||
|
|
||||||
def resolve_hello(self, info, argument):
|
def resolve_hello(self, info, argument):
|
||||||
return 'Hello ' + argument
|
return f"Hello {argument}"
|
||||||
|
|
||||||
schema = graphene.Schema(query=Query)
|
|
||||||
|
schema = Schema(query=Query)
|
||||||
|
|
||||||
Querying
|
Querying
|
||||||
--------
|
--------
|
||||||
|
@ -52,11 +54,11 @@ Then we can start querying our schema:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
result = schema.execute('{ hello }')
|
result = schema.execute("{ hello }")
|
||||||
print(result.data['hello']) # "Hello stranger"
|
print(result.data["hello"]) # "Hello stranger"
|
||||||
|
|
||||||
# or passing the argument in the query
|
# or passing the argument in the query
|
||||||
result = schema.execute('{ hello (argument: "graph") }')
|
result = schema.execute('{ hello (argument: "graph") }')
|
||||||
print(result.data['hello']) # "Hello graph"
|
print(result.data["hello"]) # "Hello graph"
|
||||||
|
|
||||||
Congrats! You got your first graphene schema working!
|
Congrats! You got your first graphene schema working!
|
||||||
|
|
|
@ -16,12 +16,9 @@ and ``other`` an extra field in the Connection Edge.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class ShipConnection(Connection):
|
class ShipConnection(Connection, node=Ship):
|
||||||
extra = String()
|
extra = String()
|
||||||
|
|
||||||
class Meta:
|
|
||||||
node = Ship
|
|
||||||
|
|
||||||
class Edge:
|
class Edge:
|
||||||
other = String()
|
other = String()
|
||||||
|
|
||||||
|
@ -37,8 +34,8 @@ that implements ``Node`` will have a default Connection.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Faction(graphene.ObjectType):
|
class Faction(ObjectType):
|
||||||
name = graphene.String()
|
name = String()
|
||||||
ships = relay.ConnectionField(ShipConnection)
|
ships = relay.ConnectionField(ShipConnection)
|
||||||
|
|
||||||
def resolve_ships(self, info):
|
def resolve_ships(self, info):
|
||||||
|
|
|
@ -12,13 +12,12 @@ subclass of ``relay.ClientIDMutation``.
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class IntroduceShip(relay.ClientIDMutation):
|
class IntroduceShip(relay.ClientIDMutation):
|
||||||
|
|
||||||
class Input:
|
class Input:
|
||||||
ship_name = graphene.String(required=True)
|
ship_name = String(required=True)
|
||||||
faction_id = graphene.String(required=True)
|
faction_id = String(required=True)
|
||||||
|
|
||||||
ship = graphene.Field(Ship)
|
ship = Field(Ship)
|
||||||
faction = graphene.Field(Faction)
|
faction = Field(Faction)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **input):
|
def mutate_and_get_payload(cls, root, info, **input):
|
||||||
|
@ -28,8 +27,6 @@ subclass of ``relay.ClientIDMutation``.
|
||||||
faction = get_faction(faction_id)
|
faction = get_faction(faction_id)
|
||||||
return IntroduceShip(ship=ship, faction=faction)
|
return IntroduceShip(ship=ship, faction=faction)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Accepting Files
|
Accepting Files
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -37,13 +34,13 @@ Mutations can also accept files, that's how it will work with different integrat
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class UploadFile(graphene.ClientIDMutation):
|
class UploadFile(ClientIDMutation):
|
||||||
class Input:
|
class Input:
|
||||||
pass
|
pass
|
||||||
# nothing needed for uploading file
|
# nothing needed for uploading file
|
||||||
|
|
||||||
# your return fields
|
# your return fields
|
||||||
success = graphene.String()
|
success = String()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **input):
|
def mutate_and_get_payload(cls, root, info, **input):
|
||||||
|
|
|
@ -14,12 +14,10 @@ Example usage (taken from the `Starwars Relay example`_):
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Ship(graphene.ObjectType):
|
class Ship(ObjectType, interfaces=(relay.Node,)):
|
||||||
'''A ship in the Star Wars saga'''
|
"""A ship in the Star Wars saga"""
|
||||||
class Meta:
|
|
||||||
interfaces = (relay.Node, )
|
|
||||||
|
|
||||||
name = graphene.String(description='The name of the ship.')
|
name = String(description="The name of the ship.")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_node(cls, info, id):
|
def get_node(cls, info, id):
|
||||||
|
@ -45,26 +43,22 @@ Example of a custom node:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class CustomNode(Node):
|
class CustomNode(Node, name="Node"):
|
||||||
|
|
||||||
class Meta:
|
|
||||||
name = 'Node'
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def to_global_id(type, id):
|
def to_global_id(type, id):
|
||||||
return '{}:{}'.format(type, id)
|
return "{}:{}".format(type, id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_node_from_global_id(info, global_id, only_type=None):
|
def get_node_from_global_id(info, global_id, only_type=None):
|
||||||
type, id = global_id.split(':')
|
type, id = global_id.split(":")
|
||||||
if only_type:
|
if only_type:
|
||||||
# We assure that the node type that we want to retrieve
|
# We assure that the node type that we want to retrieve
|
||||||
# is the same that was indicated in the field type
|
# is the same that was indicated in the field type
|
||||||
assert type == only_type._meta.name, 'Received not compatible node.'
|
assert type == only_type._meta.name, "Received not compatible node."
|
||||||
|
|
||||||
if type == 'User':
|
if type == "User":
|
||||||
return get_user(id)
|
return get_user(id)
|
||||||
elif type == 'Photo':
|
elif type == "Photo":
|
||||||
return get_photo(id)
|
return get_photo(id)
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,7 +88,7 @@ Example usage:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(ObjectType):
|
||||||
# Should be CustomNode.Field() if we want to use our custom Node
|
# Should be CustomNode.Field() if we want to use our custom Node
|
||||||
node = relay.Node.Field()
|
node = relay.Node.Field()
|
||||||
|
|
||||||
|
|
|
@ -40,14 +40,11 @@ To use the test client, instantiate ``graphene.test.Client`` and retrieve GraphQ
|
||||||
|
|
||||||
from graphene.test import Client
|
from graphene.test import Client
|
||||||
|
|
||||||
|
|
||||||
def test_hey():
|
def test_hey():
|
||||||
client = Client(my_schema)
|
client = Client(my_schema)
|
||||||
executed = client.execute('''{ hey }''')
|
executed = client.execute("""{ hey }""")
|
||||||
assert executed == {
|
assert executed == {"data": {"hey": "hello!"}}
|
||||||
'data': {
|
|
||||||
'hey': 'hello!'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Execute parameters
|
Execute parameters
|
||||||
|
@ -61,14 +58,11 @@ You can also add extra keyword arguments to the ``execute`` method, such as
|
||||||
|
|
||||||
from graphene.test import Client
|
from graphene.test import Client
|
||||||
|
|
||||||
|
|
||||||
def test_hey():
|
def test_hey():
|
||||||
client = Client(my_schema)
|
client = Client(my_schema)
|
||||||
executed = client.execute('''{ hey }''', context={'user': 'Peter'})
|
executed = client.execute("""{ hey }""", context={"user": "Peter"})
|
||||||
assert executed == {
|
assert executed == {"data": {"hey": "hello Peter!"}}
|
||||||
'data': {
|
|
||||||
'hey': 'hello Peter!'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Snapshot testing
|
Snapshot testing
|
||||||
|
@ -95,7 +89,7 @@ Here is a simple example on how our tests will look if we use ``pytest``:
|
||||||
# This will create a snapshot dir and a snapshot file
|
# This will create a snapshot dir and a snapshot file
|
||||||
# the first time the test is executed, with the response
|
# the first time the test is executed, with the response
|
||||||
# of the execution.
|
# of the execution.
|
||||||
snapshot.assert_match(client.execute('''{ hey }'''))
|
snapshot.assert_match(client.execute("""{ hey }"""))
|
||||||
|
|
||||||
|
|
||||||
If we are using ``unittest``:
|
If we are using ``unittest``:
|
||||||
|
@ -104,8 +98,9 @@ If we are using ``unittest``:
|
||||||
|
|
||||||
from snapshottest import TestCase
|
from snapshottest import TestCase
|
||||||
|
|
||||||
|
|
||||||
class APITestCase(TestCase):
|
class APITestCase(TestCase):
|
||||||
def test_api_me(self):
|
def test_api_me(self):
|
||||||
"""Testing the API for /me"""
|
"""Testing the API for /me"""
|
||||||
client = Client(my_schema)
|
client = Client(my_schema)
|
||||||
self.assertMatchSnapshot(client.execute('''{ hey }'''))
|
self.assertMatchSnapshot(client.execute("""{ hey }"""))
|
||||||
|
|
|
@ -20,17 +20,19 @@ plus the ones defined in ``UserFields``.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import AbstractType, ObjectType, InputObjectType, String
|
||||||
|
|
||||||
class UserFields(graphene.AbstractType):
|
|
||||||
name = graphene.String()
|
|
||||||
|
|
||||||
class User(graphene.ObjectType, UserFields):
|
class UserFields(AbstractType):
|
||||||
|
name = String()
|
||||||
|
|
||||||
|
|
||||||
|
class User(ObjectType, UserFields):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class UserInput(graphene.InputObjectType, UserFields):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
class UserInput(InputObjectType, UserFields):
|
||||||
|
pass
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,10 @@ You can create an ``Enum`` using classes:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import Enum
|
||||||
|
|
||||||
class Episode(graphene.Enum):
|
|
||||||
|
class Episode(Enum):
|
||||||
NEWHOPE = 4
|
NEWHOPE = 4
|
||||||
EMPIRE = 5
|
EMPIRE = 5
|
||||||
JEDI = 6
|
JEDI = 6
|
||||||
|
@ -22,7 +23,7 @@ But also using instances of Enum:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
Episode = graphene.Enum('Episode', [('NEWHOPE', 4), ('EMPIRE', 5), ('JEDI', 6)])
|
Episode = Enum("Episode", [("NEWHOPE", 4), ("EMPIRE", 5), ("JEDI", 6)])
|
||||||
|
|
||||||
Value descriptions
|
Value descriptions
|
||||||
------------------
|
------------------
|
||||||
|
@ -32,7 +33,7 @@ needs to have the ``description`` property on it.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Episode(graphene.Enum):
|
class Episode(Enum):
|
||||||
NEWHOPE = 4
|
NEWHOPE = 4
|
||||||
EMPIRE = 5
|
EMPIRE = 5
|
||||||
JEDI = 6
|
JEDI = 6
|
||||||
|
@ -40,9 +41,8 @@ needs to have the ``description`` property on it.
|
||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
if self == Episode.NEWHOPE:
|
if self == Episode.NEWHOPE:
|
||||||
return 'New Hope Episode'
|
return "New Hope Episode"
|
||||||
return 'Other episode'
|
return "Other episode"
|
||||||
|
|
||||||
|
|
||||||
Usage with Python Enums
|
Usage with Python Enums
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -52,16 +52,16 @@ the ``Enum.from_enum`` function.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
graphene.Enum.from_enum(AlreadyExistingPyEnum)
|
Enum.from_enum(AlreadyExistingPyEnum)
|
||||||
|
|
||||||
``Enum.from_enum`` supports a ``description`` and ``deprecation_reason`` lambdas as input so
|
``Enum.from_enum`` supports a ``description`` and ``deprecation_reason`` lambdas as input so
|
||||||
you can add description etc. to your enum without changing the original:
|
you can add description etc. to your enum without changing the original:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
graphene.Enum.from_enum(
|
Enum.from_enum(
|
||||||
AlreadyExistingPyEnum,
|
AlreadyExistingPyEnum,
|
||||||
description=lambda v: return 'foo' if v == AlreadyExistingPyEnum.Foo else 'bar')
|
description=lambda v: return "foo" if v == AlreadyExistingPyEnum.Foo else "bar")
|
||||||
|
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
|
@ -76,19 +76,23 @@ In the Python ``Enum`` implementation you can access a member by initing the Enu
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
class Color(Enum):
|
class Color(Enum):
|
||||||
RED = 1
|
RED = 1
|
||||||
GREEN = 2
|
GREEN = 2
|
||||||
BLUE = 3
|
BLUE = 3
|
||||||
|
|
||||||
assert Color(1) == Color.RED
|
|
||||||
|
|
||||||
|
assert Color(1) == Color.RED
|
||||||
|
|
||||||
However, in Graphene ``Enum`` you need to call get to have the same effect:
|
However, in Graphene ``Enum`` you need to call get to have the same effect:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
from graphene import Enum
|
from graphene import Enum
|
||||||
|
|
||||||
|
|
||||||
class Color(Enum):
|
class Color(Enum):
|
||||||
RED = 1
|
RED = 1
|
||||||
GREEN = 2
|
GREEN = 2
|
||||||
|
|
|
@ -9,12 +9,13 @@ character in the Star Wars trilogy:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ID, Interface, String, List
|
||||||
|
|
||||||
class Character(graphene.Interface):
|
|
||||||
id = graphene.ID(required=True)
|
class Character(Interface):
|
||||||
name = graphene.String(required=True)
|
id = ID(required=True)
|
||||||
friends = graphene.List(lambda: Character)
|
name = String(required=True)
|
||||||
|
friends = List(lambda: Character)
|
||||||
|
|
||||||
|
|
||||||
Any ObjectType that implements ``Character`` will have these exact fields, with
|
Any ObjectType that implements ``Character`` will have these exact fields, with
|
||||||
|
@ -24,19 +25,13 @@ For example, here are some types that might implement ``Character``:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Human(graphene.ObjectType):
|
class Human(ObjectType, interfaces=(Character,)):
|
||||||
class Meta:
|
starships = List(Starship)
|
||||||
interfaces = (Character, )
|
home_planet = String()
|
||||||
|
|
||||||
starships = graphene.List(Starship)
|
|
||||||
home_planet = graphene.String()
|
|
||||||
|
|
||||||
class Droid(graphene.ObjectType):
|
|
||||||
class Meta:
|
|
||||||
interfaces = (Character, )
|
|
||||||
|
|
||||||
primary_function = graphene.String()
|
|
||||||
|
|
||||||
|
class Droid(ObjectType, interfaces=(Character,)):
|
||||||
|
primary_function = String()
|
||||||
|
|
||||||
Both of these types have all of the fields from the ``Character`` interface,
|
Both of these types have all of the fields from the ``Character`` interface,
|
||||||
but also bring in extra fields, ``home_planet``, ``starships`` and
|
but also bring in extra fields, ``home_planet``, ``starships`` and
|
||||||
|
@ -75,20 +70,17 @@ For example, you can define a field ``hero`` that resolves to any
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(ObjectType):
|
||||||
hero = graphene.Field(
|
hero = Field(Character, required=True, episode=Int(required=True))
|
||||||
Character,
|
|
||||||
required=True,
|
|
||||||
episode=graphene.Int(required=True)
|
|
||||||
)
|
|
||||||
|
|
||||||
def resolve_hero(_, info, episode):
|
def resolve_hero(root, info, episode):
|
||||||
# Luke is the hero of Episode V
|
# Luke is the hero of Episode V
|
||||||
if episode == 5:
|
if episode == 5:
|
||||||
return get_human(name='Luke Skywalker')
|
return get_human(name="Luke Skywalker")
|
||||||
return get_droid(name='R2-D2')
|
return get_droid(name="R2-D2")
|
||||||
|
|
||||||
schema = graphene.Schema(query=Query, types=[Human, Droid])
|
|
||||||
|
schema = Schema(query=Query, types=[Human, Droid])
|
||||||
|
|
||||||
This allows you to directly query for fields that exist on the Character interface
|
This allows you to directly query for fields that exist on the Character interface
|
||||||
as well as selecting specific fields on any type that implements the interface
|
as well as selecting specific fields on any type that implements the interface
|
||||||
|
@ -159,12 +151,12 @@ maps a data object to a Graphene type:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Character(graphene.Interface):
|
class Character(Interface):
|
||||||
id = graphene.ID(required=True)
|
id = ID(required=True)
|
||||||
name = graphene.String(required=True)
|
name = String(required=True)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resolve_type(cls, instance, info):
|
def resolve_type(cls, instance, info):
|
||||||
if instance.type == 'DROID':
|
if instance.type == "DROID":
|
||||||
return Droid
|
return Droid
|
||||||
return Human
|
return Human
|
||||||
|
|
|
@ -11,11 +11,11 @@ NonNull
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ObjectType, NonNull, String
|
||||||
|
|
||||||
class Character(graphene.ObjectType):
|
|
||||||
name = graphene.NonNull(graphene.String)
|
|
||||||
|
|
||||||
|
class Character(ObjectType):
|
||||||
|
name = NonNull(String)
|
||||||
|
|
||||||
Here, we're using a ``String`` type and marking it as Non-Null by wrapping
|
Here, we're using a ``String`` type and marking it as Non-Null by wrapping
|
||||||
it using the ``NonNull`` class. This means that our server always expects
|
it using the ``NonNull`` class. This means that our server always expects
|
||||||
|
@ -28,21 +28,22 @@ The previous ``NonNull`` code snippet is also equivalent to:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ObjectType, String
|
||||||
|
|
||||||
class Character(graphene.ObjectType):
|
|
||||||
name = graphene.String(required=True)
|
|
||||||
|
|
||||||
|
class Character(ObjectType):
|
||||||
|
name = String(required=True)
|
||||||
|
|
||||||
List
|
List
|
||||||
----
|
----
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ObjectType, List, String
|
||||||
|
|
||||||
class Character(graphene.ObjectType):
|
|
||||||
appears_in = graphene.List(graphene.String)
|
class Character(ObjectType):
|
||||||
|
appears_in = List(String)
|
||||||
|
|
||||||
Lists work in a similar way: We can use a type modifier to mark a type as a
|
Lists work in a similar way: We can use a type modifier to mark a type as a
|
||||||
``List``, which indicates that this field will return a list of that type.
|
``List``, which indicates that this field will return a list of that type.
|
||||||
|
@ -57,10 +58,11 @@ any nullable items the type needs to be marked as ``NonNull``. For example:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ObjectType, List, NonNull, String
|
||||||
|
|
||||||
class Character(graphene.ObjectType):
|
|
||||||
appears_in = graphene.List(graphene.NonNull(graphene.String))
|
class Character(ObjectType):
|
||||||
|
appears_in = List(NonNull(String))
|
||||||
|
|
||||||
The above results in the type definition:
|
The above results in the type definition:
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,15 @@ This example defines a Mutation:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import Mutation, String, Boolean, Field
|
||||||
|
|
||||||
class CreatePerson(graphene.Mutation):
|
|
||||||
|
class CreatePerson(Mutation):
|
||||||
class Arguments:
|
class Arguments:
|
||||||
name = graphene.String()
|
name = String()
|
||||||
|
|
||||||
ok = graphene.Boolean()
|
ok = Boolean()
|
||||||
person = graphene.Field(lambda: Person)
|
person = Field(lambda: Person)
|
||||||
|
|
||||||
def mutate(self, info, name):
|
def mutate(self, info, name):
|
||||||
person = Person(name=name)
|
person = Person(name=name)
|
||||||
|
@ -38,20 +39,37 @@ So, we can finish our schema like this:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
# ... the Mutation Class
|
from graphene import ObjectType, Mutation, String, Boolean, Field, Int, Schema
|
||||||
|
|
||||||
class Person(graphene.ObjectType):
|
|
||||||
name = graphene.String()
|
|
||||||
age = graphene.Int()
|
|
||||||
|
|
||||||
class MyMutations(graphene.ObjectType):
|
class Person(ObjectType):
|
||||||
|
name = String()
|
||||||
|
age = Int()
|
||||||
|
|
||||||
|
|
||||||
|
class CreatePerson(Mutation):
|
||||||
|
class Arguments:
|
||||||
|
name = String()
|
||||||
|
|
||||||
|
ok = Boolean()
|
||||||
|
person = Field(lambda: Person)
|
||||||
|
|
||||||
|
def mutate(self, info, name):
|
||||||
|
person = Person(name=name)
|
||||||
|
ok = True
|
||||||
|
return CreatePerson(person=person, ok=ok)
|
||||||
|
|
||||||
|
|
||||||
|
class MyMutations(ObjectType):
|
||||||
create_person = CreatePerson.Field()
|
create_person = CreatePerson.Field()
|
||||||
|
|
||||||
# We must define a query for our schema
|
|
||||||
class Query(graphene.ObjectType):
|
|
||||||
person = graphene.Field(Person)
|
|
||||||
|
|
||||||
schema = graphene.Schema(query=Query, mutation=MyMutations)
|
# We must define a query for our schema
|
||||||
|
class Query(ObjectType):
|
||||||
|
person = Field(Person)
|
||||||
|
|
||||||
|
|
||||||
|
schema = Schema(query=Query, mutation=MyMutations)
|
||||||
|
|
||||||
Executing the Mutation
|
Executing the Mutation
|
||||||
----------------------
|
----------------------
|
||||||
|
@ -91,27 +109,25 @@ To use an InputField you define an InputObjectType that specifies the structure
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import InputObjectType, Mutation, String, Field, Int
|
||||||
|
|
||||||
class PersonInput(graphene.InputObjectType):
|
|
||||||
name = graphene.String(required=True)
|
|
||||||
age = graphene.Int(required=True)
|
|
||||||
|
|
||||||
class CreatePerson(graphene.Mutation):
|
class PersonInput(InputObjectType):
|
||||||
|
name = String(required=True)
|
||||||
|
age = Int(required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class CreatePerson(Mutation):
|
||||||
class Arguments:
|
class Arguments:
|
||||||
person_data = PersonInput(required=True)
|
person_data = PersonInput(required=True)
|
||||||
|
|
||||||
person = graphene.Field(Person)
|
person = Field(Person)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def mutate(root, info, person_data=None):
|
def mutate(root, info, person_data=None):
|
||||||
person = Person(
|
person = Person(name=person_data.name, age=person_data.age)
|
||||||
name=person_data.name,
|
|
||||||
age=person_data.age
|
|
||||||
)
|
|
||||||
return CreatePerson(person=person)
|
return CreatePerson(person=person)
|
||||||
|
|
||||||
|
|
||||||
Note that **name** and **age** are part of **person_data** now
|
Note that **name** and **age** are part of **person_data** now
|
||||||
|
|
||||||
Using the above mutation your new query would look like this:
|
Using the above mutation your new query would look like this:
|
||||||
|
@ -132,16 +148,18 @@ as complex of input data as you need
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import InputObjectType, InputField, Float, String
|
||||||
|
|
||||||
|
|
||||||
|
class LatLngInput(InputObjectType):
|
||||||
|
lat = Float()
|
||||||
|
lng = Float()
|
||||||
|
|
||||||
class LatLngInput(graphene.InputObjectType):
|
|
||||||
lat = graphene.Float()
|
|
||||||
lng = graphene.Float()
|
|
||||||
|
|
||||||
# A location has a latlng associated to it
|
# A location has a latlng associated to it
|
||||||
class LocationInput(graphene.InputObjectType):
|
class LocationInput(InputObjectType):
|
||||||
name = graphene.String()
|
name = String()
|
||||||
latlng = graphene.InputField(LatLngInput)
|
latlng = InputField(LatLngInput)
|
||||||
|
|
||||||
Output type example
|
Output type example
|
||||||
-------------------
|
-------------------
|
||||||
|
@ -149,11 +167,12 @@ To return an existing ObjectType instead of a mutation-specific type, set the **
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import Mutation, String
|
||||||
|
|
||||||
class CreatePerson(graphene.Mutation):
|
|
||||||
|
class CreatePerson(Mutation):
|
||||||
class Arguments:
|
class Arguments:
|
||||||
name = graphene.String()
|
name = String()
|
||||||
|
|
||||||
Output = Person
|
Output = Person
|
||||||
|
|
||||||
|
|
|
@ -18,15 +18,16 @@ This example model defines a Person, with a first and a last name:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ObjectType, String
|
||||||
|
|
||||||
class Person(graphene.ObjectType):
|
|
||||||
first_name = graphene.String()
|
class Person(ObjectType):
|
||||||
last_name = graphene.String()
|
first_name = String()
|
||||||
full_name = graphene.String()
|
last_name = String()
|
||||||
|
full_name = String()
|
||||||
|
|
||||||
def resolve_full_name(root, info):
|
def resolve_full_name(root, info):
|
||||||
return '{} {}'.format(root.first_name, root.last_name)
|
return "{} {}".format(root.first_name, root.last_name)
|
||||||
|
|
||||||
**first\_name** and **last\_name** are fields of the ObjectType. Each
|
**first\_name** and **last\_name** are fields of the ObjectType. Each
|
||||||
field is specified as a class attribute, and each attribute maps to a
|
field is specified as a class attribute, and each attribute maps to a
|
||||||
|
@ -62,25 +63,24 @@ passed to the ``ObjectType``.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ObjectType, Field, String
|
||||||
|
|
||||||
class Person(graphene.ObjectType):
|
|
||||||
first_name = graphene.String()
|
|
||||||
last_name = graphene.String()
|
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Person(ObjectType):
|
||||||
me = graphene.Field(Person)
|
first_name = String()
|
||||||
best_friend = graphene.Field(Person)
|
last_name = String()
|
||||||
|
|
||||||
|
|
||||||
|
class Query(ObjectType):
|
||||||
|
me = Field(Person)
|
||||||
|
best_friend = Field(Person)
|
||||||
|
|
||||||
def resolve_me(_, info):
|
def resolve_me(_, info):
|
||||||
# returns an object that represents a Person
|
# returns an object that represents a Person
|
||||||
return get_human(name='Luke Skywalker')
|
return get_human(name="Luke Skywalker")
|
||||||
|
|
||||||
def resolve_best_friend(_, info):
|
def resolve_best_friend(root, info):
|
||||||
return {
|
return {"first_name": "R2", "last_name": "D2"}
|
||||||
"first_name": "R2",
|
|
||||||
"last_name": "D2",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Resolvers with arguments
|
Resolvers with arguments
|
||||||
|
@ -91,10 +91,11 @@ kwargs. For example:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ObjectType, Field, String
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
|
||||||
human_by_name = graphene.Field(Human, name=graphene.String(required=True))
|
class Query(ObjectType):
|
||||||
|
human_by_name = Field(Human, name=String(required=True))
|
||||||
|
|
||||||
def resolve_human_by_name(_, info, name):
|
def resolve_human_by_name(_, info, name):
|
||||||
return get_human(name=name)
|
return get_human(name=name)
|
||||||
|
@ -119,10 +120,11 @@ For example, given this schema:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ObjectType, String
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
|
||||||
hello = graphene.String(required=True, name=graphene.String())
|
class Query(ObjectType):
|
||||||
|
hello = String(required=True, name=String())
|
||||||
|
|
||||||
def resolve_hello(_, info, name):
|
def resolve_hello(_, info, name):
|
||||||
return name if name else 'World'
|
return name if name else 'World'
|
||||||
|
@ -146,8 +148,8 @@ into a dict:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(ObjectType):
|
||||||
hello = graphene.String(required=True, name=graphene.String())
|
hello = String(required=True, name=String())
|
||||||
|
|
||||||
def resolve_hello(_, info, **args):
|
def resolve_hello(_, info, **args):
|
||||||
return args.get('name', 'World')
|
return args.get('name', 'World')
|
||||||
|
@ -156,8 +158,8 @@ Or by setting a default value for the keyword argument:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(ObjectType):
|
||||||
hello = graphene.String(required=True, name=graphene.String())
|
hello = String(required=True, name=String())
|
||||||
|
|
||||||
def resolve_hello(_, info, name='World'):
|
def resolve_hello(_, info, name='World'):
|
||||||
return name
|
return name
|
||||||
|
@ -170,15 +172,15 @@ A field can use a custom resolver from outside the class:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ObjectType, String
|
||||||
|
|
||||||
def resolve_full_name(person, info):
|
def resolve_full_name(person, info):
|
||||||
return '{} {}'.format(person.first_name, person.last_name)
|
return '{} {}'.format(person.first_name, person.last_name)
|
||||||
|
|
||||||
class Person(graphene.ObjectType):
|
class Person(ObjectType):
|
||||||
first_name = graphene.String()
|
first_name = String()
|
||||||
last_name = graphene.String()
|
last_name = String()
|
||||||
full_name = graphene.String(resolver=resolve_full_name)
|
full_name = String(resolver=resolve_full_name)
|
||||||
|
|
||||||
|
|
||||||
Instances as data containers
|
Instances as data containers
|
||||||
|
@ -203,8 +205,7 @@ property on the ``Meta`` class:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class MyGraphQlSong(graphene.ObjectType):
|
class MyGraphQlSong(ObjectType, name="Song"):
|
||||||
class Meta:
|
pass
|
||||||
name = 'Song'
|
|
||||||
|
|
||||||
.. _Interface: /docs/interfaces/
|
.. _Interface: /docs/interfaces/
|
||||||
|
|
|
@ -91,8 +91,9 @@ The following is an example for creating a DateTime scalar:
|
||||||
from graphene.types import Scalar
|
from graphene.types import Scalar
|
||||||
from graphql.language import ast
|
from graphql.language import ast
|
||||||
|
|
||||||
|
|
||||||
class DateTime(Scalar):
|
class DateTime(Scalar):
|
||||||
'''DateTime Scalar Description'''
|
"""DateTime Scalar Description"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def serialize(dt):
|
def serialize(dt):
|
||||||
|
@ -101,8 +102,7 @@ The following is an example for creating a DateTime scalar:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_literal(node):
|
def parse_literal(node):
|
||||||
if isinstance(node, ast.StringValue):
|
if isinstance(node, ast.StringValue):
|
||||||
return datetime.datetime.strptime(
|
return datetime.datetime.strptime(node.value, "%Y-%m-%dT%H:%M:%S.%f")
|
||||||
node.value, "%Y-%m-%dT%H:%M:%S.%f")
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_value(value):
|
def parse_value(value):
|
||||||
|
@ -116,13 +116,15 @@ Scalars mounted in a ``ObjectType``, ``Interface`` or ``Mutation`` act as
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Person(graphene.ObjectType):
|
from graphene import ObjectType, Field, String
|
||||||
name = graphene.String()
|
|
||||||
|
|
||||||
|
class Person(ObjectType):
|
||||||
|
name = String()
|
||||||
|
|
||||||
# Is equivalent to:
|
# Is equivalent to:
|
||||||
class Person(graphene.ObjectType):
|
class Person(ObjectType):
|
||||||
name = graphene.Field(graphene.String)
|
name = Field(String)
|
||||||
|
|
||||||
|
|
||||||
**Note:** when using the ``Field`` constructor directly, pass the type and
|
**Note:** when using the ``Field`` constructor directly, pass the type and
|
||||||
not an instance.
|
not an instance.
|
||||||
|
@ -132,7 +134,7 @@ Types mounted in a ``Field`` act as ``Argument``\ s.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
graphene.Field(graphene.String, to=graphene.String())
|
Field(String, to=String())
|
||||||
|
|
||||||
# Is equivalent to:
|
# Is equivalent to:
|
||||||
graphene.Field(graphene.String, to=graphene.Argument(graphene.String))
|
Field(String, to=Argument(String))
|
||||||
|
|
|
@ -37,7 +37,7 @@ To query a schema, call the ``execute`` method on it.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
my_schema.execute('{ lastName }')
|
my_schema.execute("{ lastName }")
|
||||||
|
|
||||||
|
|
||||||
Auto CamelCase field names
|
Auto CamelCase field names
|
||||||
|
@ -51,9 +51,9 @@ For example with the ObjectType
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
class Person(graphene.ObjectType):
|
class Person(ObjectType):
|
||||||
last_name = graphene.String()
|
last_name = String()
|
||||||
other_name = graphene.String(name='_other_Name')
|
other_name = String(name="_other_Name")
|
||||||
|
|
||||||
the ``last_name`` field name is converted to ``lastName``.
|
the ``last_name`` field name is converted to ``lastName``.
|
||||||
|
|
||||||
|
|
|
@ -17,23 +17,26 @@ This example model defines several ObjectTypes with their own fields.
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
import graphene
|
from graphene import ObjectType, String, Int, Union
|
||||||
|
|
||||||
class Human(graphene.ObjectType):
|
|
||||||
name = graphene.String()
|
|
||||||
born_in = graphene.String()
|
|
||||||
|
|
||||||
class Droid(graphene.ObjectType):
|
class Human(ObjectType):
|
||||||
name = graphene.String()
|
name = String()
|
||||||
primary_function = graphene.String()
|
born_in = String()
|
||||||
|
|
||||||
class Starship(graphene.ObjectType):
|
|
||||||
name = graphene.String()
|
|
||||||
length = graphene.Int()
|
|
||||||
|
|
||||||
class SearchResult(graphene.Union):
|
class Droid(ObjectType):
|
||||||
class Meta:
|
name = String()
|
||||||
types = (Human, Droid, Starship)
|
primary_function = String()
|
||||||
|
|
||||||
|
|
||||||
|
class Starship(ObjectType):
|
||||||
|
name = String()
|
||||||
|
length = Int()
|
||||||
|
|
||||||
|
|
||||||
|
class SearchResult(Union, types=(Human, Droid, Starship)):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
Wherever we return a SearchResult type in our schema, we might get a Human, a Droid, or a Starship.
|
Wherever we return a SearchResult type in our schema, we might get a Human, a Droid, or a Starship.
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
|
from graphene import InputObjectType, Float, ObjectType, String, Field, Schema
|
||||||
|
|
||||||
|
# Naming confusion/conflict with class Mutation and explicit import of graphene.mutation.
|
||||||
import graphene
|
import graphene
|
||||||
|
|
||||||
|
|
||||||
class GeoInput(graphene.InputObjectType):
|
class GeoInput(InputObjectType):
|
||||||
lat = graphene.Float(required=True)
|
lat = Float(required=True)
|
||||||
lng = graphene.Float(required=True)
|
lng = Float(required=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def latlng(self):
|
def latlng(self):
|
||||||
return "({},{})".format(self.lat, self.lng)
|
return "({},{})".format(self.lat, self.lng)
|
||||||
|
|
||||||
|
|
||||||
class Address(graphene.ObjectType):
|
class Address(ObjectType):
|
||||||
latlng = graphene.String()
|
latlng = String()
|
||||||
|
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(ObjectType):
|
||||||
address = graphene.Field(Address, geo=GeoInput(required=True))
|
address = Field(Address, geo=GeoInput(required=True))
|
||||||
|
|
||||||
def resolve_address(self, info, geo):
|
def resolve_address(self, info, geo):
|
||||||
return Address(latlng=geo.latlng)
|
return Address(latlng=geo.latlng)
|
||||||
|
@ -31,11 +34,11 @@ class CreateAddress(graphene.Mutation):
|
||||||
return Address(latlng=geo.latlng)
|
return Address(latlng=geo.latlng)
|
||||||
|
|
||||||
|
|
||||||
class Mutation(graphene.ObjectType):
|
class Mutation(ObjectType):
|
||||||
create_address = CreateAddress.Field()
|
create_address = CreateAddress.Field()
|
||||||
|
|
||||||
|
|
||||||
schema = graphene.Schema(query=Query, mutation=Mutation)
|
schema = Schema(query=Query, mutation=Mutation)
|
||||||
query = """
|
query = """
|
||||||
query something{
|
query something{
|
||||||
address(geo: {lat:32.2, lng:12}) {
|
address(geo: {lat:32.2, lng:12}) {
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import graphene
|
from graphene import ObjectType, ID, String, Field, Schema
|
||||||
|
|
||||||
|
|
||||||
class User(graphene.ObjectType):
|
class User(ObjectType):
|
||||||
id = graphene.ID()
|
id = ID()
|
||||||
name = graphene.String()
|
name = String()
|
||||||
|
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(ObjectType):
|
||||||
me = graphene.Field(User)
|
me = Field(User)
|
||||||
|
|
||||||
def resolve_me(self, info):
|
def resolve_me(self, info):
|
||||||
return info.context["user"]
|
return info.context["user"]
|
||||||
|
|
||||||
|
|
||||||
schema = graphene.Schema(query=Query)
|
schema = Schema(query=Query)
|
||||||
query = """
|
query = """
|
||||||
query something{
|
query something{
|
||||||
me {
|
me {
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
import graphene
|
from graphene import ObjectType, ID, String, Int, Field, Schema
|
||||||
|
|
||||||
|
|
||||||
class Patron(graphene.ObjectType):
|
class Patron(ObjectType):
|
||||||
id = graphene.ID()
|
id = ID()
|
||||||
name = graphene.String()
|
name = String()
|
||||||
age = graphene.Int()
|
age = Int()
|
||||||
|
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(ObjectType):
|
||||||
|
|
||||||
patron = graphene.Field(Patron)
|
patron = Field(Patron)
|
||||||
|
|
||||||
def resolve_patron(self, info):
|
def resolve_patron(self, info):
|
||||||
return Patron(id=1, name="Syrus", age=27)
|
return Patron(id=1, name="Syrus", age=27)
|
||||||
|
|
||||||
|
|
||||||
schema = graphene.Schema(query=Query)
|
schema = Schema(query=Query)
|
||||||
query = """
|
query = """
|
||||||
query something{
|
query something{
|
||||||
patron {
|
patron {
|
||||||
|
|
|
@ -1,43 +1,37 @@
|
||||||
import graphene
|
from graphene import Enum, Interface, ID, List, ObjectType, String, Field, Schema
|
||||||
|
|
||||||
from .data import get_character, get_droid, get_hero, get_human
|
from .data import get_character, get_droid, get_hero, get_human
|
||||||
|
|
||||||
|
|
||||||
class Episode(graphene.Enum):
|
class Episode(Enum):
|
||||||
NEWHOPE = 4
|
NEWHOPE = 4
|
||||||
EMPIRE = 5
|
EMPIRE = 5
|
||||||
JEDI = 6
|
JEDI = 6
|
||||||
|
|
||||||
|
|
||||||
class Character(graphene.Interface):
|
class Character(Interface):
|
||||||
id = graphene.ID()
|
id = ID()
|
||||||
name = graphene.String()
|
name = String()
|
||||||
friends = graphene.List(lambda: Character)
|
friends = List(lambda: Character)
|
||||||
appears_in = graphene.List(Episode)
|
appears_in = List(Episode)
|
||||||
|
|
||||||
def resolve_friends(self, info):
|
def resolve_friends(self, info):
|
||||||
# The character friends is a list of strings
|
# The character friends is a list of strings
|
||||||
return [get_character(f) for f in self.friends]
|
return [get_character(f) for f in self.friends]
|
||||||
|
|
||||||
|
|
||||||
class Human(graphene.ObjectType):
|
class Human(ObjectType, interfaces=(Character,)):
|
||||||
class Meta:
|
home_planet = String()
|
||||||
interfaces = (Character,)
|
|
||||||
|
|
||||||
home_planet = graphene.String()
|
|
||||||
|
|
||||||
|
|
||||||
class Droid(graphene.ObjectType):
|
class Droid(ObjectType, interfaces=(Character,)):
|
||||||
class Meta:
|
primary_function = String()
|
||||||
interfaces = (Character,)
|
|
||||||
|
|
||||||
primary_function = graphene.String()
|
|
||||||
|
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(ObjectType):
|
||||||
hero = graphene.Field(Character, episode=Episode())
|
hero = Field(Character, episode=Episode())
|
||||||
human = graphene.Field(Human, id=graphene.String())
|
human = Field(Human, id=String())
|
||||||
droid = graphene.Field(Droid, id=graphene.String())
|
droid = Field(Droid, id=String())
|
||||||
|
|
||||||
def resolve_hero(self, info, episode=None):
|
def resolve_hero(self, info, episode=None):
|
||||||
return get_hero(episode)
|
return get_hero(episode)
|
||||||
|
@ -49,4 +43,4 @@ class Query(graphene.ObjectType):
|
||||||
return get_droid(id)
|
return get_droid(id)
|
||||||
|
|
||||||
|
|
||||||
schema = graphene.Schema(query=Query)
|
schema = Schema(query=Query)
|
||||||
|
|
|
@ -1,34 +1,27 @@
|
||||||
import graphene
|
from graphene import ObjectType, Schema, Field, String
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
|
|
||||||
from .data import create_ship, get_empire, get_faction, get_rebels, get_ship
|
from .data import create_ship, get_empire, get_faction, get_rebels, get_ship
|
||||||
|
|
||||||
|
|
||||||
class Ship(graphene.ObjectType):
|
class Ship(ObjectType, interfaces=(relay.Node,)):
|
||||||
"""A ship in the Star Wars saga"""
|
"""A ship in the Star Wars saga."""
|
||||||
|
|
||||||
class Meta:
|
name = String(description="The name of the ship.")
|
||||||
interfaces = (relay.Node,)
|
|
||||||
|
|
||||||
name = graphene.String(description="The name of the ship.")
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_node(cls, info, id):
|
def get_node(cls, info, id):
|
||||||
return get_ship(id)
|
return get_ship(id)
|
||||||
|
|
||||||
|
|
||||||
class ShipConnection(relay.Connection):
|
class ShipConnection(relay.Connection, node=Ship):
|
||||||
class Meta:
|
pass
|
||||||
node = Ship
|
|
||||||
|
|
||||||
|
|
||||||
class Faction(graphene.ObjectType):
|
class Faction(ObjectType, interfaces=(relay.Node,)):
|
||||||
"""A faction in the Star Wars saga"""
|
"""A faction in the Star Wars saga."""
|
||||||
|
|
||||||
class Meta:
|
name = String(description="The name of the faction.")
|
||||||
interfaces = (relay.Node,)
|
|
||||||
|
|
||||||
name = graphene.String(description="The name of the faction.")
|
|
||||||
ships = relay.ConnectionField(
|
ships = relay.ConnectionField(
|
||||||
ShipConnection, description="The ships used by the faction."
|
ShipConnection, description="The ships used by the faction."
|
||||||
)
|
)
|
||||||
|
@ -44,11 +37,11 @@ class Faction(graphene.ObjectType):
|
||||||
|
|
||||||
class IntroduceShip(relay.ClientIDMutation):
|
class IntroduceShip(relay.ClientIDMutation):
|
||||||
class Input:
|
class Input:
|
||||||
ship_name = graphene.String(required=True)
|
ship_name = String(required=True)
|
||||||
faction_id = graphene.String(required=True)
|
faction_id = String(required=True)
|
||||||
|
|
||||||
ship = graphene.Field(Ship)
|
ship = Field(Ship)
|
||||||
faction = graphene.Field(Faction)
|
faction = Field(Faction)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(
|
def mutate_and_get_payload(
|
||||||
|
@ -59,9 +52,9 @@ class IntroduceShip(relay.ClientIDMutation):
|
||||||
return IntroduceShip(ship=ship, faction=faction)
|
return IntroduceShip(ship=ship, faction=faction)
|
||||||
|
|
||||||
|
|
||||||
class Query(graphene.ObjectType):
|
class Query(ObjectType):
|
||||||
rebels = graphene.Field(Faction)
|
rebels = Field(Faction)
|
||||||
empire = graphene.Field(Faction)
|
empire = Field(Faction)
|
||||||
node = relay.Node.Field()
|
node = relay.Node.Field()
|
||||||
|
|
||||||
def resolve_rebels(self, info):
|
def resolve_rebels(self, info):
|
||||||
|
@ -71,8 +64,8 @@ class Query(graphene.ObjectType):
|
||||||
return get_empire()
|
return get_empire()
|
||||||
|
|
||||||
|
|
||||||
class Mutation(graphene.ObjectType):
|
class Mutation(ObjectType):
|
||||||
introduce_ship = IntroduceShip.Field()
|
introduce_ship = IntroduceShip.Field()
|
||||||
|
|
||||||
|
|
||||||
schema = graphene.Schema(query=Query, mutation=Mutation)
|
schema = Schema(query=Query, mutation=Mutation)
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Structure(UnmountedType):
|
||||||
cls_name = type(self).__name__
|
cls_name = type(self).__name__
|
||||||
of_type_name = type(of_type).__name__
|
of_type_name = type(of_type).__name__
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"{} could not have a mounted {}() as inner type. Try with {}({}).".format(
|
"{} cannot have a mounted {}() as inner type. Try {}({}).".format(
|
||||||
cls_name, of_type_name, cls_name, of_type_name
|
cls_name, of_type_name, cls_name, of_type_name
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -19,7 +19,7 @@ def test_list_with_unmounted_type():
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
str(exc_info.value)
|
str(exc_info.value)
|
||||||
== "List could not have a mounted String() as inner type. Try with List(String)."
|
== "List cannot have a mounted String() as inner type. Try List(String)."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ def test_nonnull_with_unmounted_type():
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
str(exc_info.value)
|
str(exc_info.value)
|
||||||
== "NonNull could not have a mounted String() as inner type. Try with NonNull(String)."
|
== "NonNull cannot have a mounted String() as inner type. Try NonNull(String)."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user