如何使用Fauna构建PythonRESTAPI并将其部署到DigitalOcean应用平台

来自菜鸟教程
跳转至:导航、​搜索

介绍

许多开发人员没有时间或经验为其应用程序设置和管理基础架构。 为了赶上最后期限并降低成本,开发人员需要找到能够让他们尽可能快速高效地将应用程序部署到云端的解决方案,从而专注于编写代码并向客户交付新功能。 DigitalOcean 的 App PlatformFauna 共同提供了这种能力。

DigitalOcean App Platform 是一种平台即服务 (PaaS),它抽象了运行您的应用程序的基础设施。 它还允许您通过将代码推送到 Git 分支来部署应用程序。

Fauna 是一个强大的数据层,适用于任何规模的应用程序。 正如您将在本教程中看到的,使用 Fauna,您可以快速启动并运行数据库,而无需担心数据库操作。

这两个解决方案一起让您专注于您的应用程序,而不是管理您的基础设施。

在本教程中,您将使用 Flask 框架编写一个最小的 REST API,将 Fauna 与 Python 集成。 然后,您将从 Git 存储库将 API 部署到 DigitalOcean 的应用平台。API 将包括:

  • 用于在 Users 集合中创建用户的公共 /signup POST 端点。
  • 一个公共的 /login POST 端点,用于对 Users 集合中的文档进行身份验证。
  • 一个私有的 /things GET 端点,用于从 Things 集合中获取 Fauna 文档列表。

完成的 Python 项目可在 这个 Github 存储库 上找到。

先决条件

在开始本教程之前,您需要:

第 1 步 — 设置动物数据库

在第一步中,您将配置一个 Fauna 数据库并为 API 创建集合。 Fauna 是 基于文档的数据库 而不是传统的基于表的关系数据库。 Fauna 将您的数据存储在文档和集合中,它们是文档组。

要创建集合,您将使用 Fauna 的本地查询语言 FQL 执行查询。 FQL 是一种表达力强且功能强大的查询语言,可让您访问 Fauna 的全部功能。

要开始,登录到 Fauna 的仪表板。 登录后,点击顶部的【X31X】创建数据库【X50X】按钮。

New Database 表单中,使用 PYTHON_API 作为数据库名称:

保留 使用演示数据预填充 未选中。 按保存按钮。

创建数据库后,您将看到数据库的主页部分:

您现在要创建两个集合:

  • Users 集合将存储带有身份验证信息的文档。
  • Things 集合用于存储一些模拟数据以测试您的 API。

要创建这些集合,您将在仪表板的 shell 中执行一些 FQL 查询。 从左侧的主仪表板菜单访问 shell:

在 shell 的底部面板中编写以下 FQL 查询,使用 CreateCollection 函数创建一个名为 Things 的集合:

CreateCollection({name: "Things"})

运行查询 按钮。 您将在 shell 的顶部面板中获得与此类似的结果:

{
  ref: Collection("Things"),
  ts: 1614805457170000,
  history_days: 30,
  name: "Things"
}

结果显示四个字段:

  • ref 是对集合本身的引用。
  • ts 是其创建的时间戳,以微秒为单位。
  • history_days 是 Fauna 将保留文档更改的更改时间。
  • name 是集合名称。

接下来,使用以下查询创建 Users 集合:

CreateCollection({name: "Users"})

现在这两个集合都已就位,您将创建您的第一个文档。

Fauna 中的文档有点类似于 JSON 对象。 文档可以存储字符串、数字和数组,但它们也可以使用 Fauna 数据类型。 常见的 Fauna 类型是 Ref,它表示对集合中文档的引用。

Create 函数在指定集合中创建一个新文档。 运行以下查询以在 Things 集合中创建一个包含两个字段的文档:

Create(
  Collection("Things"),
  {
    data: {
      name: "Banana",
      color: "Yellow"
    }
  }
)

运行该查询后,Fauna 将返回创建的文档:

{
  ref: Ref(Collection("Things"), "292079274901373446"),
  ts: 1614807352895000,
  data: {
    name: "Banana",
    color: "Yellow"
  }
}

结果显示以下字段:

  • Ref 类型的 ref 是对 ID 为 292079274901373446Things 集合中此文档的引用。 请注意,您的文档将具有不同的 ID。
  • ts 是其创建的时间戳,以微秒为单位。
  • data 是文档的实际内容。

此结果与您在创建集合时得到的结果相似。 这是因为 Fauna 中的所有实体(集合、索引、角色等)实际上都存储为文档。

要读取文档,请使用接受文档引用的 Get 函数。 使用文档的参考运行 Get 查询:

Get(Ref(Collection("Things"), "292079274901373446"))

结果是完整的文档:

{
  ref: Ref(Collection("Things"), "292079274901373446"),
  ts: 1614807352895000,
  data: {
    name: "Banana",
    color: "Yellow"
  }
}

要获取存储在集合中的文档的所有引用,请将 Documents 函数与 Paginate 函数一起使用:

Paginate(Documents(Collection("Things")))

此查询返回一个包含引用数组的页面:

{
  data: [Ref(Collection("Things"), "292079274901373446")]
}

要获取实际文档而不是引用,请使用 Map 遍历引用。 然后使用 Lambda (匿名函数)遍历引用数组和 Get 每个引用:

Map(
  Paginate(Documents(Collection("Things"))),
  Lambda("ref", Get(Var("ref")))
)

结果是一个包含完整文档的数组:

{
  data: [
    {
      ref: Ref(Collection("Things"), "292079274901373446"),
      ts: 1614807352895000,
      data: {
        name: "Banana",
        color: "Yellow"
      }
    }
  ]
}

您现在要创建 Users_by_username 索引。 您通常使用 Fauna 中的索引来对数据进行分类、过滤和排序,但您也可以将它们用于其他目的,例如强制执行唯一约束。

Users_by_username 索引将通过用户的 username 查找用户,并强制执行唯一约束以防止两个文档具有相同的 username

在 shell 中执行此代码以创建索引:

CreateIndex({
  name: "Users_by_username",
  source: Collection("Users"),
  terms: [{ field: ["data", "username"] }],
  unique: true
})

CreateIndex 函数将使用配置的设置创建索引:

  • name 是索引的名称。
  • source 是索引将从中索引数据的集合(或多个集合)。
  • terms 是您在使用它来查找文档时将传递给该索引的搜索/过滤条件。
  • unique 表示索引值将是唯一的。 在此示例中,Users 集合中文档的 username 属性将被强制为唯一。

要测试索引,请通过在 Fauna shell 中运行以下代码,在 Users 集合中创建一个新文档:

Create(
  Collection("Users"),
  {
    data: {
      username: "sammy"
    }
  }
)

您将看到如下结果:

{
  ref: Ref(Collection("Users"), "292085174927098368"),
  ts: 1614812979580000,
  data: {
    username: "sammy"
  }
}

现在尝试创建一个具有相同 username 值的文档:

Create(
  Collection("Users"),
  {
    data: {
      username: "sammy"
    }
  }
)

您现在会收到一个错误:

Error: [
  {
    "position": [
      "create"
    ],
    "code": "instance not unique",
    "description": "document is not unique."
  }
]

现在索引已经到位,您可以查询它并获取单个文档。 在 shell 中运行此代码以使用索引获取 sammy 用户:

Get(
  Match(
    Index("Users_by_username"),
    "sammy"
  )
)

以下是它的工作原理:

  • Index 返回对 Users_by_username 索引的引用。
  • Match 返回对匹配文档的引用(具有 username 且值为 sammy 的文档)。
  • Get 获取由 Match 返回的引用,并获取实际文档。

此查询的结果将是:

{
  ref: Ref(Collection("Users"), "292085174927098368"),
  ts: 1614812979580000,
  data: {
    username: "sammy"
  }
}

通过将其引用传递给 Delete 函数来删除此测试文档:

Delete(Ref(Collection("Users"), "292085174927098368"))

接下来,您将为 Fauna 配置安全设置,以便您可以从代码连接到它。

第 2 步 — 配置服务器密钥和授权规则

在此步骤中,您将创建一个服务器密钥,您的 Python 应用程序将使用该密钥与 Fauna 进行通信。 然后,您将配置访问权限。

要创建密钥,请使用左侧的主菜单转到 Fauna 仪表板的 Security 部分。 一到那里:

  1. 新密钥 按钮。
  2. 选择 Server 角色。
  3. 保存

保存后,仪表板将向您显示密钥的秘密。 将秘密保存在安全的地方,永远不要将其提交到您的 Git 存储库。

WarningServer 角色是无所不能的,任何拥有此机密的人都可以完全访问您的数据库。 顾名思义,这是受信任的服务器应用程序通常使用的角色,尽管也可以创建具有有限权限的自定义角色的密钥。 当您创建生产应用程序时,您会希望扮演一个更具限制性的角色。


默认情况下,Fauna 中的所有内容都是私有的,因此您现在将创建一个新角色以允许登录用户从 Things 集合中读取文档。

在仪表板的 Security 部分,转到 Roles,并创建一个名为 User 的新自定义角色。

Collections 下拉列表中,添加 Things 集合并按下 Read 权限,使其显示绿色复选标记:

在保存角色之前,转到 Membership 选项卡并将 Users 集合添加到角色:

您现在可以通过按下 保存 按钮来保存您的 User 自定义角色。

现在,任何从 Users 集合中的文档登录的用户都可以从 Things 集合中读取任何文档。

有了身份验证和授权,现在让我们创建将与 Fauna 对话的 Python API。

第 3 步 — 构建 Python 应用程序

在这一步中,您将使用 Flask 框架构建一个小型 REST API,并使用 Python 编写 FQL 查询,使用 Fauna 驱动程序连接到您的 Fauna 数据库。

首先,创建一个项目文件夹并从您的终端访问它。

首先安装 Flask:

pip install flask

然后安装 Fauna Python 驱动程序:

pip install faunadb

在您的项目文件夹中,创建文件 main.py 并将以下代码添加到文件中,其中添加了必要的导入、FAUNA_SECRET 环境变量和 Flask 应用程序的基本配置:

主文件

import os
FAUNA_SECRET = os.environ.get('FAUNA_SECRET')

import flask
from flask import request

import faunadb
from faunadb import query as q
from faunadb.client import FaunaClient

app = flask.Flask(__name__)
app.config["DEBUG"] = True

FAUNA_SECRET 环境变量将携带您之前创建的服务器密码。 为了能够在本地或云中运行此应用程序,需要注入此变量。 没有它,应用程序将无法连接到 Fauna。 您将在启动应用程序时提供此环境变量。

现在将 /signup 路由添加到 main.py 文件。 这将在 Users 集合中创建新文档:

主文件

@app.route('/signup', methods=['POST'])
def signup():

    body = request.json
    client = FaunaClient(secret=FAUNA_SECRET)

    try:
        result = client.query(
            q.create(
                q.collection("Users"),
                {
                    "data": {
                        "username": body["username"]
                    },
                    "credentials": {
                        "password": body["password"]
                    }
                }
            )
        )

        return {
            "userId": result['ref'].id()
        }

    except faunadb.errors.BadRequest as exception:
        error = exception.errors[0]
        return {
            "code": error.code,
            "description": error.description
        }, 409

请注意,Fauna 客户端正在使用服务器密钥对每个请求进行实例化:

主文件

...
client = FaunaClient(secret=FAUNA_SECRET)
...

一旦用户登录,API 将代表每个用户使用不同的秘密执行查询,这就是为什么在每个请求上实例化客户端是有意义的。

与其他数据库不同,Fauna 客户端不维护持久连接。 在外界看来,Fauna 的行为就像一个 API; 每个查询都是一个 HTTP 请求。

客户端准备就绪后,将执行 FQL 查询,在 Users 集合中创建一个新文档。 每个 Fauna 驱动程序都将惯用语法转换为 FQL 语句。 在此路线中,您添加了以下查询:

主文件

...
q.create(
    q.collection("Users"),
    {
        "data": {
            "user": json["user"]
        },
        "credentials": {
            "password": json["password"]
        }
    }
)
...

这是这个查询在原生 FQL 中的样子:

Create(
    Collection("Users"),
    {
        "data": {
            "user": "sammy"
        },
        "credentials": {
            "password": "secretpassword"
        }
    }
)

除了文档数据之外,您还添加了带有用户密码的 credentials 配置。 文档的这一部分是完全私密的。 之后您将永远无法读取文档的凭据。 在使用 Fauna 的身份验证系统时,不可能错误地暴露用户的密码。

最后,如果已经有相同用户名的用户,则会引发 faunadb.errors.BadRequest 异常,并向客户端返回带有错误信息的 409 响应。

接下来,在 main.py 文件中添加 /login 路由来验证用户和密码。 这遵循与前一个示例类似的模式; 您使用 Fauna 连接执行查询,如果身份验证失败,则引发 faunadb.errors.BadRequest 异常并返回带有错误信息的 401 响应。 将此代码添加到 main.py

主文件

@app.route('/login', methods=['POST'])
def login():

    body = request.json
    client = FaunaClient(secret=FAUNA_SECRET)

    try:
        result = client.query(
            q.login(
                q.match(
                    q.index("Users_by_username"),
                    body["username"]
                ),
                {"password": body["password"]}
            )
        )

        return {
            "secret": result['secret']
        }

    except faunadb.errors.BadRequest as exception:
        error = exception.errors[0]
        return {
            "code": error.code,
            "description": error.description
        }, 401

这是用于使用 Fauna 对用户进行身份验证的 FQL 查询:

主文件

q.login(
    q.match(
        q.index("Users_by_username"),
        body["username"]
    ),
    {"password": body["password"]}
)

这是这个查询在原生 FQL 中的样子:

Login(
    Match(
        Index("Users_by_username"),
        "sammy"
    ),
    {"password": "secretpassword"}
)

Match 使用我们之前创建的 Users_by_username 索引返回对文档的引用。

如果提供的密码与引用的文档匹配,Login 将创建一个新令牌并返回具有以下键的字典:

  • ref 引用新文档的令牌。
  • ts 带有交易的时间戳。
  • instance 引用用于进行身份验证的文档。
  • secret 带有令牌的秘密,将用于对 Fauna 进行进一步查询。

如果您在 Fauna 仪表板的 shell 中运行该 FQL 查询,您将看到类似于以下内容的内容:

{
  ref: Ref(Ref("tokens"), "292001047221633538"),
  ts: 1614732749110000,
  instance: Ref(Collection("Users"), "291901454585692675"),
  secret: "fnEEDWVnxbACAgQNBIxMIAIIKq1E5xvPPdGwQ_zUFH4F5Dl0neg"
}

根据项目的安全要求,您必须决定如何处理令牌的秘密。 如果此 API 旨在供浏览器使用,您可能会在安全 cookie 或加密的 JSON Web 令牌 (JWT) 中返回秘密。 或者,您可以将其作为会话数据存储在其他地方,例如 Redis 实例。 出于本演示的目的,您在 HTTP 响应的正文中返回它:

最后,将这段代码添加到 main.py 中,这将启动 Flask 应用程序:

主文件

app.run(host=os.getenv('IP', '0.0.0.0'), port=int(os.getenv('PORT', 8080)))

指定 0.0.0.0 地址很重要。 一旦部署到云端,该应用程序将在 Docker 容器中运行。 如果它在 127.0.0.1 上运行,它将无法接收来自远程客户端的请求,这是 Flask 应用程序的默认地址。

这是到目前为止完整的 main.py 文件:

主文件

import os
FAUNA_SECRET = os.environ.get('FAUNA_SECRET')

import flask
from flask import request

import faunadb
from faunadb import query as q
from faunadb.client import FaunaClient

app = flask.Flask(__name__)
app.config["DEBUG"] = True

@app.route('/signup', methods=['POST'])
def signup():

    body = request.json
    client = FaunaClient(secret=FAUNA_SECRET)

    try:
        result = client.query(
            q.create(
                q.collection("Users"),
                {
                    "data": {
                        "username": body["username"]
                    },
                    "credentials": {
                        "password": body["password"]
                    }
                }
            )
        )

        return {
            "userId": result['ref'].id()
        }

    except faunadb.errors.BadRequest as exception:
        error = exception.errors[0]
        return {
            "code": error.code,
            "description": error.description
        }, 409

@app.route('/login', methods=['POST'])
def login():

    body = request.json
    client = FaunaClient(secret=FAUNA_SECRET)

    try:
        result = client.query(
            q.login(
                q.match(
                    q.index("Users_by_username"),
                    body["username"]
                ),
                {"password": body["password"]}
            )
        )

        return {
            "secret": result['secret']
        }

    except faunadb.errors.BadRequest as exception:
        error = exception.errors[0]
        return {
            "code": error.code,
            "description": error.description
        }, 401

app.run(host=os.getenv('IP', '0.0.0.0'), port=int(os.getenv('PORT', 8080)))

保存文件。

要从终端本地启动此服务器,请使用以下命令和 FAUNA_SECRET 环境变量以及您在创建服务器密钥时获得的密钥:

FAUNA_SECRET=your_fauna_server_secret python main.py

触发该命令后,Flask 将显示警告,通知您它正在与开发 WSGI 服务器一起运行。 这对于本演示来说很好,因此您可以放心地忽略此警告。

通过使用 curl 命令发出 HTTP 请求来测试您的 API。 打开一个新的终端窗口并运行以下命令:

使用以下命令创建用户:

curl -i -d '{"user":"sammy", "password": "secretpassword"}' -H 'Content-Type: application/json' -X POST http://0.0.0.0:8080/signup

您将看到以下响应,表明用户创建成功:

HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 37
Server: Werkzeug/1.0.1 Python/3.9.2
Date: Thu, 04 Mar 2021 01:00:47 GMT

{
  "userId": "292092166117786112"
}

现在使用以下命令验证该用户:

curl -i -d '{"user":"sammy", "password": "secretpassword"}' -H 'Content-Type: application/json' -X POST http://0.0.0.0:8080/login

你会得到这个成功的响应:

HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 70
Server: Werkzeug/1.0.1 Python/3.9.2
Date: Thu, 04 Mar 2021 01:01:19 GMT

{
  "secret": "fnEEDbhO3jACAAQNBIxMIAIIOlDxujk-VJShnnhkZkCUPKIHxbc"
}

关闭运行 curl 命令的终端窗口,然后切换回运行 Python 服务器的终端。 按 CTRL+C 停止服务器。

现在应用程序正在运行,我们将添加一个需要对用户进行身份验证的私有端点。

第 4 步 — 添加私有端点

在此步骤中,您将向 API 添加一个私有端点,这将要求首先对用户进行身份验证。

首先,在 main.py 文件中新建一条路由。 此路由将响应 /things 端点。 将它放在使用 app.run() 方法启动服务器的行上方:

主文件

@app.route('/things', methods=['GET'])
def things():

接下来,在 /things 路由中,实例化 Fauna 客户端:

主文件

    userSecret = request.headers.get('fauna-user-secret')
    client = FaunaClient(secret=userSecret)

该路由不使用服务器密码,而是使用来自 fauna-user-secret HTTP 标头的用户密码,该标头用于实例化 Fauna 客户端。 通过使用用户的机密而不是服务器机密,FQL 查询现在将受制于我们之前在仪表板中配置的授权规则。

然后将此 try 块添加到路由以执行查询:

主文件

    try:
        result = client.query(
            q.map_(
                q.lambda_("ref", q.get(q.var("ref"))),
                q.paginate(q.documents(q.collection("Things")))
            )
        )

        things = map(
            lambda doc: {
                "id": doc["ref"].id(),
                "name": doc["data"]["name"],
                "color": doc["data"]["color"]
            },
            result["data"]
        )

        return {
            "things": list(things)
        }

这将执行 FQL 查询并将 Fauna 响应解析为可序列化类型,然后在 HTTP 响应正文中作为 JSON 字符串返回。

最后,将这个 except 块添加到路由中:

主文件

    except faunadb.errors.Unauthorized as exception:
        error = exception.errors[0]
        return {
            "code": error.code,
            "description": error.description
        }, 401

如果请求不包含有效密钥,则会引发 faunadb.errors.Unauthorized 异常并返回带有错误信息的 401 响应。

这是 /things 路线的完整代码:

主文件

@app.route('/things', methods=['GET'])
def things():

    userSecret = request.headers.get('fauna-user-secret')
    client = FaunaClient(secret=userSecret)

    try:
        result = client.query(
            q.map_(
                q.lambda_("ref", q.get(q.var("ref"))),
                q.paginate(q.documents(q.collection("Things")))
            )
        )

        things = map(
            lambda doc: {
                "id": doc["ref"].id(),
                "name": doc["data"]["name"],
                "color": doc["data"]["color"]
            },
            result["data"]
        )

        return {
            "things": list(things)
        }

    except faunadb.errors.Unauthorized as exception:
        error = exception.errors[0]
        return {
            "code": error.code,
            "description": error.description
        }, 401

保存文件并再次运行您的服务器:

FAUNA_SECRET=your_fauna_server_secret python main.py

要测试此端点,首先通过使用有效凭据进行身份验证来获取密钥。 打开一个新的终端窗口并执行这个 curl 命令:

curl -i -d '{"username":"sammy", "password": "secretpassword"}' -H 'Content-Type: application/json' -X POST http://0.0.0.0:8080/login

此命令返回成功响应,尽管 secret 的值会有所不同:

HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 70
Server: Werkzeug/1.0.1 Python/3.9.2
Date: Thu, 04 Mar 2021 01:01:19 GMT

{
  "secret": "fnEEDb...."
}

现在 hen 使用秘密向 /things 发出 GET 请求:

curl -i -H 'fauna-user-secret: fnEEDb...' -X GET http://0.0.0.0:8080/things

你会得到另一个成功的响应:

HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 118
Server: Werkzeug/1.0.1 Python/3.9.2
Date: Thu, 04 Mar 2021 01:14:49 GMT

{
  "things": [
    {
      "color": "Yellow",
      "id": "292079274901373446",
      "name": "Banana"
    }
  ]
}

关闭运行 curl 命令的终端窗口。 返回到您的服务器正在运行的窗口并使用 CTRL+C 停止服务器。

现在您有了一个可以工作的应用程序,您就可以部署它了。

第 4 步 — 部署到 DigitalOcean

在本教程的最后一步中,您将在 App Platform 上创建一个应用程序并从 GitHub 存储库部署它。

在将项目推送到 Git 存储库之前,请确保在项目文件夹中运行以下命令:

pip freeze > requirements.txt

这将创建一个 requirements.txt 文件,其中包含部署应用程序后需要安装的依赖项列表。

现在将您的项目目录初始化为 Git 存储库:

git init

现在执行以下命令将文件添加到您的存储库:

git add .

这将添加当前目录中的所有文件。

添加文件后,进行初始提交:

git commit -m "Initial version of the site"

您的文件将提交。

打开浏览器并导航到 GitHub,使用您的个人资料登录,然后创建一个名为 sharkopedia 的新存储库。 创建一个没有 README 或许可证文件的空存储库。

创建存储库后,返回命令行将本地文件推送到 GitHub。

首先,将 GitHub 添加为远程存储库:

git remote add origin https://github.com/your_username/sharkopedia

接下来,重命名默认分支 main,以匹配 GitHub 的期望:

git branch -M main

最后,将你的 main 分支推送到 GitHub 的 main 分支:

git push -u origin main

您的文件将被传输。 您现在已准备好部署您的应用程序。

注意:为了能够在App Platform上创建应用程序,您首先需要将付款方式添加到您的DigitalOcean帐户。

该应用程序将在一个每月花费 5 美元的容器上运行,尽管测试它只需要几美分。 完成后不要忘记删除应用程序,否则您将继续被收费。


转到 DigitalOcean 仪表板的 Apps 部分,然后单击 Launch Your App

选择部署源。 您需要授权 DigitalOcean 才能阅读您的 Github 存储库。 授权访问后,选择包含您的 Python 项目的存储库和包含您要部署的应用程序版本的分支:

此时,App Platform 将确定您的项目使用 Python,并让您配置一些应用程序选项:

设置以下选项

  • 确保 TypeWeb Service
  • 使用您的服务器密码创建一个 FAUNA_SECRET 环境变量。
  • 运行命令 设置为 python main.py
  • HTTP 端口 设置为 8080

接下来,为您的应用输入一个名称并选择一个部署区域:

接下来,选择每月 5 美元的 Basic 计划和 Basic Size

之后,向下滚动并单击 Launch Your App

完成应用程序的配置后,将创建一个容器并将其与您的应用程序一起部署。 首次初始化需要几分钟,但后续部署会快得多。

在应用程序的仪表板中,您将看到一个绿色复选标记,表示部署过程已成功完成:

您现在将能够对提供的应用程序域执行 HTTP 请求。 在终端中执行以下命令,将 your_app_name 替换为您的实际应用名称,以返回 sammy 用户的新密钥:

curl -i -d '{"user":"sammy", "password": "secretpassword"}' -H 'Content-Type: application/json' -X POST https://your_app_name.ondigitalocean.app/login

您将收到类似于以下内容的响应:

HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 70
Server: Werkzeug/1.0.1 Python/3.9.2
Date: Thu, 04 Mar 2021 01:01:19 GMT

{
  "secret": "fnAADbhO3jACEEQNBIxMIAOOIlDxujk-VJShnnhkZkCUPKIskdjfh"
}

您的应用程序现在已在 Digital Ocean 上启动并运行。

结论

在本教程中,您使用 Fauna 作为数据层创建了一个 Python REST API,并将其部署到 DigitalOcean 应用平台。

要继续了解 Fauna 并深入了解 FQL,请查看 Fauna 文档