mirror of
https://github.com/graphql-python/graphene.git
synced 2025-09-21 11:22: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
|
||||
|
||||
class User(graphene.ObjectType):
|
||||
name = graphene.String()
|
||||
best_friend = graphene.Field(lambda: User)
|
||||
friends = graphene.List(lambda: User)
|
||||
class User(ObjectType):
|
||||
name = String()
|
||||
best_friend = Field(lambda: User)
|
||||
friends = List(lambda: User)
|
||||
|
||||
def resolve_best_friend(self, info):
|
||||
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
|
||||
|
||||
schema = graphene.Schema(...)
|
||||
result = schema.execute('{ name }')
|
||||
schema = Schema(...)
|
||||
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.
|
||||
|
||||
|
@ -21,14 +21,15 @@ You can pass context to a query via ``context``.
|
|||
|
||||
.. code:: python
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
name = graphene.String()
|
||||
class Query(ObjectType):
|
||||
name = String()
|
||||
|
||||
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
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
user = graphene.Field(User, id=graphene.ID(required=True))
|
||||
class Query(ObjectType):
|
||||
user = Field(User, id=ID(required=True))
|
||||
|
||||
def resolve_user(root, info, id):
|
||||
return get_user_by_id(id)
|
||||
|
||||
schema = graphene.Schema(Query)
|
||||
|
||||
schema = Schema(Query)
|
||||
result = schema.execute(
|
||||
'''
|
||||
"""
|
||||
query getUser($id: ID) {
|
||||
user(id: $id) {
|
||||
id
|
||||
|
@ -56,6 +58,6 @@ You can pass variables to a query via ``variables``.
|
|||
lastName
|
||||
}
|
||||
}
|
||||
''',
|
||||
variables={'id': 12},
|
||||
""",
|
||||
variables={"id": 12},
|
||||
)
|
||||
|
|
|
@ -12,7 +12,7 @@ Let’s build a basic GraphQL schema from scratch.
|
|||
Requirements
|
||||
------------
|
||||
|
||||
- Python (2.7, 3.4, 3.5, 3.6, pypy)
|
||||
- Python (3.6+, pypy)
|
||||
- Graphene (2.0)
|
||||
|
||||
Project setup
|
||||
|
@ -35,15 +35,17 @@ one field: ``hello`` and an input name. And when we query it, it should return `
|
|||
|
||||
.. 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):
|
||||
return 'Hello ' + argument
|
||||
return f"Hello {argument}"
|
||||
|
||||
schema = graphene.Schema(query=Query)
|
||||
|
||||
schema = Schema(query=Query)
|
||||
|
||||
Querying
|
||||
--------
|
||||
|
@ -52,11 +54,11 @@ Then we can start querying our schema:
|
|||
|
||||
.. code:: python
|
||||
|
||||
result = schema.execute('{ hello }')
|
||||
print(result.data['hello']) # "Hello stranger"
|
||||
result = schema.execute("{ hello }")
|
||||
print(result.data["hello"]) # "Hello stranger"
|
||||
|
||||
# or passing the argument in the query
|
||||
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!
|
||||
|
|
|
@ -16,12 +16,9 @@ and ``other`` an extra field in the Connection Edge.
|
|||
|
||||
.. code:: python
|
||||
|
||||
class ShipConnection(Connection):
|
||||
class ShipConnection(Connection, node=Ship):
|
||||
extra = String()
|
||||
|
||||
class Meta:
|
||||
node = Ship
|
||||
|
||||
class Edge:
|
||||
other = String()
|
||||
|
||||
|
@ -37,8 +34,8 @@ that implements ``Node`` will have a default Connection.
|
|||
|
||||
.. code:: python
|
||||
|
||||
class Faction(graphene.ObjectType):
|
||||
name = graphene.String()
|
||||
class Faction(ObjectType):
|
||||
name = String()
|
||||
ships = relay.ConnectionField(ShipConnection)
|
||||
|
||||
def resolve_ships(self, info):
|
||||
|
|
|
@ -12,13 +12,12 @@ subclass of ``relay.ClientIDMutation``.
|
|||
.. code:: python
|
||||
|
||||
class IntroduceShip(relay.ClientIDMutation):
|
||||
|
||||
class Input:
|
||||
ship_name = graphene.String(required=True)
|
||||
faction_id = graphene.String(required=True)
|
||||
ship_name = String(required=True)
|
||||
faction_id = String(required=True)
|
||||
|
||||
ship = graphene.Field(Ship)
|
||||
faction = graphene.Field(Faction)
|
||||
ship = Field(Ship)
|
||||
faction = Field(Faction)
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **input):
|
||||
|
@ -28,8 +27,6 @@ subclass of ``relay.ClientIDMutation``.
|
|||
faction = get_faction(faction_id)
|
||||
return IntroduceShip(ship=ship, faction=faction)
|
||||
|
||||
|
||||
|
||||
Accepting Files
|
||||
---------------
|
||||
|
||||
|
@ -37,13 +34,13 @@ Mutations can also accept files, that's how it will work with different integrat
|
|||
|
||||
.. code:: python
|
||||
|
||||
class UploadFile(graphene.ClientIDMutation):
|
||||
class UploadFile(ClientIDMutation):
|
||||
class Input:
|
||||
pass
|
||||
# nothing needed for uploading file
|
||||
|
||||
# your return fields
|
||||
success = graphene.String()
|
||||
success = String()
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **input):
|
||||
|
|
|
@ -14,12 +14,10 @@ Example usage (taken from the `Starwars Relay example`_):
|
|||
|
||||
.. code:: python
|
||||
|
||||
class Ship(graphene.ObjectType):
|
||||
'''A ship in the Star Wars saga'''
|
||||
class Meta:
|
||||
interfaces = (relay.Node, )
|
||||
class Ship(ObjectType, interfaces=(relay.Node,)):
|
||||
"""A ship in the Star Wars saga"""
|
||||
|
||||
name = graphene.String(description='The name of the ship.')
|
||||
name = String(description="The name of the ship.")
|
||||
|
||||
@classmethod
|
||||
def get_node(cls, info, id):
|
||||
|
@ -45,26 +43,22 @@ Example of a custom node:
|
|||
|
||||
.. code:: python
|
||||
|
||||
class CustomNode(Node):
|
||||
|
||||
class Meta:
|
||||
name = 'Node'
|
||||
|
||||
class CustomNode(Node, name="Node"):
|
||||
@staticmethod
|
||||
def to_global_id(type, id):
|
||||
return '{}:{}'.format(type, id)
|
||||
return "{}:{}".format(type, id)
|
||||
|
||||
@staticmethod
|
||||
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:
|
||||
# We assure that the node type that we want to retrieve
|
||||
# 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)
|
||||
elif type == 'Photo':
|
||||
elif type == "Photo":
|
||||
return get_photo(id)
|
||||
|
||||
|
||||
|
@ -94,7 +88,7 @@ Example usage:
|
|||
|
||||
.. code:: python
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
class Query(ObjectType):
|
||||
# Should be CustomNode.Field() if we want to use our custom Node
|
||||
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
|
||||
|
||||
|
||||
def test_hey():
|
||||
client = Client(my_schema)
|
||||
executed = client.execute('''{ hey }''')
|
||||
assert executed == {
|
||||
'data': {
|
||||
'hey': 'hello!'
|
||||
}
|
||||
}
|
||||
executed = client.execute("""{ hey }""")
|
||||
assert executed == {"data": {"hey": "hello!"}}
|
||||
|
||||
|
||||
Execute parameters
|
||||
|
@ -61,14 +58,11 @@ You can also add extra keyword arguments to the ``execute`` method, such as
|
|||
|
||||
from graphene.test import Client
|
||||
|
||||
|
||||
def test_hey():
|
||||
client = Client(my_schema)
|
||||
executed = client.execute('''{ hey }''', context={'user': 'Peter'})
|
||||
assert executed == {
|
||||
'data': {
|
||||
'hey': 'hello Peter!'
|
||||
}
|
||||
}
|
||||
executed = client.execute("""{ hey }""", context={"user": "Peter"})
|
||||
assert executed == {"data": {"hey": "hello Peter!"}}
|
||||
|
||||
|
||||
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
|
||||
# the first time the test is executed, with the response
|
||||
# of the execution.
|
||||
snapshot.assert_match(client.execute('''{ hey }'''))
|
||||
snapshot.assert_match(client.execute("""{ hey }"""))
|
||||
|
||||
|
||||
If we are using ``unittest``:
|
||||
|
@ -104,8 +98,9 @@ If we are using ``unittest``:
|
|||
|
||||
from snapshottest import TestCase
|
||||
|
||||
|
||||
class APITestCase(TestCase):
|
||||
def test_api_me(self):
|
||||
"""Testing the API for /me"""
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
class UserInput(graphene.InputObjectType, UserFields):
|
||||
pass
|
||||
|
||||
class UserInput(InputObjectType, UserFields):
|
||||
pass
|
||||
|
||||
.. code::
|
||||
|
||||
|
|
|
@ -11,9 +11,10 @@ You can create an ``Enum`` using classes:
|
|||
|
||||
.. code:: python
|
||||
|
||||
import graphene
|
||||
from graphene import Enum
|
||||
|
||||
class Episode(graphene.Enum):
|
||||
|
||||
class Episode(Enum):
|
||||
NEWHOPE = 4
|
||||
EMPIRE = 5
|
||||
JEDI = 6
|
||||
|
@ -22,7 +23,7 @@ But also using instances of Enum:
|
|||
|
||||
.. code:: python
|
||||
|
||||
Episode = graphene.Enum('Episode', [('NEWHOPE', 4), ('EMPIRE', 5), ('JEDI', 6)])
|
||||
Episode = Enum("Episode", [("NEWHOPE", 4), ("EMPIRE", 5), ("JEDI", 6)])
|
||||
|
||||
Value descriptions
|
||||
------------------
|
||||
|
@ -32,7 +33,7 @@ needs to have the ``description`` property on it.
|
|||
|
||||
.. code:: python
|
||||
|
||||
class Episode(graphene.Enum):
|
||||
class Episode(Enum):
|
||||
NEWHOPE = 4
|
||||
EMPIRE = 5
|
||||
JEDI = 6
|
||||
|
@ -40,9 +41,8 @@ needs to have the ``description`` property on it.
|
|||
@property
|
||||
def description(self):
|
||||
if self == Episode.NEWHOPE:
|
||||
return 'New Hope Episode'
|
||||
return 'Other episode'
|
||||
|
||||
return "New Hope Episode"
|
||||
return "Other episode"
|
||||
|
||||
Usage with Python Enums
|
||||
-----------------------
|
||||
|
@ -52,16 +52,16 @@ the ``Enum.from_enum`` function.
|
|||
|
||||
.. code:: python
|
||||
|
||||
graphene.Enum.from_enum(AlreadyExistingPyEnum)
|
||||
Enum.from_enum(AlreadyExistingPyEnum)
|
||||
|
||||
``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:
|
||||
|
||||
.. code:: python
|
||||
|
||||
graphene.Enum.from_enum(
|
||||
Enum.from_enum(
|
||||
AlreadyExistingPyEnum,
|
||||
description=lambda v: return 'foo' if v == AlreadyExistingPyEnum.Foo else 'bar')
|
||||
description=lambda v: return "foo" if v == AlreadyExistingPyEnum.Foo else "bar")
|
||||
|
||||
|
||||
Notes
|
||||
|
@ -76,19 +76,23 @@ In the Python ``Enum`` implementation you can access a member by initing the Enu
|
|||
.. code:: python
|
||||
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class Color(Enum):
|
||||
RED = 1
|
||||
GREEN = 2
|
||||
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:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from graphene import Enum
|
||||
|
||||
|
||||
class Color(Enum):
|
||||
RED = 1
|
||||
GREEN = 2
|
||||
|
|
|
@ -9,12 +9,13 @@ character in the Star Wars trilogy:
|
|||
|
||||
.. code:: python
|
||||
|
||||
import graphene
|
||||
from graphene import ID, Interface, String, List
|
||||
|
||||
class Character(graphene.Interface):
|
||||
id = graphene.ID(required=True)
|
||||
name = graphene.String(required=True)
|
||||
friends = graphene.List(lambda: Character)
|
||||
|
||||
class Character(Interface):
|
||||
id = ID(required=True)
|
||||
name = String(required=True)
|
||||
friends = List(lambda: Character)
|
||||
|
||||
|
||||
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
|
||||
|
||||
class Human(graphene.ObjectType):
|
||||
class Meta:
|
||||
interfaces = (Character, )
|
||||
class Human(ObjectType, interfaces=(Character,)):
|
||||
starships = List(Starship)
|
||||
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,
|
||||
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
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
hero = graphene.Field(
|
||||
Character,
|
||||
required=True,
|
||||
episode=graphene.Int(required=True)
|
||||
)
|
||||
class Query(ObjectType):
|
||||
hero = Field(Character, required=True, episode=Int(required=True))
|
||||
|
||||
def resolve_hero(_, info, episode):
|
||||
def resolve_hero(root, info, episode):
|
||||
# Luke is the hero of Episode V
|
||||
if episode == 5:
|
||||
return get_human(name='Luke Skywalker')
|
||||
return get_droid(name='R2-D2')
|
||||
return get_human(name="Luke Skywalker")
|
||||
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
|
||||
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
|
||||
|
||||
class Character(graphene.Interface):
|
||||
id = graphene.ID(required=True)
|
||||
name = graphene.String(required=True)
|
||||
class Character(Interface):
|
||||
id = ID(required=True)
|
||||
name = String(required=True)
|
||||
|
||||
@classmethod
|
||||
def resolve_type(cls, instance, info):
|
||||
if instance.type == 'DROID':
|
||||
if instance.type == "DROID":
|
||||
return Droid
|
||||
return Human
|
||||
|
|
|
@ -11,11 +11,11 @@ NonNull
|
|||
|
||||
.. 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
|
||||
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
|
||||
|
||||
import graphene
|
||||
from graphene import ObjectType, String
|
||||
|
||||
class Character(graphene.ObjectType):
|
||||
name = graphene.String(required=True)
|
||||
|
||||
class Character(ObjectType):
|
||||
name = String(required=True)
|
||||
|
||||
List
|
||||
----
|
||||
|
||||
.. 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
|
||||
``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
|
||||
|
||||
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:
|
||||
|
||||
|
|
|
@ -10,14 +10,15 @@ This example defines a Mutation:
|
|||
|
||||
.. code:: python
|
||||
|
||||
import graphene
|
||||
from graphene import Mutation, String, Boolean, Field
|
||||
|
||||
class CreatePerson(graphene.Mutation):
|
||||
|
||||
class CreatePerson(Mutation):
|
||||
class Arguments:
|
||||
name = graphene.String()
|
||||
name = String()
|
||||
|
||||
ok = graphene.Boolean()
|
||||
person = graphene.Field(lambda: Person)
|
||||
ok = Boolean()
|
||||
person = Field(lambda: Person)
|
||||
|
||||
def mutate(self, info, name):
|
||||
person = Person(name=name)
|
||||
|
@ -38,20 +39,37 @@ So, we can finish our schema like this:
|
|||
|
||||
.. 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()
|
||||
|
||||
# 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
|
||||
----------------------
|
||||
|
@ -91,27 +109,25 @@ To use an InputField you define an InputObjectType that specifies the structure
|
|||
|
||||
.. 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:
|
||||
person_data = PersonInput(required=True)
|
||||
|
||||
person = graphene.Field(Person)
|
||||
person = Field(Person)
|
||||
|
||||
@staticmethod
|
||||
def mutate(root, info, person_data=None):
|
||||
person = Person(
|
||||
name=person_data.name,
|
||||
age=person_data.age
|
||||
)
|
||||
person = Person(name=person_data.name, age=person_data.age)
|
||||
return CreatePerson(person=person)
|
||||
|
||||
|
||||
Note that **name** and **age** are part of **person_data** now
|
||||
|
||||
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
|
||||
|
||||
import graphene
|
||||
from graphene import InputObjectType, InputField, Float, String
|
||||
|
||||
class LatLngInput(graphene.InputObjectType):
|
||||
lat = graphene.Float()
|
||||
lng = graphene.Float()
|
||||
|
||||
#A location has a latlng associated to it
|
||||
class LocationInput(graphene.InputObjectType):
|
||||
name = graphene.String()
|
||||
latlng = graphene.InputField(LatLngInput)
|
||||
class LatLngInput(InputObjectType):
|
||||
lat = Float()
|
||||
lng = Float()
|
||||
|
||||
|
||||
# A location has a latlng associated to it
|
||||
class LocationInput(InputObjectType):
|
||||
name = String()
|
||||
latlng = InputField(LatLngInput)
|
||||
|
||||
Output type example
|
||||
-------------------
|
||||
|
@ -149,11 +167,12 @@ To return an existing ObjectType instead of a mutation-specific type, set the **
|
|||
|
||||
.. code:: python
|
||||
|
||||
import graphene
|
||||
from graphene import Mutation, String
|
||||
|
||||
class CreatePerson(graphene.Mutation):
|
||||
|
||||
class CreatePerson(Mutation):
|
||||
class Arguments:
|
||||
name = graphene.String()
|
||||
name = String()
|
||||
|
||||
Output = Person
|
||||
|
||||
|
|
|
@ -18,15 +18,16 @@ This example model defines a Person, with a first and a last name:
|
|||
|
||||
.. code:: python
|
||||
|
||||
import graphene
|
||||
from graphene import ObjectType, String
|
||||
|
||||
class Person(graphene.ObjectType):
|
||||
first_name = graphene.String()
|
||||
last_name = graphene.String()
|
||||
full_name = graphene.String()
|
||||
|
||||
class Person(ObjectType):
|
||||
first_name = String()
|
||||
last_name = String()
|
||||
full_name = String()
|
||||
|
||||
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
|
||||
field is specified as a class attribute, and each attribute maps to a
|
||||
|
@ -62,25 +63,24 @@ passed to the ``ObjectType``.
|
|||
|
||||
.. 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):
|
||||
me = graphene.Field(Person)
|
||||
best_friend = graphene.Field(Person)
|
||||
class Person(ObjectType):
|
||||
first_name = String()
|
||||
last_name = String()
|
||||
|
||||
|
||||
class Query(ObjectType):
|
||||
me = Field(Person)
|
||||
best_friend = Field(Person)
|
||||
|
||||
def resolve_me(_, info):
|
||||
# returns an object that represents a Person
|
||||
return get_human(name='Luke Skywalker')
|
||||
return get_human(name="Luke Skywalker")
|
||||
|
||||
def resolve_best_friend(_, info):
|
||||
return {
|
||||
"first_name": "R2",
|
||||
"last_name": "D2",
|
||||
}
|
||||
def resolve_best_friend(root, info):
|
||||
return {"first_name": "R2", "last_name": "D2"}
|
||||
|
||||
|
||||
Resolvers with arguments
|
||||
|
@ -91,10 +91,11 @@ kwargs. For example:
|
|||
|
||||
.. 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):
|
||||
return get_human(name=name)
|
||||
|
@ -119,10 +120,11 @@ For example, given this schema:
|
|||
|
||||
.. 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):
|
||||
return name if name else 'World'
|
||||
|
@ -146,8 +148,8 @@ into a dict:
|
|||
|
||||
.. code:: python
|
||||
|
||||
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, **args):
|
||||
return args.get('name', 'World')
|
||||
|
@ -156,8 +158,8 @@ Or by setting a default value for the keyword argument:
|
|||
|
||||
.. code:: python
|
||||
|
||||
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='World'):
|
||||
return name
|
||||
|
@ -170,15 +172,15 @@ A field can use a custom resolver from outside the class:
|
|||
|
||||
.. code:: python
|
||||
|
||||
import graphene
|
||||
from graphene import ObjectType, String
|
||||
|
||||
def resolve_full_name(person, info):
|
||||
return '{} {}'.format(person.first_name, person.last_name)
|
||||
|
||||
class Person(graphene.ObjectType):
|
||||
first_name = graphene.String()
|
||||
last_name = graphene.String()
|
||||
full_name = graphene.String(resolver=resolve_full_name)
|
||||
class Person(ObjectType):
|
||||
first_name = String()
|
||||
last_name = String()
|
||||
full_name = String(resolver=resolve_full_name)
|
||||
|
||||
|
||||
Instances as data containers
|
||||
|
@ -203,8 +205,7 @@ property on the ``Meta`` class:
|
|||
|
||||
.. code:: python
|
||||
|
||||
class MyGraphQlSong(graphene.ObjectType):
|
||||
class Meta:
|
||||
name = 'Song'
|
||||
class MyGraphQlSong(ObjectType, name="Song"):
|
||||
pass
|
||||
|
||||
.. _Interface: /docs/interfaces/
|
||||
|
|
|
@ -91,8 +91,9 @@ The following is an example for creating a DateTime scalar:
|
|||
from graphene.types import Scalar
|
||||
from graphql.language import ast
|
||||
|
||||
|
||||
class DateTime(Scalar):
|
||||
'''DateTime Scalar Description'''
|
||||
"""DateTime Scalar Description"""
|
||||
|
||||
@staticmethod
|
||||
def serialize(dt):
|
||||
|
@ -101,8 +102,7 @@ The following is an example for creating a DateTime scalar:
|
|||
@staticmethod
|
||||
def parse_literal(node):
|
||||
if isinstance(node, ast.StringValue):
|
||||
return datetime.datetime.strptime(
|
||||
node.value, "%Y-%m-%dT%H:%M:%S.%f")
|
||||
return datetime.datetime.strptime(node.value, "%Y-%m-%dT%H:%M:%S.%f")
|
||||
|
||||
@staticmethod
|
||||
def parse_value(value):
|
||||
|
@ -116,13 +116,15 @@ Scalars mounted in a ``ObjectType``, ``Interface`` or ``Mutation`` act as
|
|||
|
||||
.. code:: python
|
||||
|
||||
class Person(graphene.ObjectType):
|
||||
name = graphene.String()
|
||||
from graphene import ObjectType, Field, String
|
||||
|
||||
|
||||
class Person(ObjectType):
|
||||
name = String()
|
||||
|
||||
# Is equivalent to:
|
||||
class Person(graphene.ObjectType):
|
||||
name = graphene.Field(graphene.String)
|
||||
|
||||
class Person(ObjectType):
|
||||
name = Field(String)
|
||||
|
||||
**Note:** when using the ``Field`` constructor directly, pass the type and
|
||||
not an instance.
|
||||
|
@ -132,7 +134,7 @@ Types mounted in a ``Field`` act as ``Argument``\ s.
|
|||
|
||||
.. code:: python
|
||||
|
||||
graphene.Field(graphene.String, to=graphene.String())
|
||||
Field(String, to=String())
|
||||
|
||||
# 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
|
||||
|
||||
my_schema.execute('{ lastName }')
|
||||
my_schema.execute("{ lastName }")
|
||||
|
||||
|
||||
Auto CamelCase field names
|
||||
|
@ -51,9 +51,9 @@ For example with the ObjectType
|
|||
|
||||
.. code:: python
|
||||
|
||||
class Person(graphene.ObjectType):
|
||||
last_name = graphene.String()
|
||||
other_name = graphene.String(name='_other_Name')
|
||||
class Person(ObjectType):
|
||||
last_name = String()
|
||||
other_name = String(name="_other_Name")
|
||||
|
||||
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
|
||||
|
||||
import graphene
|
||||
from graphene import ObjectType, String, Int, Union
|
||||
|
||||
class Human(graphene.ObjectType):
|
||||
name = graphene.String()
|
||||
born_in = graphene.String()
|
||||
|
||||
class Droid(graphene.ObjectType):
|
||||
name = graphene.String()
|
||||
primary_function = graphene.String()
|
||||
class Human(ObjectType):
|
||||
name = String()
|
||||
born_in = String()
|
||||
|
||||
class Starship(graphene.ObjectType):
|
||||
name = graphene.String()
|
||||
length = graphene.Int()
|
||||
|
||||
class SearchResult(graphene.Union):
|
||||
class Meta:
|
||||
types = (Human, Droid, Starship)
|
||||
class Droid(ObjectType):
|
||||
name = String()
|
||||
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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
class GeoInput(graphene.InputObjectType):
|
||||
lat = graphene.Float(required=True)
|
||||
lng = graphene.Float(required=True)
|
||||
class GeoInput(InputObjectType):
|
||||
lat = Float(required=True)
|
||||
lng = Float(required=True)
|
||||
|
||||
@property
|
||||
def latlng(self):
|
||||
return "({},{})".format(self.lat, self.lng)
|
||||
|
||||
|
||||
class Address(graphene.ObjectType):
|
||||
latlng = graphene.String()
|
||||
class Address(ObjectType):
|
||||
latlng = String()
|
||||
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
address = graphene.Field(Address, geo=GeoInput(required=True))
|
||||
class Query(ObjectType):
|
||||
address = Field(Address, geo=GeoInput(required=True))
|
||||
|
||||
def resolve_address(self, info, geo):
|
||||
return Address(latlng=geo.latlng)
|
||||
|
@ -31,11 +34,11 @@ class CreateAddress(graphene.Mutation):
|
|||
return Address(latlng=geo.latlng)
|
||||
|
||||
|
||||
class Mutation(graphene.ObjectType):
|
||||
class Mutation(ObjectType):
|
||||
create_address = CreateAddress.Field()
|
||||
|
||||
|
||||
schema = graphene.Schema(query=Query, mutation=Mutation)
|
||||
schema = Schema(query=Query, mutation=Mutation)
|
||||
query = """
|
||||
query something{
|
||||
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):
|
||||
id = graphene.ID()
|
||||
name = graphene.String()
|
||||
class User(ObjectType):
|
||||
id = ID()
|
||||
name = String()
|
||||
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
me = graphene.Field(User)
|
||||
class Query(ObjectType):
|
||||
me = Field(User)
|
||||
|
||||
def resolve_me(self, info):
|
||||
return info.context["user"]
|
||||
|
||||
|
||||
schema = graphene.Schema(query=Query)
|
||||
schema = Schema(query=Query)
|
||||
query = """
|
||||
query something{
|
||||
me {
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
import graphene
|
||||
from graphene import ObjectType, ID, String, Int, Field, Schema
|
||||
|
||||
|
||||
class Patron(graphene.ObjectType):
|
||||
id = graphene.ID()
|
||||
name = graphene.String()
|
||||
age = graphene.Int()
|
||||
class Patron(ObjectType):
|
||||
id = ID()
|
||||
name = String()
|
||||
age = Int()
|
||||
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
class Query(ObjectType):
|
||||
|
||||
patron = graphene.Field(Patron)
|
||||
patron = Field(Patron)
|
||||
|
||||
def resolve_patron(self, info):
|
||||
return Patron(id=1, name="Syrus", age=27)
|
||||
|
||||
|
||||
schema = graphene.Schema(query=Query)
|
||||
schema = Schema(query=Query)
|
||||
query = """
|
||||
query something{
|
||||
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
|
||||
|
||||
|
||||
class Episode(graphene.Enum):
|
||||
class Episode(Enum):
|
||||
NEWHOPE = 4
|
||||
EMPIRE = 5
|
||||
JEDI = 6
|
||||
|
||||
|
||||
class Character(graphene.Interface):
|
||||
id = graphene.ID()
|
||||
name = graphene.String()
|
||||
friends = graphene.List(lambda: Character)
|
||||
appears_in = graphene.List(Episode)
|
||||
class Character(Interface):
|
||||
id = ID()
|
||||
name = String()
|
||||
friends = List(lambda: Character)
|
||||
appears_in = List(Episode)
|
||||
|
||||
def resolve_friends(self, info):
|
||||
# The character friends is a list of strings
|
||||
return [get_character(f) for f in self.friends]
|
||||
|
||||
|
||||
class Human(graphene.ObjectType):
|
||||
class Meta:
|
||||
interfaces = (Character,)
|
||||
|
||||
home_planet = graphene.String()
|
||||
class Human(ObjectType, interfaces=(Character,)):
|
||||
home_planet = String()
|
||||
|
||||
|
||||
class Droid(graphene.ObjectType):
|
||||
class Meta:
|
||||
interfaces = (Character,)
|
||||
|
||||
primary_function = graphene.String()
|
||||
class Droid(ObjectType, interfaces=(Character,)):
|
||||
primary_function = String()
|
||||
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
hero = graphene.Field(Character, episode=Episode())
|
||||
human = graphene.Field(Human, id=graphene.String())
|
||||
droid = graphene.Field(Droid, id=graphene.String())
|
||||
class Query(ObjectType):
|
||||
hero = Field(Character, episode=Episode())
|
||||
human = Field(Human, id=String())
|
||||
droid = Field(Droid, id=String())
|
||||
|
||||
def resolve_hero(self, info, episode=None):
|
||||
return get_hero(episode)
|
||||
|
@ -49,4 +43,4 @@ class Query(graphene.ObjectType):
|
|||
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 .data import create_ship, get_empire, get_faction, get_rebels, get_ship
|
||||
|
||||
|
||||
class Ship(graphene.ObjectType):
|
||||
"""A ship in the Star Wars saga"""
|
||||
class Ship(ObjectType, interfaces=(relay.Node,)):
|
||||
"""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
|
||||
def get_node(cls, info, id):
|
||||
return get_ship(id)
|
||||
|
||||
|
||||
class ShipConnection(relay.Connection):
|
||||
class Meta:
|
||||
node = Ship
|
||||
class ShipConnection(relay.Connection, node=Ship):
|
||||
pass
|
||||
|
||||
|
||||
class Faction(graphene.ObjectType):
|
||||
"""A faction in the Star Wars saga"""
|
||||
class Faction(ObjectType, interfaces=(relay.Node,)):
|
||||
"""A faction in the Star Wars saga."""
|
||||
|
||||
class Meta:
|
||||
interfaces = (relay.Node,)
|
||||
|
||||
name = graphene.String(description="The name of the faction.")
|
||||
name = String(description="The name of the faction.")
|
||||
ships = relay.ConnectionField(
|
||||
ShipConnection, description="The ships used by the faction."
|
||||
)
|
||||
|
@ -44,11 +37,11 @@ class Faction(graphene.ObjectType):
|
|||
|
||||
class IntroduceShip(relay.ClientIDMutation):
|
||||
class Input:
|
||||
ship_name = graphene.String(required=True)
|
||||
faction_id = graphene.String(required=True)
|
||||
ship_name = String(required=True)
|
||||
faction_id = String(required=True)
|
||||
|
||||
ship = graphene.Field(Ship)
|
||||
faction = graphene.Field(Faction)
|
||||
ship = Field(Ship)
|
||||
faction = Field(Faction)
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(
|
||||
|
@ -59,9 +52,9 @@ class IntroduceShip(relay.ClientIDMutation):
|
|||
return IntroduceShip(ship=ship, faction=faction)
|
||||
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
rebels = graphene.Field(Faction)
|
||||
empire = graphene.Field(Faction)
|
||||
class Query(ObjectType):
|
||||
rebels = Field(Faction)
|
||||
empire = Field(Faction)
|
||||
node = relay.Node.Field()
|
||||
|
||||
def resolve_rebels(self, info):
|
||||
|
@ -71,8 +64,8 @@ class Query(graphene.ObjectType):
|
|||
return get_empire()
|
||||
|
||||
|
||||
class Mutation(graphene.ObjectType):
|
||||
class Mutation(ObjectType):
|
||||
introduce_ship = IntroduceShip.Field()
|
||||
|
||||
|
||||
schema = graphene.Schema(query=Query, mutation=Mutation)
|
||||
schema = Schema(query=Query, mutation=Mutation)
|
||||
|
|
|
@ -808,14 +808,14 @@ class Signature(object):
|
|||
def bind(self, *args, **kwargs):
|
||||
"""Get a BoundArguments object, that maps the passed `args`
|
||||
and `kwargs` to the function's signature. Raises `TypeError`
|
||||
if the passed arguments can not be bound.
|
||||
if the passed arguments cannot be bound.
|
||||
"""
|
||||
return self._bind(args, kwargs)
|
||||
|
||||
def bind_partial(self, *args, **kwargs):
|
||||
"""Get a BoundArguments object, that partially maps the
|
||||
passed `args` and `kwargs` to the function's signature.
|
||||
Raises `TypeError` if the passed arguments can not be bound.
|
||||
Raises `TypeError` if the passed arguments cannot be bound.
|
||||
"""
|
||||
return self._bind(args, kwargs, partial=True)
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ class Field(MountedType):
|
|||
source and resolver
|
||||
), "A Field cannot have a source and a resolver in at the same time."
|
||||
assert not callable(default_value), (
|
||||
'The default value can not be a function but received "{}".'
|
||||
'The default value cannot be a function but received "{}".'
|
||||
).format(base_type(default_value))
|
||||
|
||||
if required:
|
||||
|
|
|
@ -14,7 +14,7 @@ class Structure(UnmountedType):
|
|||
cls_name = type(self).__name__
|
||||
of_type_name = type(of_type).__name__
|
||||
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
|
||||
)
|
||||
)
|
||||
|
|
|
@ -57,7 +57,7 @@ def test_field_default_value_not_callable():
|
|||
Field(MyType, default_value=lambda: True)
|
||||
except AssertionError as e:
|
||||
# substring comparison for py 2/3 compatibility
|
||||
assert "The default value can not be a function but received" in str(e)
|
||||
assert "The default value cannot be a function but received" in str(e)
|
||||
|
||||
|
||||
def test_field_source():
|
||||
|
|
|
@ -19,7 +19,7 @@ def test_list_with_unmounted_type():
|
|||
|
||||
assert (
|
||||
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 (
|
||||
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