程序猿阵线联盟-汇总各类技术干货程序员

程序员开发Web项目一个 Python 3 的智能 API 框架

2019-03-16  本文已影响128人  扒皮狼

开始

我们将从安装 API Star 开始。为此实验创建一个虚拟环境是一个好主意。如果你不知道如何创建一个虚拟环境,不要担心,继续往下看。

Python
pip install apistar

(译注:上面的命令是在 Python 3 虚拟环境下使用的)

如果你没有使用虚拟环境或者你的 Python 3 的 pip 名为 pip3,那么使用 pip3 install apistar 代替。

一旦我们安装了这个包,我们就应该可以使用 apistar 命令行工具了。我们可以用它创建一个新项目,让我们在当前目录中创建一个新项目。

Python
apistar new .

现在我们应该创建两个文件:app.py,它包含主应用程序,然后是 test.py,它用于测试。让我们来看看 app.py 文件:

Python

**from** apistar **import** Include, Route

**from** apistar.frameworks.wsgi **import** WSGIApp **as** App

**from** apistar.handlers **import** docs_urls, static_urls

**def** welcome(name=**None**):

    **if** name **is** **None**:

        **return** {'message': 'Welcome to API Star!'}

    **return** {'message': 'Welcome to API Star, %s!'% name}

routes= [

    Route('/', 'GET', welcome),

    Include('/docs', docs_urls),

    Include('/static', static_urls)

]

app= App(routes=routes)

**if** __name__== '__main__':

    app.main()

在我们深入研究代码之前,让我们运行应用程序并查看它是否正常工作。我们在浏览器中输入 http://127.0.0.1:8080/,我们将得到以下响应:

Python

{"message": "Welcome to API Star!"}

如果我们输入:http://127.0.0.1:8080/?name=masnun

Python

{"message": "Welcome to API Star, masnun!"}

同样的,输入 http://127.0.0.1:8080/docs/,我们将看到自动生成的 API 文档。

现在让我们来看看代码。我们有一个 welcome 函数,它接收一个名为 name 的参数,其默认值为 None。API Star 是一个智能的 API 框架。它将尝试在 url 路径或者查询字符串中找到 name 键并将其传递给我们的函数,它还基于其生成 API 文档。这真是太好了,不是吗?

然后,我们创建一个 Route 和 Include 实例的列表,并将列表传递给 App 实例。Route 对象用于定义用户自定义路由。顾名思义,Include 包含了在给定的路径下的其它 url 路径。

路由

路由很简单。当构造 App 实例时,我们需要传递一个列表作为 routes 参数,这个列表应该有我们刚才看到的 Route 或 Include 对象组成。对于 Route,我们传递一个 url 路径,http 方法和可调用的请求处理程序(函数或者其他)。对于 Include 实例,我们传递一个 url 路径和一个 Routes 实例列表。

路径参数

我们可以在花括号内添加一个名称来声明 url 路径参数。例如 /user/{user_id} 定义了一个 url,其中 user_id 是路径参数,或者说是一个将被注入到处理函数(实际上是可调用的)中的变量。这有一个简单的例子:

Python

**from** apistar **import** Route

**from** apistar.frameworks.wsgi **import** WSGIApp **as** App

**def** user_profile(user_id: int):

    **return** {'message': 'Your profile id is: {}'.format(user_id)}

routes= [

    Route('/user/{user_id}', 'GET', user_profile),

]

app= App(routes=routes)

**if** __name__== '__main__':

    app.main()

如果我们访问 http://127.0.0.1:8080/user/23,我们将得到以下响应:

Python

{"message": "Your profile id is: 23"}

但如果我们尝试访问 http://127.0.0.1:8080/user/some_string,它将无法匹配。因为我们定义了 user_profile 函数,且为 user_id 参数添加了一个类型提示。如果它不是整数,则路径不匹配。但是如果我们继续删除类型提示,只使用 user_profile(user_id),它将匹配此 url。这也展示了 API Star 的智能之处和利用类型和好处。

包含/分组路由

有时候将某些 url 组合在一起是有意义的。假设我们有一个处理用户相关功能的 user 模块,将所有与用户相关的 url 分组在 /user 路径下可能会更好。例如 /user/new、/user/1、/user/1/update 等等。我们可以轻松地在单独的模块或包中创建我们的处理程序和路由,然后将它们包含在我们自己的路由中。

让我们创建一个名为 user 的新模块,文件名为 user.py。我们将以下代码放入这个文件:

Python

**from** apistar **import** Route

**def** user_new():

    **return** {"message": "Create a new user"}

**def** user_update(user_id: int):

    **return** {"message": "Update user #{}".format(user_id)}

**def** user_profile(user_id: int):

    **return** {"message": "User Profile for: {}".format(user_id)}

user_routes= [

    Route("/new", "GET", user_new),

    Route("/{user_id}/update", "GET", user_update),

    Route("/{user_id}/profile", "GET", user_profile),

]

现在我们可以从 app 主文件中导入 user_routes,并像这样使用它:

Python

**from** apistar **import** Include

**from** apistar.frameworks.wsgi **import** WSGIApp **as** App

**from** user **import** user_routes

routes= [

    Include("/user", user_routes)

]

app= App(routes=routes)

**if** __name__== '__main__':

    app.main()

现在 /user/new 将委托给 user_new 函数。

访问查询字符串/查询参数

查询参数中传递的任何参数都可以直接注入到处理函数中。比如 url /call?phone=1234,处理函数可以定义一个 phone 参数,它将从查询字符串/查询参数中接收值。如果 url 查询字符串不包含 phone 的值,那么它将得到 None。我们还可以为参数设置一个默认值,如下所示:

Python

**def** welcome(name=**None**):

    **if** name **is** **None**:

        **return** {'message': 'Welcome to API Star!'}

    **return** {'message': 'Welcome to API Star, %s!'% name}

在上面的例子中,我们为 name 设置了一个默认值 None。

注入对象

通过给一个请求程序添加类型提示,我们可以将不同的对象注入到视图中。注入请求相关的对象有助于处理程序直接从内部访问它们。API Star 内置的 http 包中有几个内置对象。我们也可以使用它的类型系统来创建我们自己的自定义对象并将它们注入到我们的函数中。API Star 还根据指定的约束进行数据验证。

让我们定义自己的 User 类型,并将其注入到我们的请求处理程序中:

Python

**from** apistar **import** Include, Route

**from** apistar.frameworks.wsgi **import** WSGIApp **as** App

**from** apistar **import** typesystem

**class** User(typesystem.Object):

    properties= {

    'name': typesystem.string(max_length=100),

    'email': typesystem.string(max_length=100),

    'age': typesystem.integer(maximum=100, minimum=18)

    }

    required= ["name", "age", "email"]

**def** new_user(user: User):

    **return** user

routes= [

    Route('/', 'POST', new_user),

]

app= App(routes=routes)

**if** __name__== '__main__':

    app.main()

现在如果我们发送这样的请求:

Python

curl -X POST \

  http://127.0.0.1:8080/ \

  -H 'Cache-Control: no-cache' \

  -H 'Content-Type: application/json' \

  -d '{"name": "masnun", "email": "masnun@gmail.com", "age": 12}'

猜猜发生了什么?我们得到一个错误,说年龄必须等于或大于 18。类型系允许我们进行智能数据验证。如果我们启用了 docs url,我们还将自动记录这些参数。

发送响应

如果你已经注意到,到目前为止,我们只可以传递一个字典,它将被转换为 JSON 并作为默认返回。但是,我们可以使用 apistar 中的 Response 类来设置状态码和其它任意响应头。这有一个简单的例子:

Python

**from** apistar **import** Route, Response

**from** apistar.frameworks.wsgi **import** WSGIApp **as** App

**def** hello():

    **return** Response(

    content="Hello".encode("utf-8"),

    status=200,

    headers={"X-API-Framework": "API Star"},

    content_type="text/plain"

    )

routes= [

    Route('/', 'GET', hello),

]

app= App(routes=routes)

**if** __name__== '__main__':

    app.main()

它应该返回纯文本响应和一个自定义标响应头。请注意,content 应该是字节,而不是字符串。这就是我编码它的原因。

继续

我刚刚介绍了 API Star 的一些特性,API Star 中还有许多非常酷的东西,我建议通过 Github Readme 文件来了解这个优秀框架所提供的不同功能的更多信息。喜欢的朋友欢迎点击喜欢转发,在评论区也可以留言表述你的意见。

点击居然老师公开课视频播放地址

上一篇下一篇

猜你喜欢

热点阅读