The In Memory Mocking Example#
Overview#
这篇文章介绍了如何用 graphene + flask + flask_graphql 实现一个极简的 GraphQL API. 这个例子中我们没有数据库, 而是用 in-memory 的 Python dict 来模拟数据存储后端.
Note
这个例子是我自己写的, 在网上没有.
Code#
resolver 模块定义了如何从后端中获取数据 (以后进阶的 dataloader 等高级模式都在这个模块中实现)
resolvers.py
1# -*- coding: utf-8 -*-
2
3"""
4This module implements resolvers.
5"""
6
7import typing as T
8
9
10class UserType(T.TypedDict):
11 id: str
12 name: str
13 email: str
14
15
16def resolve_users():
17 # Mock data
18 return [
19 {"id": "1", "name": "Alice", "email": "alice@example.com"},
20 {"id": "2", "name": "Bob", "email": "bob@example.com"},
21 {"id": "3", "name": "Charlie", "email": "charlie@example.com"},
22 ]
23
24
25def resolve_user_by_id(id: str) -> UserType:
26 users = resolve_users()
27 return next((user for user in users if user["id"] == id), None)
schema 模块定义了 GraphQL 的 schema. 这个例子中只有 query 而没有 mutation.
schema.py
1# -*- coding: utf-8 -*-
2
3"""
4This module defines the GraphQL schema.
5"""
6
7import graphene
8from resolvers import resolve_users, resolve_user_by_id
9
10
11class User(graphene.ObjectType):
12 id = graphene.ID()
13 name = graphene.String()
14 email = graphene.String()
15
16
17class Query(graphene.ObjectType):
18 users = graphene.List(User)
19 user = graphene.Field(User, id=graphene.ID(required=True))
20
21 def resolve_users(self, info):
22 print(info)
23 return resolve_users()
24
25 def resolve_user(self, info, id: str):
26 print(info)
27 return resolve_user_by_id(id)
28
29
30schema = graphene.Schema(query=Query)
app 模块将 graphql 的部分和 flask 的部分结合在一起.
app.py
1# -*- coding: utf-8 -*-
2
3"""
4This module defines the GraphQL schema.
5"""
6
7import graphene
8from resolvers import resolve_users, resolve_user_by_id
9
10
11class User(graphene.ObjectType):
12 id = graphene.ID()
13 name = graphene.String()
14 email = graphene.String()
15
16
17class Query(graphene.ObjectType):
18 users = graphene.List(User)
19 user = graphene.Field(User, id=graphene.ID(required=True))
20
21 def resolve_users(self, info):
22 print(info)
23 return resolve_users()
24
25 def resolve_user(self, info, id: str):
26 print(info)
27 return resolve_user_by_id(id)
28
29
30schema = graphene.Schema(query=Query)
Test#
我们写了个简单的脚本, 用于测试在 localhost 运行的 GraphQL API Server.
test.py
1# -*- coding: utf-8 -*-
2
3import requests
4from rich import print as rprint
5
6
7def run_query(query: str) -> dict:
8 res = requests.post(
9 "http://127.0.0.1:5000/graphql",
10 headers={
11 "Content-Type": "application/json",
12 },
13 json={"query": query.strip()},
14 )
15 return res.json()
16
17
18# Put your graphql query here
19query1 = """
20{
21 users {
22 id
23 name
24 email
25 }
26}
27"""
28rprint(run_query(query1))
29"""
30Will print:
31
32{
33 'data': {
34 'users': [
35 {'id': '1', 'name': 'Alice', 'email': 'alice@example.com'},
36 {'id': '2', 'name': 'Bob', 'email': 'bob@example.com'},
37 {'id': '3', 'name': 'Charlie', 'email': 'charlie@example.com'}
38 ]
39 }
40}
41"""
42
43query2 = """
44{
45 user(id: "1") {
46 id
47 name
48 email
49 }
50}
51"""
52rprint(run_query(query2))
53"""
54Will print:
55
56{'data': {'user': {'id': '1', 'name': 'Alice', 'email': 'alice@example.com'}}}
57"""