Skip to content

Instantly share code, notes, and snippets.

@lem0n4id
Forked from miguelgrinberg/rest-server.py
Last active December 15, 2021 15:17
Show Gist options
  • Save lem0n4id/31ca8e48f79034c4dd86bc61a6072fd8 to your computer and use it in GitHub Desktop.
Save lem0n4id/31ca8e48f79034c4dd86bc61a6072fd8 to your computer and use it in GitHub Desktop.
The code from miguel grinberg's article on building RESTful web services with Python and the Flask microframework. See the article here: http://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask
"""This script is a simple TODO web service.
A basic authentication has been implemented using flask_httpauth
API routes defined:
- get_tasks
- get_task
- create_task
- update_task
- delete_task
This script requires that `flask` and `flask_httpauth` be installed
within the Python environment you are running this script in.
Some bugs in the original code has been fixed.
Read miguel grinberg's blog to learn about this :P
"""
from flask import Flask, jsonify, abort, make_response, request, url_for
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
auth = HTTPBasicAuth()
@auth.get_password
def get_password(username):
if username == 'miguel':
return 'python'
return None
@app.errorhandler(404)
def not_found(error):
return make_response(jsonify({'error': 'Not found'}), 404)
@auth.error_handler
def unauthorized():
return make_response(jsonify({'error': 'Unauthorized access'}), 403)
tasks = [
{
'id': 1,
'title': u'Buy groceries',
'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
'done': False
},
{
'id': 2,
'title': u'Learn Python',
'description': u'Need to find a good Python tutorial on the web',
'done': False
}
]
def make_public_task(task):
new_task = {}
for field in task:
if field == 'id':
new_task['uri'] = url_for(
'get_task', task_id=task['id'], _external=True)
else:
try:
new_task[field] = task[field]
except TypeError:
pass
return new_task
@app.route('/todo/api/v1.0/tasks', methods=['GET'])
@auth.login_required
def get_tasks():
return jsonify({'task': list(map(make_public_task, tasks))})
@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['GET'])
@auth.login_required
def get_task(task_id):
task = [task for task in tasks if task['id'] == task_id]
if len(task) == 0:
abort(404)
return jsonify({'task': make_public_task(task[0])})
@app.route('/todo/api/v1.0/tasks', methods=['POST'])
@auth.login_required
def create_task():
if not request.json or not 'title' in request.json:
abort(400)
task = {
'id': tasks[-1]['id'] + 1,
'title': request.json['title'],
'description': request.json.get('description', ""),
'done': False
}
tasks.append(task)
return jsonify({'task': make_public_task(task)}), 201
@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['PUT'])
@auth.login_required
def update_task(task_id):
task = [task for task in tasks if task['id'] == task_id]
if len(task) == 0:
abort(404)
if not request.json:
abort(400)
if 'title' in request.json and type(request.json['title']) != str:
abort(400)
if 'description' in request.json and type(request.json['description']) != str:
abort(400)
if 'done' in request.json and type(request.json['done']) is not bool:
abort(400)
task[0]['title'] = request.json.get('title', task[0]['title'])
task[0]['description'] = request.json.get(
'description', task[0]['description'])
task[0]['done'] = request.json.get('done', task[0]['done'])
return jsonify({'task': make_public_task(task[0])})
@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['DELETE'])
@auth.login_required
def delete_task(task_id):
task = [task for task in tasks if task['id'] == task_id]
if len(task) == 0:
abort(404)
tasks.remove(task[0])
return jsonify({'result': True})
if __name__ == "__main__":
app.run(debug=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment