flask, SQLAlchemy, sqlite3 實現 RESTful API, 同時支持form操做。javascript
前端與後臺的交互都採用json數據格式,原生javascript實現的ajax。其技術要點以下html
JSON.parse(xhr2.responseText)
// 輔助函數:FormData轉化爲json var convert_FormData_to_json = function (formData) { var objData = {}; for (var entry of formData.entries()){ objData[entry[0]] = entry[1]; } return JSON.stringify(objData); };
request.json.get('title', task['title'])
jsonify({'task': replace_id_to_uri(task)})
/myapp
|----app.py
|----/templates
| |----index.html前端
from flask import Flask, jsonify, render_template from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True db = SQLAlchemy(app) # 定義ORM class Todo(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(80), unique=True) description = db.Column(db.String(120), unique=True) done = db.Column(db.Boolean) def __init__(self, title, description, done): self.title = title self.description = description self.done = done def __repr__(self): return '<Todo %r>' % self.title # 建立表格、插入數據 @app.before_first_request def create_db(): # Recreate database each time for demo #db.drop_all() db.create_all() tasks = [Todo('Buy groceries', 'Milk, Cheese, Pizza, Fruit, Tylenol', False), Todo('Learn Python', 'Need to find a good Python tutorial on the web', False), Todo('Mow the lawn', 'Find out some tools', False)] db.session.add_all(tasks) db.session.commit() # ================================== # 下面路由至頁面 # ================================== @app.route('/') def index(): return render_template('index.html') # ================================== # 下面是RESTful api # ================================== # 輔助函數 from flask import url_for def replace_id_to_uri(task): return dict(uri = url_for('get_task', task_id=task.id, _external=True), title = task.title, description = task.description, done = task.done) # 查詢所有 @app.route('/todo/api/v1.0/tasks/', methods=['GET']) def get_tasks(): tasks = Todo.query.all() return jsonify({'tasks': list(map(replace_id_to_uri, tasks))}) # 查詢一個 from flask import abort @app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['GET']) def get_task(task_id): task = Todo.query.filter_by(id=task_id).first() if task is None: abort(404) return jsonify({'task': replace_id_to_uri(task)}) # 添加 from flask import request @app.route('/todo/api/v1.0/tasks/', methods=['POST']) def create_task(): # 沒有數據,或者數據缺乏 title 項,返回 400,表示請求無效 if not request.json or not 'title' in request.json: abort(400) task = Todo(request.json['title'], request.json.get('description', ""), False) db.session.add(task) db.session.commit() return jsonify({'task': replace_id_to_uri(task)}), 201 # 更新 @app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['PUT']) def update_task(task_id): task = Todo.query.filter_by(id=task_id).first() if task is None: abort(404) if not request.json: abort(400) if 'title' in request.json and type(request.json['title']) != unicode: abort(400) if 'description' in request.json and type(request.json['description']) is not unicode: abort(400) if 'done' in request.json and type(request.json['done']) is not bool: abort(400) task['title'] = request.json.get('title', task['title']) task['description'] = request.json.get('description', task['description']) task['done'] = request.json.get('done', task['done']) #db.session.update(task) db.session.commit() return jsonify({'task': replace_id_to_uri(task)}) # 刪除 @app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['DELETE']) def delete_task(task_id): task = Todo.query.filter_by(id=task_id).first() if task is None: abort(404) db.session.delete(task) db.session.commit() return jsonify({'result': True}) # 定製404出錯頁面 @app.errorhandler(404) def not_found(error): return jsonify({'error': 'Not found'}), 404 if __name__ == '__main__': app.run(debug=True)
<meta charset="utf-8"/> <form enctype='application/json' method="post"> <label>任務標題:</label> <input type="text" name="title"></br> <label>任務描述:</label> <input type="texteara" name="description"></br> <button type="submit">添加任務</button> </form> <!-- 任務列表 --> <ol id="container"></ol> <script> var container = document.getElementById('container'); // 輔助函數:將一條任務(task),放入form的下方容器的尾部 var add_child = function (task) { var li = document.createElement("li"); li.innerText = task["title"] + " " + task["description"]; container.appendChild(li); }; // 輔助函數:FormData轉化爲json var convert_FormData_to_json = function (formData) { var objData = {}; for (var entry of formData.entries()){ objData[entry[0]] = entry[1]; } return JSON.stringify(objData); }; // 最初,ajax取所有任務,放入form的下方容器 window.onload = function () { var xhr = new XMLHttpRequest(); xhr.open('GET', '/todo/api/v1.0/tasks/'); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.send(); xhr.addEventListener('loadend', function() { if(xhr.status == 200){ var res = JSON.parse(xhr.responseText); //console.log(res); res["tasks"].map(add_child) } }, false); }; </script> <script> var formobj = document.querySelector('form'); //var formobj = document.getElementByTag('form'); formobj.addEventListener('submit', function(event){ event.preventDefault(); var xhr2 = new XMLHttpRequest(); xhr2.open('POST', '/todo/api/v1.0/tasks/'); xhr2.setRequestHeader('Content-Type', 'application/json'); xhr2.send(convert_FormData_to_json(new FormData(formobj)));// 發送json數據! xhr2.addEventListener('loadend', function() { if(xhr2.status == 201){ // 201,去看app.py!! var res2 = JSON.parse(xhr2.responseText); [res2["task"]].map(add_child); // 這裏也用map,沒別的目的,只想與前面的形式一致 } }, false); }, false); </script>
1).www.pythondoc.com/flask-restful/first.htmljava