Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
The code from my 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
#!flask/bin/python
from flask import Flask, jsonify, abort, request, make_response, url_for
from flask.ext.httpauth import HTTPBasicAuth
app = Flask(__name__, static_url_path = "")
auth = HTTPBasicAuth()
@auth.get_password
def get_password(username):
if username == 'miguel':
return 'python'
return None
@auth.error_handler
def unauthorized():
return make_response(jsonify( { 'error': 'Unauthorized access' } ), 403)
# return 403 instead of 401 to prevent browsers from displaying the default auth dialog
@app.errorhandler(400)
def not_found(error):
return make_response(jsonify( { 'error': 'Bad request' } ), 400)
@app.errorhandler(404)
def not_found(error):
return make_response(jsonify( { 'error': 'Not found' } ), 404)
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:
new_task[field] = task[field]
return new_task
@app.route('/todo/api/v1.0/tasks', methods = ['GET'])
@auth.login_required
def get_tasks():
return jsonify( { 'tasks': 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 = filter(lambda t: t['id'] == task_id, tasks)
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 = filter(lambda t: t['id'] == task_id, tasks)
if len(task) == 0:
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[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 = filter(lambda t: t['id'] == task_id, tasks)
if len(task) == 0:
abort(404)
tasks.remove(task[0])
return jsonify( { 'result': True } )
if __name__ == '__main__':
app.run(debug = True)

Very useful...Thanks

Thanks :)

nmud19 commented Mar 4, 2016

Thanks man!

I am getting error while executing app.py

C:\Python27\todo-api\flask>python app.py
Traceback (most recent call last):
File "app.py", line 3, in
from flask.ext.httpauth import HTTPBasicAuth
File "C:\Python27\Scripts\flask\lib\site-packages\flask\exthook.py", line 87, in load_module
raise ImportError('No module named %s' % fullname)
ImportError: No module named flask.ext.httpauth

@Rsimpossible What does that error message say?

flask/bin/pip install flask-httpauth
https://github.com/miguelgrinberg/flask-httpauth

@app.errorhandler(400)
def not_found(error):
return make_response(jsonify( { 'error': 'Bad request' } ), 400)

@app.errorhandler(404)
def not_found(error):
return make_response(jsonify( { 'error': 'Not found' } ), 404)

in the above code function name is same for both 400 and 404.

Very helpful code and thanks .I'm getting "error": "Unauthorized access" in the browser while I run rest-server.py .Can you help me get rid of this please?

Thanks miguelgrinberg for this wonderful code !!

For other how are getting the error for flask.ext.httpauth is depricated
So just change flask.ext.httpauth to flask_httpauth in line number 3

asavalia commented Sep 5, 2016

Really, it's very helpfull... 👍

Thank you so much Man !!!! It's really helpful !!!

This was super helpful. It got me acquainted with api using flask very easily. Keep up the good work Miguel

How can I convert my code in API : Please follow this link I have posted detailed question on Stack Overflow

http://stackoverflow.com/questions/42928251/making-my-python-code-as-an-restful-api-python-flask

Great guide, Thank you very much.

vboyk commented Apr 26, 2017

flask.ext.httpauth package is marked as deprecated (Python 3.6). Use flask_httpauth instead:
from flask_httpauth import HTTPBasicAuth

just I want

savanmorya commented May 29, 2017 edited

very easy to understand, best for beginners

Awesome writeup for beginners. I was trying to teach my son to write a restful api. I am definitely going to point him to this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment