GraphQL Support (With Strawberry 🍓)
This is in a very early stage right now. We will have a much more stable version when we have a stable API for Views and View Controllers.
Step 1: Creating a virtualenv
To ensure that there are isolated dependencies, we will use virtual environments.
python3 -m venv venv
Step 2: Activate the virtualenv and install Robyn
source venv/bin/activate
pip install robyn strawberry-graphql
Step 3: Coding the App
from typing import List, Optional
from robyn import Robyn, jsonify
import json
import dataclasses
import strawberry
import strawberry.utils.graphiql
@strawberry.type
class User:
name: str
@strawberry.type
class Query:
@strawberry.field
def user(self) -> Optional[User]:
return User(name="Hello")
schema = strawberry.Schema(Query)
app = Robyn(__file__)
@app.get("/", const=True)
async def get():
return strawberry.utils.graphiql.get_graphiql_html()
@app.post("/")
async def post(request):
body = request.json()
query = body["query"]
variables = body.get("variables", None)
context_value = {"request": request}
root_value = body.get("root_value", None)
operation_name = body.get("operation_name", None)
data = await schema.execute(
query,
variables,
context_value,
root_value,
operation_name,
)
return jsonify(
{
"data": (data.data),
**({"errors": data.errors} if data.errors else {}),
**({"extensions": data.extensions} if data.extensions else {}),
}
)
if __name__ == "__main__":
app.start(port=8080, host="0.0.0.0")
Let us try to decipher the usage line by line.
These statements just import the dependencies.
from typing import List, Optional
from robyn import Robyn, jsonify
import json
import dataclasses
import strawberry
import strawberry.utils.graphiql
Here, we are creating a base User
type with a name
property.
We are then creating a GraphQl Query
that returns the User
.
@strawberry.type
class User:
name: str
@strawberry.type
class Query:
@strawberry.field
def user(self) -> Optional[User]:
return User(name="Hello")
schema = strawberry.Schema(Query)
Now, we are initializing a Robyn app. For us, to serve a GraphQl app, we need to have a get
route to return the GraphiQL(ide)
and then a post route to process the GraphQl
request.
app = Robyn(__file__)
We are populating the html page with the GraphiQL IDE using strawberry
. We are using const=True
to precompute this population. Essentially, making it very fast and bypassing the execution overhead in this get request.
@app.get("/", const=True)
async def get():
return strawberry.utils.graphiql.get_graphiql_html()
Finally, we are getting params(body, query, variables, context_value, root_value, operation_name) from the request
object.
@app.post("/")
async def post(request):
body = request.json()
query = body["query"]
variables = body.get("variables", None)
context_value = {"request": request}
root_value = body.get("root_value", None)
operation_name = body.get("operation_name", None)
data = await schema.execute(
query,
variables,
context_value,
root_value,
operation_name,
)
return jsonify(
{
"data": (data.data),
**({"errors": data.errors} if data.errors else {}),
**({"extensions": data.extensions} if data.extensions else {}),
}
)
The above is the example for just one route. You can do the same for as many as you like. 😃
What's next?
That's all folks. 😄 Keep an eye out for more updates on this page. We will be adding more examples and documentation as we go along.