### Setup Virtual Environment and Install Dependencies Source: https://github.com/graphql-python/graphene/blob/master/README.md Set up a virtual environment named 'venv' and install project dependencies, including test extras, using pip. ```bash virtualenv venv source venv/bin/activate pip install -e ".[test]" ``` -------------------------------- ### Install Graphene Source: https://github.com/graphql-python/graphene/blob/master/docs/quickstart.rst Install Graphene version 3.0 or higher using pip. ```bash pip install "graphene>=3.0" ``` -------------------------------- ### Graphene v3 Subscription Example Source: https://github.com/graphql-python/graphene/wiki/v3-release-notes This example demonstrates Graphene v3's new subscription support by yielding counts from 1 to 10. Note that server support for websockets is still required. ```python from graphene import ObjectType, Int, Schema class Subscription(ObjectType): count_to_ten = Int() async def subscribe_count_to_ten(root, info): count = 0 while count < 10: count += 1 yield count class Query(ObjectType): a = String() schema = Schema(query=Query, subscription=Subscription) result = await schema.subscribe("subscription { countToTen }") count = 0 async for item in result: count = item.data["countToTen"] assert count == 10 ``` -------------------------------- ### Install Graphene Source: https://github.com/graphql-python/graphene/blob/master/README.md Install the graphene library using pip. Ensure you are using a version greater than or equal to 3.1. ```bash pip install "graphene>=3.1" ``` -------------------------------- ### Install Pre-commit Hooks Source: https://github.com/graphql-python/graphene/blob/master/README.md Install pre-commit hooks to ensure code quality and consistency before committing changes. ```bash pre-commit install ``` -------------------------------- ### Example GraphQL Query Source: https://github.com/graphql-python/graphene/blob/master/docs/quickstart.rst This is an example of a GraphQL query requesting the 'hello' field with a 'firstName' argument. ```graphql { hello(firstName: "friend") } ``` -------------------------------- ### Example GraphQL Response Source: https://github.com/graphql-python/graphene/blob/master/docs/quickstart.rst This is the expected JSON response for the 'hello' query with the 'firstName' argument. ```json { "data": { "hello": "Hello friend!" } } ``` -------------------------------- ### Execute a Basic Mutation Source: https://github.com/graphql-python/graphene/blob/master/docs/types/mutations.rst Example GraphQL query string to execute the `createPerson` mutation defined previously. ```graphql mutation myFirstMutation { createPerson(name:"Peter") { person { name } ok } } ``` -------------------------------- ### JSONString Example Source: https://github.com/graphql-python/graphene/blob/master/docs/types/scalars.rst Demonstrates how to use the JSONString scalar type to handle JSON input and update specific keys within it. ```APIDOC ## JSONString Represents a JSON string. ### Usage ```python from graphene import Schema, ObjectType, JSONString, String class Query(ObjectType): update_json_key = JSONString( required=True, json_input=JSONString(required=True), key=String(required=True), value=String(required=True) ) def resolve_update_json_key(root, info, json_input, key, value): assert json_input == {"name": "Jane"} json_input[key] = value return json_input schema = Schema(query=Query) results = schema.execute(""" query { updateJsonKey(jsonInput: \"{\\\"name\\\": \\"Jane\\\"}\", key: \"name\", value: \"Beth\") } """) assert results.data == {"updateJsonKey": "{\"name\": \"Beth\"}"} ``` ``` -------------------------------- ### Mutation Response Example Source: https://github.com/graphql-python/graphene/blob/master/docs/types/mutations.rst Expected JSON response after executing the `createPerson` mutation. ```json { "createPerson": { "person" : { "name": "Peter" }, "ok": true } } ``` -------------------------------- ### Base64 Example Source: https://github.com/graphql-python/graphene/blob/master/docs/types/scalars.rst Illustrates the use of the Base64 scalar type for encoding and decoding Base64 strings, shown here with an integer increment operation. ```APIDOC ## Base64 Represents a Base64 encoded string. ### Usage ```python from graphene import Schema, ObjectType, Base64 class Query(ObjectType): increment_encoded_id = Base64( required=True, base64_input=Base64(required=True), ) def resolve_increment_encoded_id(root, info, base64_input): assert base64_input == "4" return int(base64_input) + 1 schema = Schema(query=Query) results = schema.execute(""" query { incrementEncodedId(base64Input: "NA==") } """) assert results.data == {"incrementEncodedId": "NQ=="} ``` ``` -------------------------------- ### Basic Graphene Schema Definition Source: https://github.com/graphql-python/graphene/blob/master/README.md Define a basic GraphQL schema using graphene. This example shows how to create a simple query field. ```python import graphene class Query(graphene.ObjectType): hello = graphene.String(description='A typical hello world') def resolve_hello(self, info): return 'World' schema = graphene.Schema(query=Query) ``` -------------------------------- ### Execute Mutation with InputObject Data Source: https://github.com/graphql-python/graphene/blob/master/docs/types/mutations.rst Example GraphQL query string to execute a mutation that accepts an `InputObjectType`. ```graphql mutation myFirstMutation { createPerson(personData: {name:"Peter", age: 24}) { person { name, age } } } ``` -------------------------------- ### Basic Relay Mutation Example Source: https://github.com/graphql-python/graphene/blob/master/docs/relay/mutations.rst Define a mutation that creates a ship and returns the created ship and its faction. This mutation subclasses relay.ClientIDMutation and defines input arguments and return fields. ```python class IntroduceShip(relay.ClientIDMutation): class Input: ship_name = graphene.String(required=True) faction_id = graphene.String(required=True) ship = graphene.Field(Ship) faction = graphene.Field(Faction) @classmethod def mutate_and_get_payload(cls, root, info, **input): ship_name = input.ship_name faction_id = input.faction_id ship = create_ship(ship_name, faction_id) faction = get_faction(faction_id) return IntroduceShip(ship=ship, faction=faction) ``` -------------------------------- ### Ensure Correct Order in Batch Load Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/dataloader.rst When fetching data for multiple keys, ensure the returned list of values is in the same order as the input keys. This example filters users by IDs and then orders the results. ```python class UserLoader(DataLoader): async def batch_load_fn(self, keys): users = {user.id: user for user in User.objects.filter(id__in=keys)} return [users.get(user_id) for user_id in keys] ``` -------------------------------- ### Querying a Graphene Schema Source: https://github.com/graphql-python/graphene/blob/master/README.md Execute a GraphQL query against a defined graphene schema. This demonstrates how to send a query string and get the result. ```python query = ''' query SayHello { hello } ''' result = schema.execute(query) ``` -------------------------------- ### Using graphene.Time Scalar Source: https://github.com/graphql-python/graphene/blob/master/docs/types/scalars.rst Shows how to implement the Time scalar for time-specific logic. This example requires importing datetime and Graphene components. It resolves a time one hour after the provided time input. ```python import datetime from graphene import Schema, ObjectType, Time class Query(ObjectType): one_hour_from = Time(required=True, time_input=Time(required=True)) def resolve_one_hour_from(root, info, time_input): assert time_input == datetime.time(15, 4, 5) tmp_time_input = datetime.datetime.combine(datetime.date(1, 1, 1), time_input) return (tmp_time_input + datetime.timedelta(hours=1)).time() schema = Schema(query=Query) results = schema.execute(""" query { oneHourFrom(timeInput: "15:04:05") } """) assert results.data == {"oneHourFrom": "16:04:05"} ``` -------------------------------- ### Schema Instance Check: Direct Subclassing (Before) Source: https://github.com/graphql-python/graphene/wiki/v3-release-notes Previously, Graphene's Schema class directly subclassed GraphQLSchema. This example demonstrates the check used before v3. ```python from graphql import GraphQLSchema from graphene import Schema # Assuming Query is defined elsewhere # class Query(ObjectType): # pass # schema = Schema(query=Query) # Placeholder for schema definition if not provided in context class DummyQuery(ObjectType): pass schema = Schema(query=DummyQuery) assert isinstance(schema, GraphQLSchema) ``` -------------------------------- ### Query with CamelCase Fields Source: https://github.com/graphql-python/graphene/blob/master/docs/types/schema.rst Example of how a query would look when using fields that have been auto camelCased or explicitly named. ```graphql { lastName _other_Name } ``` -------------------------------- ### Using graphene.Decimal Scalar Source: https://github.com/graphql-python/graphene/blob/master/docs/types/scalars.rst Demonstrates the use of the Decimal scalar for precise decimal arithmetic. It requires importing the decimal module and Graphene. The example adds one to a given decimal input. ```python import decimal from graphene import Schema, ObjectType, Decimal class Query(ObjectType): add_one_to = Decimal(required=True, decimal_input=Decimal(required=True)) def resolve_add_one_to(root, info, decimal_input): assert decimal_input == decimal.Decimal("10.50") return decimal_input + decimal.Decimal("1") schema = Schema(query=Query) ``` -------------------------------- ### Execute Mutation Returning ObjectType Source: https://github.com/graphql-python/graphene/blob/master/docs/types/mutations.rst Example GraphQL query string to execute a mutation configured to return an existing `ObjectType`. ```graphql mutation myFirstMutation { createPerson(name:"Peter") { name __typename } } ``` -------------------------------- ### Using graphene.Date Scalar Source: https://github.com/graphql-python/graphene/blob/master/docs/types/scalars.rst Demonstrates how to use the Date scalar for date-based operations. It requires importing datetime and Graphene components. The example shows resolving a date one week from an input date. ```python import datetime from graphene import Schema, ObjectType, Date class Query(ObjectType): one_week_from = Date(required=True, date_input=Date(required=True)) def resolve_one_week_from(root, info, date_input): assert date_input == datetime.date(2006, 1, 2) return date_input + datetime.timedelta(weeks=1) schema = Schema(query=Query) results = schema.execute(""" query { oneWeekFrom(dateInput: "2006-01-02") } """) assert results.data == {"oneWeekFrom": "2006-01-09"} ``` -------------------------------- ### Custom DateTime Scalar Source: https://github.com/graphql-python/graphene/blob/master/docs/types/scalars.rst Provides an example of creating a custom scalar type for DateTime, including serialization and parsing logic. ```APIDOC ## Custom DateTime Scalar Example of creating a custom DateTime scalar. ### Definition ```python import datetime from graphene.types import Scalar from graphql.language import ast class DateTime(Scalar): '''DateTime Scalar Description''' @staticmethod def serialize(dt): return dt.isoformat() @staticmethod def parse_literal(node, _variables=None): if isinstance(node, ast.StringValueNode): return datetime.datetime.strptime( node.value, "%Y-%m-%dT%H:%M:%S.%f") @staticmethod def parse_value(value): return datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f") ``` ``` -------------------------------- ### Implicit Static Methods for Resolvers Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Demonstrates how Graphene implicitly treats resolver methods as static methods. The first argument is always the parent object, not 'self'. This example shows both explicit '@staticmethod' usage and implicit handling. ```python from graphene import ObjectType, String class Person(ObjectType): first_name = String() last_name = String() @staticmethod def resolve_first_name(parent, info): ''' Decorating a Python method with `staticmethod` ensures that `self` will not be provided as an argument. However, Graphene does not need this decorator for this behavior. ''' return parent.first_name def resolve_last_name(parent, info): ''' Normally the first argument for this method would be `self`, but Graphene executes this as a staticmethod implicitly. ''' return parent.last_name # ... ``` -------------------------------- ### Query Result for Droid Episode Source: https://github.com/graphql-python/graphene/blob/master/docs/types/interfaces.rst Example JSON data returned when querying for a hero in an episode that resolves to a Droid. Includes the typename and specific Droid fields. ```json { "data": { "hero": { "__typename": "Droid", "name": "R2-D2", "primaryFunction": "Astromech" } } } ``` -------------------------------- ### Querying with Field Arguments Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Example of a GraphQL query that utilizes a field with a required argument. The argument value is provided within the query. ```graphql query { humanByName(name: "Luke Skywalker") { firstName lastName } } ``` -------------------------------- ### Query Result for Human Episode Source: https://github.com/graphql-python/graphene/blob/master/docs/types/interfaces.rst Example JSON data returned when querying for a hero in an episode that resolves to a Human. Includes the typename and specific Human fields. ```json { "data": { "hero": { "__typename": "Human", "name": "Luke Skywalker", "homePlanet": "Tatooine" } } } ``` -------------------------------- ### GraphQL Pagination Response Structure Source: https://github.com/graphql-python/graphene/wiki/Relay-Pagination-example Illustrates the structure of the 'pageInfo' object returned in paginated GraphQL queries, including start and end cursors and page navigation flags. ```json { "pageInfo": { "startCursor": "YXJyYXljb25uZWN0aW9uOjQx", "endCursor": "YXJyYXljb25uZWN0aW9uOjQz", "hasNextPage": false, "hasPreviousPage": true } } ``` -------------------------------- ### ObjectType Initialization: Direct Initialization of Private Fields (Before) Source: https://github.com/graphql-python/graphene/wiki/v3-release-notes Before Graphene v3, ObjectTypes could be initialized directly with private variables by simply prepending an underscore. This example shows the older, less explicit method. ```python from graphene import ObjectType, String class User(ObjectType): _private_state = None name = String() user = User(name="Leia", _private_state="Extra info") assert user._private_state == "Extra info" ``` -------------------------------- ### Resolver for ObjectType Field Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Example demonstrating how to resolve a field on an ObjectType. The `parent` object is used to access data from the parent resolver, and `info` provides execution context. ```python from graphene import ObjectType, String, Field def get_human(name): first_name, last_name = name.split() return Person(first_name, last_name) class Person(ObjectType): full_name = String() def resolve_full_name(parent, info): return f"{parent.first_name} {parent.last_name}" class Query(ObjectType): me = Field(Person) def resolve_me(parent, info): # returns an object that represents a Person return get_human(name="Luke Skywalker") ``` -------------------------------- ### Using graphene.DateTime Scalar Source: https://github.com/graphql-python/graphene/blob/master/docs/types/scalars.rst Illustrates the usage of the DateTime scalar for date and time operations. It involves importing datetime and Graphene. The example resolves a datetime one hour after the input datetime. ```python import datetime from graphene import Schema, ObjectType, DateTime class Query(ObjectType): one_hour_from = DateTime(required=True, datetime_input=DateTime(required=True)) def resolve_one_hour_from(root, info, datetime_input): assert datetime_input == datetime.datetime(2006, 1, 2, 15, 4, 5) return datetime_input + datetime.timedelta(hours=1) schema = Schema(query=Query) results = schema.execute(""" query { oneHourFrom(datetimeInput: "2006-01-02T15:04:05") } """) assert results.data == {"oneHourFrom": "2006-01-02T16:04:05"} ``` -------------------------------- ### GraphQL Paginated Data Response Source: https://github.com/graphql-python/graphene/wiki/Relay-Pagination-example Shows an example of the JSON response received after executing a paginated GraphQL query, including 'pageInfo' and 'edges' with node data. ```json { "data": { "places": { "pageInfo": { "startCursor": "YXJyYXljb25uZWN0aW9uOjQy", "endCursor": "YXJyYXljb25uZWN0aW9uOjQ0", "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "cursor": "YXJyYXljb25uZWN0aW9uOjQy", "node": { "id": "UGxhY2VfTm9kZV9UeXBlOjQz", "name": "Wilton, Franklin, Maine, United States" } }, { "cursor": "YXJyYXljb25uZWN0aW9uOjQz", "node": { "id": "UGxhY2VfTm9kZV9UeXBlOjQ0", "name": "Boise City, Ada, Idaho, United States" } }, { "cursor": "YXJyYXljb25uZWN0aW9uOjQ0", "node": { "id": "UGxhY2VfTm9kZV9UeXBlOjQ1", "name": "Helena, Shelby, Akabama, USA" } } ] } } } ``` -------------------------------- ### Implement Depth Limit Validator Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/queryvalidation.rst Use the depth_limit_validator to prevent overly complex or potentially malicious queries by setting a maximum allowed depth. Ensure the graphql and graphene libraries are installed. ```python from graphql import validate, parse from graphene import ObjectType, Schema, String from graphene.validation import depth_limit_validator class MyQuery(ObjectType): name = String(required=True) schema = Schema(query=MyQuery) # queries which have a depth more than 20 # will not be executed. validation_errors = validate( schema=schema.graphql_schema, document_ast=parse('THE QUERY'), rules=( depth_limit_validator( max_depth=20 ), ) ) ``` -------------------------------- ### Implement Custom Blacklist Field Validator Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/queryvalidation.rst Create a custom validation rule by extending `ValidationRule` to check for blacklisted fields in a GraphQL query. This example demonstrates how to report errors for disallowed fields. ```python from graphql import GraphQLError from graphql.language import FieldNode from graphql.validation import ValidationRule my_blacklist = ( "disallowed_field", ) def is_blacklisted_field(field_name: str): return field_name.lower() in my_blacklist class BlackListRule(ValidationRule): def enter_field(self, node: FieldNode, *_args): field_name = node.name.value if not is_blacklisted_field(field_name): return self.report_error( GraphQLError( f"Cannot query '{field_name}': field is blacklisted.", node, ) ) ``` -------------------------------- ### Receive Enum Member Directly in Resolver Input (Graphene v3) Source: https://github.com/graphql-python/graphene/wiki/v3-release-notes When Enums are used as input fields in Graphene v3, resolvers now receive the Enum member directly. This example asserts that color_input is Color.RED. ```python from graphene import Enum, ObjectType, Schema class Color(Enum): RED = 1 GREEN = 2 BLUE = 3 class Query(ObjectType): color = Color(required=True, color_input=Color(required=True)) def resolve_color(root, info, color_input): assert color_input is Color.RED return color_input schema = Schema(query=Query) result = schema.execute("query { color(colorInput: RED) }") assert result.data["color"] == "RED" ``` -------------------------------- ### Build Documentation with Make Source: https://github.com/graphql-python/graphene/blob/master/README.md Generate the HTML version of the project documentation using the 'make docs' command. This process utilizes Sphinx and a custom theme. ```bash make docs ``` -------------------------------- ### Define and Execute a Subscription Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/subscriptions.rst Defines a basic schema with a query and a subscription that yields the current time every second. It then demonstrates how to execute this subscription and print the received data. ```python import asyncio from datetime import datetime from graphene import ObjectType, String, Schema, Field # Every schema requires a query. class Query(ObjectType): hello = String() def resolve_hello(root, info): return "Hello, world!" class Subscription(ObjectType): time_of_day = String() async def subscribe_time_of_day(root, info): while True: yield datetime.now().isoformat() await asyncio.sleep(1) schema = Schema(query=Query, subscription=Subscription) async def main(schema): subscription = 'subscription { timeOfDay }' result = await schema.subscribe(subscription) async for item in result: print(item.data['timeOfDay']) asyncio.run(main(schema)) ``` -------------------------------- ### Basic Query Execution with Test Client Source: https://github.com/graphql-python/graphene/blob/master/docs/testing/index.rst Instantiate graphene.test.Client and retrieve GraphQL responses by executing a query. ```python from graphene.test import Client def test_hey(): client = Client(my_schema) executed = client.execute('''{ hey }''') assert executed == { 'data': { 'hey': 'hello!' } } ``` -------------------------------- ### Configure interfaces and possible types using Meta class Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Shows how to specify GraphQL Interfaces that an ObjectType implements and provide 'possible_types' to help Graphene resolve ambiguous types like interfaces or Unions. ```python from graphene import ObjectType, Node Song = namedtuple('Song', ('title', 'artist')) class MyGraphQlSong(ObjectType): class Meta: interfaces = (Node, ) possible_types = (Song, ) ``` -------------------------------- ### Mounting Types as Arguments Source: https://github.com/graphql-python/graphene/blob/master/docs/types/scalars.rst Illustrates how types mounted in a Field are treated as Arguments. This shows the equivalence between passing a type instance directly and using graphene.Argument. ```python graphene.Field(graphene.String, to=graphene.String()) # Is equivalent to: graphene.Field(graphene.String, to=graphene.Argument(graphene.String)) ``` -------------------------------- ### Executing Schema with Middleware Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/middleware.rst Demonstrates how to pass a middleware instance to the schema's execute method. Multiple middlewares are executed bottom-up. ```python result = schema.execute('THE QUERY', middleware=[AuthorizationMiddleware()]) ``` -------------------------------- ### Create a Basic Graphene Schema Source: https://github.com/graphql-python/graphene/blob/master/docs/quickstart.rst Defines a simple GraphQL schema with 'hello' and 'goodbye' fields using Python ObjectTypes. The 'hello' field accepts a 'first_name' argument. ```python from graphene import ObjectType, String, Schema class Query(ObjectType): # this defines a Field `hello` in our Schema with a single Argument `first_name` # By default, the argument name will automatically be camel-based into firstName in the generated schema hello = String(first_name=String(default_value="stranger")) goodbye = String() # our Resolver method takes the GraphQL context (root, info) as well as # Argument (first_name) for the Field and returns data for the query Response def resolve_hello(root, info, first_name): return f'Hello {first_name}!' def resolve_goodbye(root, info): return 'See ya!' schema = Schema(query=Query) ``` -------------------------------- ### Schema Execution and Query Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Demonstrates executing a GraphQL query against a Graphene schema and asserting the result. This shows the practical application of the defined resolvers. ```python schema = Schema(query=Query) query_string = "{ me { fullName } }" result = schema.execute(query_string) assert result.data["me"] == {"fullName": "Luke Skywalker"} ``` -------------------------------- ### Configure ObjectType description using Meta class or docstring Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Demonstrates setting the schema description for an ObjectType. The description can be provided as a docstring on the Python object or as the 'description' property in the inner Meta class, with the Meta class value taking precedence. ```python from graphene import ObjectType class MyGraphQlSong(ObjectType): ''' We can set the schema description for an Object Type here on a docstring ''' class Meta: description = 'But if we set the description in Meta, this value is used instead' ``` -------------------------------- ### Relay Connection Field in ObjectType Source: https://github.com/graphql-python/graphene/blob/master/docs/relay/connection.rst Use relay.ConnectionField to add a connection to an ObjectType. This example shows how to define a 'ships' connection for a 'Faction' type. ```python class Faction(graphene.ObjectType): name = graphene.String() ships = relay.ConnectionField(ShipConnection) def resolve_ships(root, info): return [] ``` -------------------------------- ### Executing Schema with Functional Middleware Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/middleware.rst Shows how to execute a schema using a functional middleware. The middleware is passed as an element in a list to the 'middleware' argument. ```python result = schema.execute('THE QUERY', middleware=[timing_middleware]) ``` -------------------------------- ### Handle missing required arguments with **kwargs Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Demonstrates how to handle missing required arguments by collecting all keyword arguments into a dictionary and using .get() with a default value. ```python from graphene import ObjectType, String class Query(ObjectType): hello = String(required=True, name=String()) def resolve_hello(parent, info, **kwargs): name = kwargs.get('name', 'World') return f'Hello, {name}!' ``` -------------------------------- ### Resolve Enum Value Directly in Graphene v3 Source: https://github.com/graphql-python/graphene/wiki/v3-release-notes In Graphene v3, resolvers can return Enum members directly instead of their values. This example shows returning Color.RED. ```python from graphene import Enum, ObjectType, Schema class Color(Enum): RED = 1 GREEN = 2 BLUE = 3 class Query(ObjectType): color = Color(required=True) def resolve_color(root, info): return Color.RED schema = Schema(query=Query) result = schema.execute("query { color }") assert result.data["color"] == "RED" ``` -------------------------------- ### Execute a GraphQL Query Programmatically Source: https://github.com/graphql-python/graphene/blob/master/docs/quickstart.rst Demonstrates how to execute GraphQL queries against a Graphene schema object using the 'execute' method. Shows querying with and without arguments. ```python # we can query for our field (with the default argument) query_string = '{ hello }' result = schema.execute(query_string) print(result.data['hello']) # "Hello stranger!" # or passing the argument in the query query_with_argument = '{ hello(firstName: "GraphQL") }' result = schema.execute(query_with_argument) print(result.data['hello']) # "Hello GraphQL!" ``` -------------------------------- ### Error Message for Unresolved Interface Type Source: https://github.com/graphql-python/graphene/blob/master/docs/types/interfaces.rst An example of an error message encountered when Graphene cannot determine which concrete type to resolve for an interface field. This typically occurs when 'resolve_type' is not defined. ```text "Abstract type Character must resolve to an Object type at runtime for field Query.hero ..." ``` -------------------------------- ### Define a User DataLoader Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/dataloader.rst Create a DataLoader by subclassing DataLoader and implementing the batch_load_fn. This function receives a list of keys and should return a list of corresponding values. ```python from aiodataloader import DataLoader class UserLoader(DataLoader): async def batch_load_fn(self, keys): # Here we call a function to return a user for each key in keys return [get_user(id=key) for key in keys] ``` -------------------------------- ### Complete Schema with Mutation and Query Source: https://github.com/graphql-python/graphene/blob/master/docs/types/mutations.rst This snippet demonstrates how to integrate a defined mutation into a Graphene schema, including a necessary Query type. ```python # ... the Mutation Class class Person(graphene.ObjectType): name = graphene.String() age = graphene.Int() class MyMutations(graphene.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) ``` -------------------------------- ### Execute a Basic Query Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/execute.rst Directly call the `execute` method on a Graphene schema to run a query. The result object contains data and potential errors. ```python from graphene import Schema schema = Schema(...) result = schema.execute('{ name }') ``` -------------------------------- ### Resolver Access to Context and Info Source: https://github.com/graphql-python/graphene/wiki/Roadmap Demonstrates how resolvers can access context and info objects using the `@with_info` and `@with_context` decorators. This provides a way to inject these objects when needed without them being default arguments. ```python class MyObjectType(graphene.ObjectType): field_with_info_and_context = graphene.String(to=graphene.String()) @with_info @with_context def field_with_info_and_context(self, to, context, info): return "Hello {}".format(to) ``` -------------------------------- ### Create a Graphene Schema Source: https://github.com/graphql-python/graphene/blob/master/docs/types/schema.rst Instantiate a Schema object by providing the root ObjectTypes for query, mutation, and subscription operations. ```python my_schema = Schema( query=MyRootQuery, mutation=MyRootMutation, subscription=MyRootSubscription ) ``` -------------------------------- ### Enum Input Handling: Resolver Received Enum Value (Before) Source: https://github.com/graphql-python/graphene/wiki/v3-release-notes Prior to v3, resolvers received the underlying value of an Enum member when it was used as an input. This example shows the previous behavior for comparison. ```python from graphene import Enum, ObjectType, String, Schema class Color(Enum): RED = 1 GREEN = 2 BLUE = 3 class Query(ObjectType): color = String(color_input=Color(required=True)) def resolve_color(root, info, color_input): return color_input schema = Schema(query=Query) result = schema.execute("query { color(colorInput: RED) }") assert result.data["color"] == "1" ``` -------------------------------- ### Load Users with DataLoader Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/dataloader.rst Instantiate a DataLoader and use its load method to fetch individual items. DataLoader automatically batches concurrent requests within an event loop frame. ```python user_loader = UserLoader() user1 = await user_loader.load(1) user1_best_friend = await user_loader.load(user1.best_friend_id) user2 = await user_loader.load(2) user2_best_friend = await user_loader.load(user2.best_friend_id) ``` -------------------------------- ### Run Benchmarks with Pytest Source: https://github.com/graphql-python/graphene/blob/master/README.md Execute performance benchmarks for the graphene project using pytest with the benchmark-only flag. ```bash pytest graphene --benchmark-only ``` -------------------------------- ### Run Tests with Tox for All Python Versions Source: https://github.com/graphql-python/graphene/blob/master/README.md Use tox to run tests across all Python versions specified in the tox.ini configuration file. Tox creates virtual environments for each Python version. ```bash tox ``` -------------------------------- ### Query Execution with Extra Parameters Source: https://github.com/graphql-python/graphene/blob/master/docs/testing/index.rst Add extra keyword arguments to the execute method, such as context, root, variables, etc. ```python 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!' } } ``` -------------------------------- ### Mutation Accepting Files Source: https://github.com/graphql-python/graphene/blob/master/docs/relay/mutations.rst Implement a mutation that can accept file uploads. The files are accessed via the context in the mutation payload. ```python class UploadFile(graphene.ClientIDMutation): class Input: pass # nothing needed for uploading file # your return fields success = graphene.String() @classmethod def mutate_and_get_payload(cls, root, info, **input): # When using it in Django, context will be the request files = info.context.FILES # Or, if used in Flask, context will be the flask global request # files = context.files # do something with files return UploadFile(success=True) ``` -------------------------------- ### ClientByClientIdLoader Definition (After v3 - Async) Source: https://github.com/graphql-python/graphene/wiki/v3-release-notes This is the definition of a ClientByClientIdLoader using `aiodataloader` after Graphene v3. It requires async views and uses `async def batch_load_fn`. ```python from aiodataloader import DataLoader from typing import Dict from collections import defaultdict from server.domain.entities import Clients class ClientByClientIdLoader(DataLoader): def __init__(self, *args, **kwargs): self.current_user = kwargs.pop("current_user") super().__init__(*args, **kwargs) async def batch_load_fn(self, client_ids): id_client: Dict[int, Clients.Client] = defaultdict(None) clients = Clients.by_ids( current_user=self.current_user, ids=client_ids, ) for client in clients: id_client[client["id"]] = client return [id_client.get(client_id, None) for client_id in client_ids] ``` -------------------------------- ### Using Base64 Scalar Source: https://github.com/graphql-python/graphene/blob/master/docs/types/scalars.rst Illustrates the usage of the Base64 scalar type for encoding and decoding data. The input is expected to be a Base64 encoded string. ```python from graphene import Schema, ObjectType, Base64 class Query(ObjectType): increment_encoded_id = Base64( required=True, base64_input=Base64(required=True), ) def resolve_increment_encoded_id(root, info, base64_input): assert base64_input == "4" return int(base64_input) + 1 schema = Schema(query=Query) results = schema.execute(""" query { incrementEncodedId(base64Input: "NA==") } """) assert results.data == {"incrementEncodedId": "NQ=="} ``` -------------------------------- ### GraphQL Query with Inline Fragments Source: https://github.com/graphql-python/graphene/blob/master/docs/types/interfaces.rst A GraphQL query demonstrating how to fetch fields from an interface and also specific fields from implementing types using inline fragments. ```graphql query HeroForEpisode($episode: Int!) { hero(episode: $episode) { __typename name ... on Droid { primaryFunction } ... on Human { homePlanet } } } ``` -------------------------------- ### Mounting Scalars as Fields Source: https://github.com/graphql-python/graphene/blob/master/docs/types/scalars.rst Demonstrates how scalars mounted in an ObjectType are treated as Fields. This is equivalent to explicitly defining them as graphene.Field. ```python class Person(graphene.ObjectType): name = graphene.String() # Is equivalent to: class Person(graphene.ObjectType): name = graphene.Field(graphene.String) ``` -------------------------------- ### Mounting Scalars in ObjectType Source: https://github.com/graphql-python/graphene/blob/master/docs/types/scalars.rst Demonstrates how scalars mounted within an ObjectType are treated as Fields, and how types mounted in a Field act as Arguments. ```APIDOC ## Mounting Scalars Scalars mounted in a `ObjectType`, `Interface` or `Mutation` act as `Field`s. ### ObjectType Example ```python class Person(graphene.ObjectType): name = graphene.String() # Is equivalent to: class Person(graphene.ObjectType): name = graphene.Field(graphene.String) ``` Types mounted in a `Field` act as `Argument`s. ### Field Argument Example ```python graphene.Field(graphene.String, to=graphene.String()) # Is equivalent to: graphene.Field(graphene.String, to=graphene.Argument(graphene.String)) ``` ``` -------------------------------- ### Use ObjectType as value objects Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Shows how Graphene ObjectTypes can be instantiated and used as value objects to hold data, similar to Python data classes or objects. ```python peter = Person(first_name='Peter', last_name='Griffin') peter.first_name # prints "Peter" peter.last_name # prints "Griffin" ``` -------------------------------- ### Run Tests with Tox for a Specific Python Version Source: https://github.com/graphql-python/graphene/blob/master/README.md Execute tests using tox for a specific Python version, such as py39, as defined in the tox.ini file. ```bash tox -e py39 ``` -------------------------------- ### ClientByClientIdLoader Definition (Before v3) Source: https://github.com/graphql-python/graphene/wiki/v3-release-notes This is the definition of a ClientByClientIdLoader using `promise.dataloader` before Graphene v3. It demonstrates the batch loading mechanism for client data. ```python from promise import Promise from promise.dataloader import DataLoader from typing import Dict from collections import defaultdict from server.domain.entities import Clients class ClientByClientIdLoader(DataLoader): def __init__(self, *args, **kwargs): self.current_user = kwargs.pop("current_user") super().__init__(*args, **kwargs) def batch_load_fn(self, client_ids): id_client: Dict[int, Clients.Client] = defaultdict(None) clients = Clients.by_ids( current_user=self.current_user, ids=client_ids, ) for client in clients: id_client[client["id"]] = client return Promise.resolve( [id_client.get(client_id, None) for client_id in client_ids] ) ``` -------------------------------- ### Simplified Resolver Syntax Source: https://github.com/graphql-python/graphene/wiki/Roadmap Illustrates the proposed simpler resolver syntax where only `self` and `**args` are received by default. This change aims to reduce boilerplate in resolver definitions. ```python class MyObjectType(graphene.ObjectType): hello = graphene.String(to=graphene.String()) other = graphene.String() def resolve_hello(self, to): return "Hello {}".format(to) def resolve_other(self): return "Hey!" ``` -------------------------------- ### ObjectType Initialization: Custom __init__ Required for Private Fields (After) Source: https://github.com/graphql-python/graphene/wiki/v3-release-notes In Graphene v3, initializing ObjectTypes with private fields (prefixed with '_') requires defining a custom __init__ method. This ensures explicit handling of private state. ```python from graphene import ObjectType, String class User(ObjectType): def __init__(self, _private_state=None, **kwargs): self._private_state = _private_state super().__init__(**kwargs) _private_state = None name = String() user = User(name="Leia", _private_state="Extra info") assert user._private_state == "Extra info" ``` -------------------------------- ### graphene.ResolveInfo Source: https://github.com/graphql-python/graphene/blob/master/docs/api/index.rst Provides information about the execution context during field resolution in Graphene. Includes details about the query, schema, and more. ```APIDOC ## Class: graphene.ResolveInfo ### Description Provides information about the execution context during field resolution in Graphene. Includes details about the query, schema, and more. ### Usage Accessible as the second argument in resolver functions, offering context for data fetching and manipulation. ``` -------------------------------- ### GraphQL Query for Paginated Data Source: https://github.com/graphql-python/graphene/wiki/Relay-Pagination-example Demonstrates a GraphQL query to fetch paginated data using 'first' and 'after' arguments, requesting pageInfo and specific node fields. ```graphql { places(first: 3, after: "YXJyYXljb25uZWN0aW9uOjQx") { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { id name } } } } ``` -------------------------------- ### Handle missing required arguments with default value Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Shows how to provide a default value directly to the argument in the resolver function signature to handle cases where the argument is not provided. ```python from graphene import ObjectType, String class Query(ObjectType): hello = String(required=True, name=String()) def resolve_hello(parent, info, name='World'): return f'Hello, {name}!' ``` -------------------------------- ### Define Nested InputObjectTypes Source: https://github.com/graphql-python/graphene/blob/master/docs/types/mutations.rst Shows how to create nested `InputObjectType` structures, allowing for complex and hierarchical input data in mutations. ```python import graphene 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) ``` -------------------------------- ### GraphQL Schema Definition Language (SDL) Equivalent Source: https://github.com/graphql-python/graphene/blob/master/docs/quickstart.rst This is the equivalent schema definition in GraphQL Schema Definition Language (SDL) for the Python code above. ```graphql type Query { hello(firstName: String = "stranger"): String goodbye: String } ``` -------------------------------- ### GraphQL Schema Definition for Interfaces Source: https://github.com/graphql-python/graphene/blob/master/docs/types/interfaces.rst The complete GraphQL schema definition showing the Character interface and its implementations by Human and Droid types. Note the 'implements' keyword. ```graphql interface Character { id: ID! name: String! friends: [Character] } type Human implements Character { id: ID! name: String! friends: [Character] starships: [Starship] homePlanet: String } type Droid implements Character { id: ID! name: String! friends: [Character] primaryFunction: String } ``` -------------------------------- ### Execute a GraphQL Query Source: https://github.com/graphql-python/graphene/blob/master/docs/types/schema.rst Execute a query string against a Graphene schema using the execute method. This is the primary way to interact with your API. ```python query_string = 'query whoIsMyBestFriend { myBestFriend { lastName } }' my_schema.execute(query_string) ``` -------------------------------- ### Graphene ObjectType with Class Arguments Source: https://github.com/graphql-python/graphene/wiki/Docs-and-Example-Code-Style-Guide-Work:-graphene-v-3.0 Use class arguments directly in the ObjectType definition instead of a nested Meta class for interfaces. ```python class Human(graphene.ObjectType, interfaces = (Character, )): starships = graphene.List(Starship) home_planet = graphene.String() ``` -------------------------------- ### Resolver with Argument Clashing with Reserved Field Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Shows how to handle an argument name that clashes with Graphene's reserved fields by using the `args` parameter. The argument is then passed to the resolver. ```python from graphene import ObjectType, Field, String class Query(ObjectType): answer = String(args={'description': String()}) def resolve_answer(parent, info, description): return description ``` -------------------------------- ### Mutation using InputObjectType Source: https://github.com/graphql-python/graphene/blob/master/docs/types/mutations.rst Demonstrates how to use a defined `InputObjectType` as an argument for a mutation. The mutation resolver accesses nested input data through the argument object. ```python import graphene class PersonInput(graphene.InputObjectType): name = graphene.String(required=True) age = graphene.Int(required=True) class CreatePerson(graphene.Mutation): class Arguments: person_data = PersonInput(required=True) person = graphene.Field(Person) def mutate(root, info, person_data=None): person = Person( name=person_data.name, age=person_data.age ) return CreatePerson(person=person) ``` -------------------------------- ### graphene.Context Source: https://github.com/graphql-python/graphene/blob/master/docs/api/index.rst Represents the execution context for a GraphQL request in Graphene. Can be used to pass request-specific data. ```APIDOC ## Class: graphene.Context ### Description Represents the execution context for a GraphQL request in Graphene. Can be used to pass request-specific data. ### Usage Typically passed to the `execute` function and accessible within resolvers via `ResolveInfo`. ``` -------------------------------- ### Execute Query with Context Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/execute.rst Pass custom context to a query execution using the `context` parameter. This context is accessible within resolver functions via `info.context`. ```python from graphene import ObjectType, String, Schema class Query(ObjectType): name = String() def resolve_name(root, info): return info.context.get('name') schema = Schema(Query) result = schema.execute('{ name }', context={'name': 'Syrus'}) assert result.data['name'] == 'Syrus' ``` -------------------------------- ### Define a Basic Graphene Mutation Source: https://github.com/graphql-python/graphene/blob/master/docs/types/mutations.rst This snippet shows how to define a simple mutation with arguments and output fields. The `mutate` method handles the data modification logic. ```python import graphene class CreatePerson(graphene.Mutation): class Arguments: name = graphene.String() ok = graphene.Boolean() person = graphene.Field(lambda: Person) def mutate(root, info, name): person = Person(name=name) ok = True return CreatePerson(person=person, ok=ok) ``` -------------------------------- ### Graphene Python Implementation for Pagination Source: https://github.com/graphql-python/graphene/wiki/Relay-Pagination-example Provides a Python implementation using Graphene to set up cursor-based pagination with DjangoObjectType, Connection, and ConnectionField. It defines a custom count field for the connection. ```python from graphene import Connection, ConnectionField, Node, Int from graphene_django import DjangoObjectType from import Place class Place_Node_Type(DjangoObjectType): class Meta: model = Place interfaces = (Node, ) class Place_Connection(Connection): class Meta: node = Place_Node_Type count = Int() def resolve_count(root, info): return len(root.edges) class Query(object): places = ConnectionField(Place_Connection) def resolve_places(root, info, **kwargs): return Place.objects.all() ``` -------------------------------- ### Functional Timing Middleware Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/middleware.rst A functional middleware that logs the time taken to resolve each field. It requires importing the timer function from the time module. ```python from time import time as timer def timing_middleware(next, root, info, **args): start = timer() return_value = next(root, info, **args) duration = round((timer() - start) * 1000, 2) parent_type_name = root._meta.name if root and hasattr(root, '_meta') else '' logger.debug(f"{parent_type_name}.{info.field_name}: {duration} ms") return return_value ``` -------------------------------- ### Mutation Returning an Existing ObjectType Source: https://github.com/graphql-python/graphene/blob/master/docs/types/mutations.rst This snippet demonstrates how to configure a mutation to return an existing `ObjectType` directly by setting the `Output` attribute. This simplifies return types when the mutation's output matches a defined type. ```python import graphene class CreatePerson(graphene.Mutation): class Arguments: name = graphene.String() Output = Person def mutate(root, info, name): return Person(name=name) ``` -------------------------------- ### Execute Query with Variables Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/execute.rst Pass variables to a query using the `variables` parameter. This is useful for parameterized queries, especially when dealing with required arguments. ```python from graphene import ObjectType, Field, ID, Schema class Query(ObjectType): user = Field(User, id=ID(required=True)) def resolve_user(root, info, id): return get_user_by_id(id) schema = Schema(Query) result = schema.execute( ''' query getUser($id: ID) { user(id: $id) { id firstName lastName } } ''', variables={'id': 12}, ) ``` -------------------------------- ### Set default argument value in Graphene schema Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Illustrates setting a default value for an argument directly within the GraphQL schema definition using Graphene's `default_value`. ```python from graphene import ObjectType, String class Query(ObjectType): hello = String( required=True, name=String(default_value='World') ) def resolve_hello(parent, info, name): return f'Hello, {name}!' ``` -------------------------------- ### Integrate DataLoader with Graphene User Type Source: https://github.com/graphql-python/graphene/blob/master/docs/execution/dataloader.rst Define a Graphene ObjectType for User and use DataLoader's load and load_many methods within the resolve methods to efficiently fetch related data. ```python class User(graphene.ObjectType): name = graphene.String() best_friend = graphene.Field(lambda: User) friends = graphene.List(lambda: User) async def resolve_best_friend(root, info): return await user_loader.load(root.best_friend_id) async def resolve_friends(root, info): return await user_loader.load_many(root.friend_ids) ``` -------------------------------- ### Default Resolver Behavior Source: https://github.com/graphql-python/graphene/blob/master/docs/types/objecttypes.rst Illustrates Graphene's default resolver when no explicit resolver is defined for a field. It shows how the default resolver accesses attributes from a parent object or keys from a parent dictionary. ```python from collections import namedtuple from graphene import ObjectType, String, Field, Schema PersonValueObject = namedtuple("Person", ["first_name", "last_name"]) class Person(ObjectType): first_name = String() last_name = String() class Query(ObjectType): me = Field(Person) my_best_friend = Field(Person) def resolve_me(parent, info): # always pass an object for `me` field return PersonValueObject(first_name="Luke", last_name="Skywalker") def resolve_my_best_friend(parent, info): # always pass a dictionary for `my_best_fiend_field` return {"first_name": "R2", "last_name": "D2"} schema = Schema(query=Query) result = schema.execute(''' { me { firstName lastName } myBestFriend { firstName lastName } } ''') # With default resolvers we can resolve attributes from an object.. assert result.data["me"] == {"firstName": "Luke", "lastName": "Skywalker"} # With default resolvers, we can also resolve keys from a dictionary.. assert result.data["myBestFriend"] == {"firstName": "R2", "lastName": "D2"} ``` -------------------------------- ### GraphQL Edges with Cursor and Node Source: https://github.com/graphql-python/graphene/wiki/Relay-Pagination-example Shows the structure of the 'edges' array in a paginated GraphQL response, where each edge contains a cursor and the node data. ```graphql edges { cursor node { } } ```