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"""