前后端分离简单理解
flask中返回json格式数据
from flask import jsonify # 返回json数据 @app.route('/') def hello_world(): data = { 'msg': 'ok', 'status': '200', } return jsonify(data)
简单前后端分离:
前端页面变成一个静态文件。存放在项目的static/html目录下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Score List</title> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script> $(function (){ $.getJSON("/getscores/", function (data){ console.log(data); var scores = data["scores"]; var $ul = $("#score_container"); for(var i=0; i < scores.length; i++){ var $li = $("<li></li>").html(scores[i]); $ul.append($li); } }) }) </script> </head> <body> <h2>机试成绩表</h2> <ul id="score_container"></ul> </body> </html>
后端只需要返回json数据即可:
@app.route('/getscores/') def get_scores(): data = { 'msg': 'ok', 'status': '200', 'scores': [1,2,3,4,5,6,30,40] } return jsonify(data)
什么是RESTFul?
-
简介
REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。 一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。 REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。遵循restful开发的应用程序接口(API)称为RESTFul API。 RESTFul的接口都是围绕资源以及对资源的各种动作展开的。
-
资源
所谓的资源就是在网络中存在的任意实体,哪怕是一条简单信息。
-
动作
所谓动作就是数据的CURD。在开发者设计良好的前提下,对网络资源的动作都可抽象为对资源的CURD操作。RESTFul对网络的操作抽象为HTTP的GET、POST、PUT、DELETE等请求的方式以完成对资源的增删改查。具体对照如下:
方法 行为 示例 GET 获取资源信息 http://127.0.0.1:5000/source GET 获取指定资源 http://127.0.0.1:5000/source/250 POST 创建新的资源 http://127.0.0.1:5000/source PUT 更新指定资源 http://127.0.0.1:5000/source/250 DELETE 删除指定资源 http://127.0.0.1:5000/source/250 -
数据
通常传输的数据格式都采用JSON,有时也可以通过URL的参数进行传递
-
工具
说明:postman是一款非常好用的API开发测试工具,可以模拟各种请求 提醒:安装包,一路next完成安装,演示一个地址的访问
参考阮一峰大神的博客:http://www.ruanyifeng.com/blog/2011/09/restful.html
理解之后再来看RESTful api开发遵循的原则:http://www.ruanyifeng.com/blog/2014/05/restful_api.html
假如获取电影资源,遵循RESTful api开发原则的代码应该怎么写:
@app.route('/movie/', methods=["GET", "POST", "PUT", "DELETE"]) def movie(): if request.method == "GET": # 获取资源 data = { "m_name": "捉妖记" } return jsonify(data) elif request.method == "POST": data = { "msg": "存储成功" } return jsonify(data) elif request.method == "PUT": data = { "msg": "更新成功" } return jsonify(data) elif request.method == "DELETE": data = { "msg": "删除成功" } return jsonify(data) else: abort(405)
原生实现RESTful
定义一个user模型
class User(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) u_name = db.Column(db.String(16), unique=True) u_password = db.Column(db.String(32)) def to_dict(self): return {"u_name": self.u_name, 'u_password': self.u_password}
实现原生RESTful:
@blue.route("/users/<int:id>/", methods=["GET", "POST", "PUT", "DELETE", "PATCH"]) def users(id): if request.method == "GET": page = int(request.args.get("page", default=1)) per_page = int(request.args.get("per_page", default=3)) users = User.query.paginate(page=page, per_page=per_page, error_out=False).items users_dict = [] for user in users: users_dict.append(user.to_dict()) data = { "message": "ok", "status": "200", "data": users_dict } return jsonify(data) elif request.method == "POST": # 更新或创建 username = request.form.get("username") password = request.form.get("password") data = { "message": "ok", "status": "422" } if not username or not password: data["message"] = "参数不正确" return jsonify(data), 422 user = User() user.u_name = username user.u_password = generate_password(password=password) try: db.session.add(user) db.session.commit() data["status"] = "201" except Exception as e: data["status"] = "901" data["message"] = str(e) return jsonify(data), 422 return jsonify(data), 201 elif request.method == "PUT": username = request.form.get("username") password = request.form.get("password") user = User.query.get(id) user.u_name = username user.u_password = generate_password(password) db.session.add(user) db.session.commit() data = { "message": "update success", } return jsonify(data), 201 elif request.method == "DELETE": user = User.query.get(id) data = { "message": "delete success" } if user: db.session.delete(user) db.session.commit() return jsonify(data), 204 else: data["message"] = "指定数据不存在" return jsonify(data) elif request.method == "PATCH": password = request.form.get("password") user = User.query.get(id) user.u_password = generate_password(password) data = { "messgage": "update success" } db.session.add(user) db.session.commit() return jsonify(data), 201 else: abort(405) def generate_password(password): hash = hashlib.md5() hash.update(password.encode("utf-8")) return hash.hexdigest()
前端只需要根据ajax的方法类型来控制对资源的操作:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>UserLogin</title> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script type="text/javascript"> $(function () { $("button").click(function () { var username = $("#username").val(); var password = $("#password").val(); $.ajax("/users/5/", { datatype: "json", type: "PATCH", data: "username=" + username + "&password=" + password, success: function (data) { console.log(data); } }) }) } ) </script> </head> <body> <span>用户名:</span><input id="username" type="text" placeholder="请输入用户名"> <br> <span>密码:</span> <input id="password" type="password" placeholder="请输入密码"> <br> <button>注册</button> </body> </html>
使用Flask-restful
flask-restuflu中每种资源抽象成类,需要继承自Resource,来看一个最简单的例子,把我们的helloword转化为一个资源:
class Hello(Resource): def get(self): return {"msg": "ok"} def post(self): return {"msg": "create success"}