Python Flask高级编程之RESTFul API前后端分离(学习笔记)

Flask-RESTful是一个强大的Python库,用于构建RESTful APIs。它建立在Flask框架之上,提供了一套简单易用的工具,可以帮助你快速地创建API接口。Flask-RESTful遵循REST原则,支持常见的HTTP请求方法,如GET、POST、PUT和DELETE,并提供了验证、授权、分页等功能。

  • 理解API
  • 理解Restful API
  • 理解装饰器
  • 理解Flask框架
  • 使用Python Flask 实现Restful API

API的理解

API(application programming interfaces),即应用程序编程接口。API由服务器(Server)提供(服务器有各种各样的类型,一般我们浏览网页用到的是web server,即网络服务器),通过API,计算机可以读取、编辑网站数据,就像人类可以加载网页、提交信息等。通俗地,API可以理解为家用电器的插头,用户只提供插座,并执行将插头插入插座的行为,不需要考虑电器内部如何运作。从另外一个角度上讲API是一套协议,规定了与外界的沟通方式:如何发送请求和接受响应。

理解 RESTful API

RESTful API即满足RESTful风格设计的API,RESTful表示的是一种互联网软件架构(以网络为基础的应用软件的架构设计),如果一个架构符合REST原则,就称它为RESTful架构。RESTful架构的特点:

  1. 每一个URI代表一种资源;
  2. 客户端和服务器之间,传递这种资源的某种表现层;把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。
  3. 客户端通过四个HTTP动词,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。

后端的RESTful API指的是在服务器端实现的符合RESTful架构风格的API,它用于提供数据和服务,并且通常被前端或其他服务端所调用。后端的RESTful API包括了资源的定义、URI的设计、HTTP方法的使用以及数据格式等内容。

而前端的RESTful API通常是指在客户端(比如浏览器端、移动端应用)中调用后端RESTful API的方式和规范。前端的RESTful API通常是通过Ajax、Fetch API或者一些库(比如axios)来发起HTTP请求,按照RESTful规范与后端的API进行交互,包括发送GET、POST、PUT、DELETE等请求,处理返回的数据等。

设计 RESTful API

设计 RESTful API 需要遵循一定的规范和原则。下面是一些常见的设计原则:

  • • 使用名词来表示资源,比如 /users/articles 等。
  • • 使用 HTTP 方法来表示对资源的操作,比如 GET、POST、PUT、DELETE 等。
  • • 使用 URL 参数来传递附加信息,比如查询条件、分页信息等。
  • • 使用 HTTP 状态码来表示操作结果,比如 200 表示成功、201 表示创建成功、400 表示请求错误、404 表示资源不存在等。
  • • 使用 JSON 或 XML 格式来传输数据。

下面是一个简单的 RESTful API 设计示例:

GET /users        # 获取所有用户信息
GET /users/1      # 获取指定用户信息
POST /users       # 添加用户
PUT /users/1      # 修改指定用户信息
DELETE /users/1   # 删除指定用户

理解装饰器

为了理解装饰器,应该先做好三个方面的准备:

1. 理解对象

通过变量和对象的关系理解对象,在python中,如果要使用一个变量,不需要提前进行声明,只需要在用的时候,给这个变量赋值即可。如 a=1,整数1 为一个对象,a 是一个引用,利用赋值语句,引用a指向了对象1;这边形象比喻一下:这个过程就相当于"放风筝",变量a就是你手里面的"线",python就跟那根"线"一样,通过引用来接触和拴住天空中的风筝------对象。由于Python一切皆是对象的理念,所以函数也是一个对象。

比如,写一个函数,也可以是说创造了一个函数对象。

python 复制代码
def cal(x,y):
    result=x+y
    return result

这时便是创造了一个叫做cal的函数对象。然后就可以使用了

python 复制代码
cal(1,2)  #直接使用了cal这个函数对象
...........或者.............
calculate=cal  #把一个名为calculate的变量指向cal这个函数对象
calculate(1,2)
2.理解函数带括弧和不带括弧时分别代表的意思

如果只写一个cal(不带扩号),此时的cal仅仅是代表一个函数对象;当写成cal(1,2)时,就是在告诉编辑器说"执行cal这个cal函数"

3.理解可变参数和关键字参数
  • 可变参数

定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。如下,在函数内部,参数numbers接收到的是一个tuple,并且,调用该函数时,可以传入任意个参数,包括0个参数:

python 复制代码
def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum
calc(1,2) # 5
  • 关键字参数

可变参数允许传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。请看示例:

python 复制代码
def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)

>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

现在正式开始理解装饰器了。首先理解为什么需要装饰器呢?

主要原因是装饰器可以起到一个"偷懒"的作用,比如写了很多个简单的函数,现在想知道在运行的时候是哪些函数在执行,并且你又觉得这个没有必要写测试,只是想要很简单的在执行完毕之前给它打印上一句"Start",那该怎么办呢?你可以这样:

python 复制代码
def func_name(arg):
    print 'Start func_name'
    sentence

想想看给每一个函数后面都加上那一句话将是非常的麻烦的。但是有了装饰器就不一样了。

python 复制代码
def log(func):
    def wrapper(*arg, **kw):
        print 'Start%s'%func
        return func(*arg,**kw)
    return wrapper

@log
def func_a(arg):
    pass

@log
def func_b(arg):
    pass

@log
def func_c(arg):
    pass

这段代码是一个简单的装饰器示例,使用了 Python 的装饰器语法。

首先,定义了一个装饰器函数 log ,该函数接受一个函数 func作为参数。装饰器的作用是在函数执行前后打印日志。

  1. def log(func) : 定义了装饰器函数 log,接受一个函数作为参数,这个函数将被装饰。

  2. def wrapper(arg, kw): 在装饰器内部定义了一个内部函数 wrapper ,它接受任意数量的位置参数 arg 和关键字参数 kw 。这里使用arg** 和****kw**来接收任意数量的参数。

  3. print('Start%s' % func): 在函数执行前打印日志信息,使用了**%** 格式化字符串来将 func 的字符串表示插入日志中。

  4. **return func(*arg, kw): 调用被装饰的原始函数 func,并将接收到的参数传递给它。返回原始函数的结果。

  5. 这里使用**@log** 语法将装饰器应用到了三个函数 func_afunc_bfunc_c上。这相当于执行了以下操作:

python 复制代码
func_a = log(func_a)
func_b = log(func_b)
func_c = log(func_c)

这样,每当调用这些函数时,实际上是调用了被装饰后的版本,这些版本在执行前后会打印日志信息。

理解Flask框架:一个小的Flask应用

python 复制代码
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

运行上面代码,在浏览器上输入http://127.0.0.1:5000/,便会看到 Hello World! 字样。

那么,这段代码做了什么?

1.首先导入了Flask类。这个类的实例是WSGI应用程序

2.接下来,我们创建一个该类的实例,第一个参数是应用模块或者包的名称,如果使用单一的模块,应该使用name,因为模块的名称将会因其作为单独应用启动还是作为模块导入而有不同

3.然后,我们使用route()装饰器告诉Flask什么样的URL能够触发我们的函数。

4.这个函数的名字也在生成 URL 时被特定的函数采用,这个函数返回我们想要显示在用户浏览器中的信息。

5.最后使用run()函数来让应用运行在本地服务器上。其中if__name__=='main':确保服务器只会在该脚本被Python解释器直接执行的时候才会运行,而不是作为模块导入的时候。

如果启用了调试支持,服务器会在代码修改后自动重新载入,并在发生错误时提供一个相当有用的调试器。启动调试,app.run(debug=True);并且route()装饰器把一个函数绑定到对应的URL上。如下例子

python 复制代码
@app.route('/')
def index():
    return 'Index Page'

@app.route('/hello')
def hello():
    return 'Hello World'

其中还是可以构造含有动态部分的URL,要给 URL 添加变量部分,可以把这些特殊的字段标记为 <variable_name> , 这个部分将会作为命名参数传递到函数。规则可以用 <converter:variable_name> 指定一个可选的转换器,如下例子。

python 复制代码
@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return 'User %s' % username

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return 'Post %d' % post_id

如果Flask能匹配URL,也是可以生成URL的。用url_for()来给指定的函数构造URL。它接受函数名作为第一个参数,也接受对应 URL 规则的变量部分的命名参数。未知变量部分会添加到 URL 末尾作为查询参数。这里有一些例子:

python 复制代码
from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route('/')
... def index(): pass
...
>>> @app.route('/login')
... def login(): pass
...
>>> @app.route('/user/<username>')
... def profile(username): pass
...
>>> with app.test_request_context():
...  print url_for('index')  #/
...  print url_for('login')   #/login
...  print url_for('login', next='/')  #/login?next=/
...  print url_for('profile', username='John Doe')
...    #/user/John%20Doe

HTTP(与web应用会话的协议)有许多不同的访问URL方法。默认情况下,路由只回应GET请求,但是通过route()装饰器传递methods参数可以改变这个行为。

python 复制代码
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        do_the_login()
    else:
        show_the_login_form()

使用Python Flask 实现Restful API

Flask 是一个轻量级Web框架,可以实现快速的 Web 开发,并且提供了良好的扩展性。另外,Flask 还为实现 Restful API 提供了很多方便的工具,如Flask Restful 和 Flask Restplus 等。Flask 的代码结构简单,上手容易,比 Django 等其他框架更为轻量级,更适合快速迭代。

安装 Flask

首先,我们需要安装 Flask。可以使用 pip 命令来安装:

python 复制代码
pip install flask
创建 Flask 应用

首先,我们需要导入 Flask 模块,并创建一个 Flask 应用实例:

python 复制代码
from flask import Flask

app = Flask(__name__)

这里的 __name__ 参数表示当前模块的名字,Flask 根据这个参数来确定应用的根目录。

定义 API 路由

接下来,我们需要定义 API 的路由和处理函数。在 Flask 中,可以使用 @app.route 装饰器来定义路由:

python 复制代码
@app.route('/users', methods=['GET'])
def get_users():
    return jsonify(users)

这里的 /users 表示路由的路径,methods=['GET'] 表示这个路由只支持 GET 方法。get_users 函数是这个路由的处理函数,它返回一个 JSON 格式的用户列表。

同样的,我们还可以定义其他路由和处理函数,比如获取指定用户信息、添加用户、修改用户信息和删除用户等。

处理请求参数

在 RESTful API 中,客户端通常需要向服务器传递一些参数,比如查询条件、请求体等。在 Flask 中,可以使用 request 对象来访问这些参数:

python 复制代码
user = {'id': request.json['id'], 'name': request.json['name'], 'age': request.json['age']}

这里的 request.json 表示请求体中的 JSON 数据。如果请求体不是 JSON 格式,可以使用 request.form 或 request.args 来获取表单数据或查询参数。

返回 JSON 数据

在 RESTful API 中,通常需要返回 JSON 格式的数据。在 Flask 中,可以使用 jsonify 函数来将 Python 对象转换为 JSON 格式的数据:

python 复制代码
return jsonify(users)

这里的 users 是一个 Python 列表对象,jsonify(users) 将它转换为 JSON 格式的数据,并返回给客户端。

启动应用

最后,我们需要在应用中启动 Flask 服务器:

python 复制代码
if __name__ == '__main__':
    app.run()

这里的 name 参数表示当前模块的名字,app.run() 表示启动 Flask 服务器,默认监听在本地的 5000 端口上。如果需要修改监听地址或端口,可以使用 host 和 port 参数来指定。

编写代码

下面是一个简单的 Flask 应用,它实现了一个简单的 RESTful API,用于获取和修改用户信息:

python 复制代码
from flask import Flask, jsonify, request

app = Flask(__name__)

# 用户数据(模拟数据库)
users = [
    {"id": 1, "name": "Alice", "age": 20},
    {"id": 2, "name": "Bob", "age": 25},
    {"id": 3, "name": "Charlie", "age": 30},
]

# 获取所有用户信息
@app.route('/users', methods=['GET'])
def get_users():
    return jsonify(users)

# 获取指定用户信息
@app.route('/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
    user = next((user for user in users if user['id'] == user_id), None)
    if user:
        return jsonify(user)
    else:
        return jsonify({'error': 'User not found'})

# 添加用户
@app.route('/users', methods=['POST'])
def add_user():
    user = {'id': request.json['id'], 'name': request.json['name'], 'age': request.json['age']}
    users.append(user)
    return jsonify(user)

# 修改用户信息
@app.route('/users/<int:user_id>', methods=['PUT'])
def update_user(user_id):
    user = next((user for user in users if user['id'] == user_id), None)
    if user:
        user['name'] = request.json.get('name', user['name'])
        user['age'] = request.json.get('age', user['age'])
        return jsonify(user)
    else:
        return jsonify({'error': 'User not found'})

# 删除用户
@app.route('/users/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):
    user = next((user for user in users if user['id'] == user_id), None)
    if user:
        users.remove(user)
        return jsonify({'result': True})
    else:
        return jsonify({'error': 'User not found'})

if __name__ == '__main__':
    app.run()
测试 API

启动应用后,我们可以使用 curl 命令或其他工具来测试 API:

python 复制代码
# 获取所有用户信息
curl http://localhost:5000/users

# 获取指定用户信息
curl http://localhost:5000/users/1

# 添加用户
curl -H "Content-Type: application/json" -X POST -d "{\"id\": 4, \"name\": \"David\", \"age\": 35}" http://localhost:5000/users


# 修改用户信息
curl -H "Content-Type: application/json" -X PUT -d "{\"name\": \"Alice Smith\", \"age\": 22}" http://localhost:5000/users/1


# 删除用户
curl -X DELETE http://localhost:5000/users/4

在 Windows 的命令提示符中,需要使用双引号 " 对 JSON 数据进行引用,并且在内部的双引号前面加上反斜杠 \ 进行转义。

参考:​​​​​​​
用Python 的Flask实现 RESTful API(学习篇)

通过Flask框架创建灵活的、可扩展的Web Restful API服务 - 知乎 (zhihu.com)

相关推荐
明月清风徐徐5 分钟前
Scrapy爬取豆瓣电影Top250排行榜
python·selenium·scrapy
theLuckyLong6 分钟前
SpringBoot后端解决跨域问题
spring boot·后端·python
Yongqiang Cheng9 分钟前
Python operator.itemgetter(item) and operator.itemgetter(*items)
python·operator·itemgetter
MavenTalk12 分钟前
Move开发语言在区块链的开发与应用
开发语言·python·rust·区块链·solidity·move
FksLiao24 分钟前
Superset安装
python
L Jiawen31 分钟前
【Python · PyTorch】卷积神经网络(基础概念)
pytorch·python·cnn
goomind36 分钟前
深度学习模型评价指标介绍
人工智能·python·深度学习·计算机视觉
->yjy1 小时前
wordcloud库基本介绍
python
2401_840192271 小时前
python基础大杂烩
linux·开发语言·python
abments1 小时前
JavaScript逆向爬虫教程-------基础篇之常用的编码与加密介绍(python和js实现)
javascript·爬虫·python