Building GraphQL queries with Python


+
=



The problem
The problem

The problem

query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
},
pageInfo {
startCursor
endCursor
}
}
}
The problem
query {
bookings (customerId: "81de7115-b0b2-49ad-ac03-3a56a488ebcd", orderBy: "startDate") {
edges {
node {
startDate
endDate
buildingRef
}
cursor
},
pageInfo {
startCursor
endCursor
hasNextPage
}
}
}
The problem
But with Python... π€·ββοΈ
query {
bookings (customerId: "81de7115-b0b2-49ad-ac03-3a56a488ebcd", orderBy: "startDate") {
edges {
node {
startDate
endDate
buildingRef
}
cursor
},
pageInfo {
startCursor
endCursor
hasNextPage
}
}
}
The solutionπ‘
The solutionπ‘
Simple GraphQL Client
The solutionπ‘
Simple GraphQL Client
(the one with most stars on GitHub β)
(the most sophisticated one π§ββοΈ)
sgqlc overview
-
sgqlc.types - int, str, bool, etc.
-
sgqlc.types.datetime - date, time, datetime
-
sgqlc.types.relay - Node, Connection
-
sgqlc.operation - Query (the main entrypoint)
-
sgqlc.endpoint.http - HTTP wrapper
sgqlc overview
-
sgqlc.types
-
sgqlc.types.datetime
-
sgqlc.types.relay
-
sgqlc.operation
-
sgqlc.endpoint.http
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
},
pageInfo {
...
}
}
}
Everything is a type, there are just various abstractions throughout the package.
sgqlc overview
-
sgqlc.types
-
sgqlc.types.datetime
-
sgqlc.types.relay
-
sgqlc.operation
-
sgqlc.endpoint.http
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
},
pageInfo {
...
}
}
}
sgqlc overview
-
sgqlc.types
-
sgqlc.types.datetime
-
sgqlc.types.relay
-
sgqlc.operation
-
sgqlc.endpoint.http
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
},
pageInfo {
...
}
}
}
Relay types are related to pagination, ordering & filtering.
Relay - edges & nodes
Query
edge
edge
edge
Booking
Booking
Booking
node
node
node
cursor
cursor
cursor
sgqlc overview
-
sgqlc.types
-
sgqlc.types.datetime
-
sgqlc.types.relay
-
sgqlc.operation
-
sgqlc.endpoint.http
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
},
pageInfo {
...
}
}
}
Relay types are related to pagination, ordering & filtering.
sgqlc overview
-
sgqlc.types
-
sgqlc.types.datetime
-
sgqlc.types.relay
-
sgqlc.operation
-
sgqlc.endpoint.http
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
},
pageInfo {
...
}
}
}
Operation == Query (data fetching)
sgqlc overview
-
sgqlc.types
-
sgqlc.types.datetime
-
sgqlc.types.relay
-
sgqlc.operation
-
sgqlc.endpoint.http
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
},
pageInfo {
...
}
}
}
Wraps the GraphQL query to a HTTP POST request with the query attached as a body.
Let's define our node
Let's define our node
# schema.py
from sgqlc.types import String
from sgqlc.types.relay import Node
from sgqlc.types.datetime import DateTime
class BookingNode(Node):
start_date = DateTime
end_date = DateTime
building_ref = String
Let's define our node
# schema.py
from sgqlc.types import String
from sgqlc.types.relay import Node
from sgqlc.types.datetime import DateTime
class BookingNode(Node):
start_date = DateTime
end_date = DateTime
building_ref = String
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
cursor
},
...
}
}
Let's define our node
# schema.py
from sgqlc.types import String
from sgqlc.types.relay import Node
from sgqlc.types.datetime import DateTime
class BookingNode(Node):
start_date = DateTime
end_date = DateTime
building_ref = String
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
cursor
},
...
}
}
The Node model appends the cursor to the node by default.
Let's define our edge
# schema.py
from sgqlc.types import String, Type, Field
from sgqlc.types.relay import Node
from sgqlc.types.datetime import DateTime
class BookingNode(Node):
start_date = DateTime
end_date = DateTime
building_ref = String
class BookingEdge(Type):
node = Field(BookingNode)
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
cursor
},
...
}
}
Let's define our connection
# schema.py
from sgqlc.types import String, Type, Field
from sgqlc.types.relay import Node, Connection
from sgqlc.types.datetime import DateTime
class BookingNode(Node):
start_date = DateTime
end_date = DateTime
building_ref = String
class BookingEdge(Type):
node = Field(BookingNode)
class BookingConnection(Connection):
edges = list_of(BookingEdge)
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
cursor
},
...
}
}
Let's define our connection
# schema.py
from sgqlc.types import String, Type, Field
from sgqlc.types.relay import Node, Connection
from sgqlc.types.datetime import DateTime
class BookingNode(Node):
start_date = DateTime
end_date = DateTime
building_ref = String
class BookingEdge(Type):
node = Field(BookingNode)
class BookingConnection(Connection):
edges = list_of(BookingEdge)
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
cursor
},
pageInfo {
startCursor
endCursor
hasNextPage
}
}
}
The Connection model appends the page info to the query by default.
Let's define our query
# schema.py
from sgqlc.types import String, Type, Field
from sgqlc.types.relay import Node, Connection
from sgqlc.types.datetime import DateTime
class BookingNode(Node):
start_date = DateTime
end_date = DateTime
building_ref = String
class BookingEdge(Type):
node = Field(BookingNode)
class BookingConnection(Connection):
edges = list_of(BookingEdge)
class Query(Type):
bookings = Field(
BookingConnection
)
query {
bookings (...) {
edges {
node {
startDate
endDate
buildingRef
}
cursor
},
pageInfo {
startCursor
endCursor
hasNextPage
}
}
}
Let's add args to the query
from sgqlc.types import String, Type, Field
from sgqlc.types.relay import Node, Connection
from sgqlc.types.datetime import DateTime
class BookingNode(Node):
start_date = DateTime
end_date = DateTime
building_ref = String
class BookingEdge(Type):
node = Field(BookingNode)
class BookingConnection(Connection):
edges = list_of(BookingEdge)
class Query(Type):
bookings = Field(
BookingConnection,
args={
'customer_id': String,
'order_by': String
}
)
query {
... (customerId: "", orderBy: "") {
edges {
node {
startDate
endDate
buildingRef
}
cursor
},
pageInfo {
startCursor
endCursor
hasNextPage
}
}
}
The schema is done ποΈ
from sgqlc.types import String, Type, Field
from sgqlc.types.relay import Node, Connection
from sgqlc.types.datetime import DateTime
class BookingNode(Node):
start_date = DateTime
end_date = DateTime
building_ref = String
class BookingEdge(Type):
node = Field(BookingNode)
class BookingConnection(Connection):
edges = list_of(BookingEdge)
class Query(Type):
bookings = Field(
BookingConnection,
args={
'customer_id': String,
'order_by': String
}
)
query {
... (customerId: "", orderBy: "") {
edges {
node {
startDate
endDate
buildingRef
}
cursor
},
pageInfo {
startCursor
endCursor
hasNextPage
}
}
}
And last, but not least...

And last, but not least...
Let's build the query !π·

Initialize the query
from sgqlc.operation import Operation
from sgqlc.endpoint.http import HTTPEndpoint
from .schema import Query
bookings_query = Operation(Query)
Provide query filter params
from sgqlc.operation import Operation
from sgqlc.endpoint.http import HTTPEndpoint
from .schema import Query
bookings_query = Operation(Query)
bookings_query.bookings(customer_id='...', order_by='...')
Attach edges & nodes
from sgqlc.operation import Operation
from sgqlc.endpoint.http import HTTPEndpoint
from .schema import Query
bookings_query = Operation(Query)
bookings_query.bookings(customer_id='...', order_by='...')
bookings_query.bookings.edges() # Attaches all edges
bookings_query.bookings.edges.node.startDate() # Attaches only a specific edge
Call a GraphQL endpoint
from sgqlc.operation import Operation
from sgqlc.endpoint.http import HTTPEndpoint
from .schema import Query
bookings_query = Operation(Query)
bookings_query.bookings(customer_id='...', order_by='...')
bookings_query.bookings.edges() # Attaches all edges
bookings_query.bookings.edges.node.startDate() # Attaches only a specific edge
endpoint = HTTPEndpoint(url='https://...')
result = endpoint(query=bookings_query) # __call__
from sgqlc.operation import Operation
from sgqlc.endpoint.http import HTTPEndpoint
from .schema import Query
bookings_query = Operation(Query)
bookings_query.bookings(customer_id='...', order_by='...')
bookings_query.bookings.edges() # Attaches all edges
bookings_query.bookings.edges.node.startDate() # Attaches only a specific edge
endpoint = HTTPEndpoint(url='https://...')
result = endpoint(query=bookings_query) # __call__

We got it!π¦ΈββοΈ
But with Python! π
query {
bookings (customerId: "81de7115-b0b2-49ad-ac03-3a56a488ebcd", orderBy: "startDate") {
edges {
node {
startDate
endDate
buildingRef
}
cursor
},
pageInfo {
startCursor
endCursor
hasNextPage
}
}
}
Furthermore
-
first: <number>
-
limit: <number>
-
after: <cursor>
- ...
Q&A π

Building GraphQL queries with Python
By Ventsislav Tashev
Building GraphQL queries with Python
- 1,982