Restful API
基础介绍:
? RESTful API(Representational State Transfer)是一种基于HTTP协议设计的应用程序编程接口(API)风格,用于在客户端和服务器之间进行通信。它提供了一组规范和约束,用于创建可伸缩、可靠和可维护的网络服务。
-
路径(URI)设计:
- 使用有意义的路径来表示资源,例如
/users 表示用户资源。 - 遵循路径层次结构,使用斜杠
/ 分隔不同的资源和子资源,例如/users/{id}/orders 表示特定用户的订单资源。 - 避免在路径中使用动词,使用HTTP方法来表示操作类型。
- url链接中,不能有动词,只能有名词。并且对于一些名词,如果出现复数,那么应该在后面加s。
- 使用有意义的路径来表示资源,例如
-
HTTP方法(Verbs):
-
使用适当的HTTP方法来表示对资源的操作:
- GET:从服务器上获取资源。
- POST:在服务器上新创建一个资源。
- PUT:在服务器上更新资源。(客户端提供所有改变后的数据)
- PATCH:在服务器上更新资源。(客户端只提供需要改变的属性)
- DELETE:从服务器上删除资源。
-
合理使用HTTP状态码来表示请求的结果:
-
200 OK 服务器成功响应客户端的请求。 400 INVALID REQUEST 用户发出的请求有错误,服务器没有进行新建或修改数据的操作 401 Unauthorized 用户没有权限访问这个请求 403 Forbidden 因为某些原因禁止访问这个请求 404 NOT FOUND 用户发送的请求的url不存在 406 NOT Acceptable 用户请求不被服务器接收(比如服务器期望客户端发送某个字段,但是没有发送)。 500 Internal server error 服务器内部错误,比如出现了bug
-
-
3.参数传递
在 RESTful API 中,参数传递可以使用不同的方式,包括查询参数(Query Parameters)、路径参数(Path Parameters)、请求体(Request Body)和请求头(Request Headers)。这些不同的方式可以根据具体的需求和语义选择使用。
以下是对每种参数传递方式的简要说明:
- 查询参数(Query Parameters):
- 查询参数是附加在URL末尾的键值对,以
? 开头,多个参数使用& 分隔,例如:/users?name=john&age=25 。 - 查询参数常用于过滤、排序、分页等操作。
- 在服务器端,可以通过解析URL中的查询参数来获取传递的值。
- 查询参数是附加在URL末尾的键值对,以
- 路径参数(Path Parameters):
- 路径参数是包含在URL路径中的变量,由花括号
{} 表示,例如:/users/{id} 。 - 路径参数用于标识特定的资源,如获取特定用户的信息。
- 在服务器端,可以通过解析URL路径来提取路径参数的值。
- 路径参数是包含在URL路径中的变量,由花括号
- 请求体(Request Body):
- 请求体是在HTTP请求中包含的数据,通常使用POST、PUT等方法发送。
- 请求体可以包含结构化数据,如JSON、XML等格式,用于传递更复杂的参数。
- 在服务器端,可以通过解析请求体来获取传递的值。
- 请求头(Request Headers):
- 请求头是包含在HTTP请求头部中的键值对,用于传递元数据和其他信息。
- 请求头可以用于身份验证、内容类型指定等目的。
- 在服务器端,可以通过解析请求头来获取传递的值。
4.错误处理
- 使用适当的HTTP状态码来指示错误,如400表示请求错误、401表示未授权、500表示服务器内部错误等。
- 提供有用的错误信息,帮助客户端识别和解决问题。
案例:
现在给出代码,展示Restful APi 在Flask中的使用:
from flask import Flask, url_for, redirect, request app = Flask(__name__) app.debug = True @app.route('/article/<id>/') def article(id): return '%s article detail' % id @app.route('/login/', methods=['GET', 'POST']) def login(): return 'login page' @app.route('/profile/', methods=['GET', 'POST']) def profile(): name = request.args.get('name') # get请求使用request.args获取参数 if not name: # 如果没有name,说明没有登录,进行重定向,重定向到路由函数login return redirect(url_for('login')) else: return "hello " + name if __name__ == '__main__': # host=0.0.0.0可以让其他电脑也能访问到该网站,port指定访问的端口。默认的host是127.0.0.1,port为5000 app.run(host='0.0.0.0', port=9000)
改进:
class User(Base): # 定义表名为users __tablename__ = 'users' # 将id设置为主键,并且默认是自增长的 id = Column(Integer, primary_key=True, autoincrement=True) # name字段,字符类型,最大的长度是50个字符 name = Column(String(50)) fullname = Column(String(50)) password = Column(String(100)) # 修改内置方法 def __str__(self): return "<User(id='%s',name='%s',fullname='%s',password='%s')>" % ( self.id, self.name, self.fullname, self.password) def to_json(self): # 封装一个可以转化为json格式的函数方法 return {"id": self.id, "name": self.name, "fullname": self.fullname, "password": self.password} @app.route('/users/<id>/', methods=['GET']) def users_get_by_id(id): result = get_user_by_id(id) return jsonify(result.to_json())# 这里的result应该是python的字典类型,最后使用Flask中的jsonify函数修饰一下 @app.route('/users/', methods=['GET']) def users_get(): result = get_user_list() return jsonify([x.to_json() for x in result]) # 使用列表生成式,对列表中的每一个元素都是用 to_json() def get_user_by_id(user_id): Session = sessionmaker(bind=engine) session = Session() return session.query(User).filter(User.id == user_id).all()[0]# 返回一个对象 def get_user_list(): Session = sessionmaker(bind=engine) session = Session() return session.query(User).order_by(User.id).all()
这样改进后,我们发现每一个路由函数的返回结果都是一个json对象,这样也可以作为Ajax请求的地址来实现动态加载数据了。
增删改查:
增加:
def put_user(name, fullname, password): Session = sessionmaker(bind=engine) # 导入引擎 session = Session() # 实例化一个session对象 add_user = User(name=name, fullname=fullname, password=password) session.add(add_user) session.commit() return "ok"
结合一下:
@app.route('/users/' methods=['PUT·]] def users_put(): name = request.args.get('name′) fullname = request.args.get('fullname') password = request.args.get('password') try: result = put_user(name, fullname, password) if result == "ok": return jsonify({ "status": "successful", "content":"add user Successful" ,"function":"put_user" }),208 except Exception as e: return jsonify({"status": "fail","content":e}),500 return 'users page'
修改:
def update_user_by_id(id, name, fullname,password): Session = sessionmaker(bind=engine) session = Session() result =θ if name: result = session.query(User).filter(User.id == id).update({"name": name}) if fullname: result = session.query(User).filter(User.id == id).update({"fullname": fullname}) if password: result = session.query(User) .filter(User.id == id).update({"password": password}) session.commit() session.close() return result
在上面的操作中,如果更新成功,result会被置为1.
@app.route(/users/<id>/*, methods=['PATCH']) def users_patch(id): fullname = request.args.get('fullname') name = request.args.get('name*) password = request.args.get('password') result = update_user_by_id(id, name, fullname, password) if result == 1: return jsonify( {"status": "successful", "content":"update user successful", "function": "update_user_by_id"}), 200 if result == θ: return jsonify( {"status": "fail", "content": "Failed to update user data", "function": "update_user_by_id"}), 408 except Exception as e: return jsonify(f"status": "fail", "Error Name": e.--class-- "content": eb), 500
删除:
def delete_user_by_id(user_id): Session = sessionmaker(bind=engine) session = Session() session.query(User).filter(User.id == user_id).delete() session.commit() session.close() return "ok"
@app.route('/users/<id>/" methods=['DELETE']) def users_delete_by_id(id): try: result = delete_user_by_id(id) if result == "ok": return jsonify({"status": "successful", "content": "delete user successful", "function": "put_user"}), 200 except Exception as e: return jsonify({"status": "fail","content": e}),500
总结:
? 在本篇博客中,我们深入探索了RESTful API的基础知识,并了解了如何在Flask框架中使用它来构建强大的API。我们学习了RESTful原则、路径设计、HTTP方法、参数传递等关键概念,并通过示例代码演示了它们的实际应用。
? 通过使用Flask框架,我们可以轻松地创建和管理RESTful API,从而使我们的应用程序更加灵活、可扩展和易于维护。Flask提供了强大的路由和视图函数机制,使我们能够以简洁的方式定义API的端点和动作。
? 同时,我们还探讨了RESTful API的设计原则,如良好的路径命名、合适的HTTP状态码和错误处理等,这些原则帮助我们设计出易于理解和使用的API接口,提供良好的开发者体验。
? 通过学习和实践RESTful API的基础知识,我们可以构建出符合标准的API,并为前端开发人员、移动应用程序开发人员和其他客户端提供一致、可靠的接口。这不仅有助于提高开发效率,还能促进团队间的协作和集成,为构建现代化、高性能的应用奠定坚实基础。
? 无论是构建简单的API还是复杂的分布式系统,掌握RESTful API的基础知识都是非常重要的。希望本篇博客对您在理解和应用RESTful API方面起到了指导作用,并能为您的API开发之旅提供一些有价值的见解。
? 祝您在使用Flask和构建RESTful API的过程中取得巨大成功!