Package: ariadne-relay
Ariadne-RelayAriadne-Relay provides a toolset for implementingGraphQLservers
in Python that conform to theRelay specification,
using theAriadnelibrary.The goals of Ariadne-Relay are to:Make building Relay features feel as close as possible to core AriadneMinimize boilerplate for common casesMake it as easy as possible to fully customize and optimize a Relay deploymentInstallationAriadne-Relay can be installed with pip:pip install ariadne-relayQuickstartIf you are not familiar with Ariadne usage in general, theAraidne docsare the best place to start.Here's a variation of the Ariadne quickstart as a Relay implementation:fromdataclassesimportdataclassfromariadneimportgql,InterfaceType,make_executable_schemafromariadne.asgiimportGraphQLfromariadne_relayimportNodeObjectType,RelayQueryType,resolve_node_query# Using a dataclass for Person rather than a dict,# since it works better with a Node implementation@dataclassclassPerson:id:intfirstName:strlastName:strage:inttype_defs=gql("""type Query {node(id: ID!): Nodepeople(after: Stringbefore: Stringfirst: Intlast: Int): PeopleConnection!}interface Node {id: ID!}type PageInfo {hasNextPage: Boolean!hasPreviousPage: Boolean!startCursor: StringendCursor: String}type Person implements Node {id: ID!firstName: StringlastName: Stringage: IntfullName: String}type PersonEdge {cursor: String!node: Person}type PeopleConnection {pageInfo: PageInfo!edges: [PersonEdge]!}""")# A mock data store of peoplepeople_data={"1":Person(id=1,firstName="John",lastName="Doe",age=21),"2":Person(id=2,firstName="Bob",lastName="Boberson",age=24),}# Instead of using Ariadne's QueryType, use the Relay-enabled# RelayQueryType classquery=RelayQueryType()# resolve_node_query is provided as a resolver for Query.node()query.set_field("node",resolve_node_query)# Connection resolvers work exactly like standard Ariadne resolvers,# except they convert the returned value to a connection structure@query.connection("people")defresolve_people(*_):returnlist(people_data.values())# Define the Node interfacenode=InterfaceType("Node")# Add a Node type resolver@node.type_resolverdefresolve_node_type(obj,*_):returnobj.__class__.__name__# Instead of Ariadne's ObjectType, use the Relay-enabled# NodeObjectType class for types that implement Nodeperson=NodeObjectType("Person")# Add an instance_resolver to define how an instance of# this type is retrieved, given an id@person.instance_resolverdefresolve_person_instance(id,*_):returnpeople_data.get(id)@person.field("fullName")defresolve_person_fullname(person,*_):return"%s%s"%(person.firstName,person.lastName)# Create executable GraphQL schemaschema=make_executable_schema(type_defs,node,query,person)# Create an ASGI app using the schema, running in debug modeapp=GraphQL(schema,debug=True)Connection FactoriesThe heavy lifting of generating a connection structure in aRelayObjectType.connection()is performed by the chosen factory.  It is possible to specify a factory of your chosing
by passing it in the call toconnection():@query.connection("people", factory=CustomConnection)ReferenceConnectionThe default that is used whenfactoryis not overridden isReferenceConnection.  This
implementation wrapsgraphql_relay.connection_from_array_slice()and provides the expected
behavior of the Relay reference implementation.SnakeCaseConnectionTheSnakeCaseConnectionfactory provides equivalent functionality toReferenceConnection,
but returns a connection structure with snake-case field names.  This is useful in conjunction
withariadne.snake_case_fallback_resolvers.ConnectionProxyTheConnectionProxyfactory can be used to proxy an already-formed connection structure,
for example a payload that was produced by an external GraphQL endpoint. It simply passes through
the data untouched.Custom FactoriesMany deployments will benefit from customizing the connection factory. One example would be
properly integrating a given ORM like Djano. Other examples might be extending the functionality
of connections, or customizing how cursors are formed. TheBaseConnectionandSnakeCaseBaseConnectionclasses can be useful for this purpose.ContributingPlease seeCONTRIBUTING.md.