±à¼ÍƼö: |
±¾ÎÄÀ´×ÔÓÚblog.miguelgrinberg.com£¬ÎÄÕ´Ӱ²×°²¿Êðµ½Éè¼Æµ½¶Ôweb·þÎñÔö¼Ó°²È«»úÖÆæ¸æ¸µÀÀ´¡£ |
|
FlaskÊÇÒ»¸öPython WEB¿ª·¢¿ò¼Ü¡£½ÓÏÂÀ´Ò»¶ÎÏÐϾʱ¼ä´òËã×öµÄ¡°Î÷×Ó¿ìѶ¡±ÏîÄ¿ÖУ¬ÎÒ´òËãÄÃËüÀ´×öRESTful
API¡£ËäȻ֮ǰ¶ÔPython²¢²»Á˽⣬¶ÔFlask¸üÊÇİÉú£¬µ«°®ÕÛÌڵı¾ÐÔ´ÙʹÎÒ²»¶Ïȥѧϰ¡£ÓÚÊǽñÌì¿´blog¡¢¿´Îĵµ£¬Ð¡ÓÐÊÕ»ñ£¬ÂÔ¼ÇÒ»¶þ¡£
×¼±¸¹¤×÷
È·±£»úÆ÷ÉÏÒѾ°²×°ÁËPython¡¢Pip¡¢VirtualenvµÈ¹¤¾ß¡£Èç¹ûĬÈϵÄPip°²×°Ô´±È½ÏÂý£¬¿ÉÒÔÓÃv2exµÄÊÔÊÔ¡£¾ßÌå·½·¨ÊÇÔÚ~/.pip/Ï´´½¨Ò»¸öÃûΪpip.confµÄÎļþ£¬ÊäÈëеÄpipÔ´¡£
[global]
index-url = http://pypi.v2ex.com/simple |
°²×°Flask
ΪÁ˲»Ó°ÏìϵͳµÄPython»·¾³£¬ÎÒÃÇÓÃVirtualenvÐéÄâÒ»¸öÔËÐл·¾³£¬È»ºóÔÚ´Ë»·¾³Ï¿ª·¢Ò»¸öÃûΪtodoµÄʾÀýСӦÓ㨴¿RESTful
API£¬JSON¸ñʽµÄÊý¾Ý£©¡£
cd ~/Desktop
mkdir todo-api
cd todo-api
virtualenv venv
. venv/bin/activate |
´ËʱÃüÁîÐд°¿ÚÓ¦³öÏÖ(venv)mbpr2013:todo-api linkoubian$ ÕâÑùµÄÌáʾ·û£¬×¢Òâ×î×ó±ßµÄvenv±íÃ÷µ±Ç°ÔËÐеÄÊÇÐéÄâ³öÀ´µÄ»·¾³¡£¹¤×÷Íê³Éºó´òËãÍ˳övenv£¬Ö»ÐèÖ´ÐÐdeactivateÃüÁî¼´¿É¡£
ÕâʱִÐÐpip install flask±ã¿ÉÔÚvenvϰ²×°flaskÄ£¿é¡£
²âÊÔFlaskÊÇ·ñÕý³£¹¤×÷
±àдһ¸öHello World³ÌÐò£¬ÈçÏ£º
from flask import
Flask
app = Flask(__name__)
@app.route('/')
def index():
return "Hello, World!"
if __name__ == '__main__':
app.run(debug = True) |
±£´æÎª~/Desktop/todo-api/app.py£¬Ìí¼Ó¿ÉÖ´ÐÐȨÏÞºó£¬ÇÃpython app.py¿ªÊ¼ÔËÐÐFlask¡£´Ëʱ´ò¿ªä¯ÀÀÆ÷£¬·ÃÎÊlocalhost:5000¼´¿É¿´µ½Hello,
World!
¿ªÊ¼Éè¼ÆRESTful API
»ñÈ¡ËùÓеÄtasks
Ò»¸ötaskÓÉid¡¢title¡¢description¡¢doneµÈÊôÐÔ¹¹³É£¬»ñÈ¡taskÁбíµÄurl¿ÉÒÔÉè¼Æ³É/todo/tasks¡£¾ßÌå´úÂëÈçÏ£¬
from flask import
Flask, jsonify
app = Flask(__name__)
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
},
]
@app.route('/todo/tasks', methods = ['GET'])
def get_tasks():
return jsonify({'tasks': tasks})
if __name__ == '__main__':
app.run(debug = True) |
ÒòΪFlaskÔËÐÐÔÚdebugģʽÏ»á×Ô¶¯reload£¬ËùÒÔ´úÂëдÍêºó±£´æÎļþ¼´¿É¡£
MacÉÏÓÐÒ»¿îÃûΪPawµÄHTTP Client£¬ËãÊÇÎÒ¼û¹ý¡¢ÓùýµÄ¸÷ÖÖAPI²âÊÔ¹¤¾ßÖеÄٮٮÕߣ¬Á¦¼ö¡£
´ò¿ªPaw£¬ÔÚurlÀïÊäÈëhttp://localhost:5000/todo/tasks£¬Ñ¡ÔñGET£¬ÇÃCMD+Enter¼´¿ÉÌýµ½±íʾ³É¹¦µÄÇå´àÌáʾÒô¡£Paw³ýÁËÌṩÔÉúµÄHTTPÏìÓ¦¸ñʽ£¬»¹Ìṩ¸ñʽ»¯ºóä¯ÀÀ¹¦ÄÜ£¬Ñ¡ÔñJSON¸ñʽ¼´¿É¡£
ÉÏÃæÕâ¶Î´úÂ뻹ÊDZȽÏÇåÎúºÃ¶®µÄ£¬Ê×ÏÈ´´½¨Ò»¸ötaskÊý×飬³õʼ»¯Á½¸ötask¶ÔÏó·Å½øÈ¥¡£Ö¸¶¨GET·½Ê½ÇëÇó/todo/tasks×ÊԴʱִÐÐget_tasks·½·¨£¬¾ßÌåÊǰÑÇ°Ãæ´´½¨µÄtasksÊý×éÒÔJSONµÄ¸ñʽ·µ»Ø¡£¶ø½«PythonµÄÊý×éת³ÉJSON¸ñʽÊÇͨ¹ýFlaskµÄjsonifyº¯ÊýʵÏֵġ£
¸ù¾Ýid»ñµÃÌØ¶¨task
ͨ³£ÎÒÃǽ«id·ÅÔÚURLÖУ¬È»ºó¶ÔÓ¦µÄ´¦Àíº¯Êý´ÓURLÖеõ½idÒÔ´ÓÊý¾ÝÔ´£¨´Ë´¦ÎªtaskÊý×飬´æÔÚÄÚ´æÖУ©ÖвéѯÏàÓ¦µØentity£¨´Ë´¦Îªtask£©¡£
@app.route('/todo/tasks/<int:task_id>',
methods = ['GET'])
def get_task(task_id):
task = filter(lambda t: t['id'] == task_id, tasks)
if len(task) == 0:
abort(404)
return jsonify({'task': task[0]}) |
ΪÁËÕý³£Ê¹ÓÃabortº¯Êý£¬ÐèÒª´ÓflaskÄ£¿éimportһϡ£Í¨¹ýPaw²âÊÔhttp://localhost:5000/todo/tasks/1£¬·¢ÏÖÒ»ÇÐÕý³£¡£
·ÃÎÊhttp://localhost:5000/todo/tasks/0ʱ£¬·µ»ØÒ»¶Î³ö´íµÄHTML£¬ÕâÊÇFlask¶Ô404µÄĬÈÏ´¦Àí£¬ÎÒÃÇ¿ÉÒÔ×Ô¼º¶¨ÒåÒ»¸ö·µ»ØJSON¸ñʽµÄ´íÎóÏûÏ¢¡£
@app.errorhandler(404)
def not_found(error):
return make_response(jsonify( { 'error': 'Not
found' } ), 404) |
ÎÒÃÇÓÃmake_responseº¯Êý£¬½«¹¹ÔìºÃµÄJSON×÷Ϊ404´íÎóµÄÏìÓ¦£¬·µ»Ø¸ø¿Í»§¶Ë¡£
´´½¨Ò»¸ötask
URLÈÔÈ»ÓÃ/todo/tasks£¬µ«HTTP·½·¨ÎªPOST¡£¸ù¾ÝRequest¶ÔÏóÖеÄÊý¾Ý¹¹ÔìÒ»¸öеÄtask¶ÔÏ󣬲åÈëÊý¾ÝÔ´¼´¿É¡£
@app.route('/todo/tasks',
methods = ['POST'])
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': task}), 201 |
ÁíÍ⣬ÎÒÃÇÐèÒª¶¨ÒåÒ»¸ö400µÄ´¦ÀíÆ÷£¬ÀàËÆÓÚ404£¬
@app.errorhandler(400)
def not_found(error):
return make_response(jsonify( { 'error': 'Bad
request' } ), 400) |
ÔÚPawÖУ¬POSTÇëÇóhttp://localhost:5000/todo/tasks£¬Í¬Ê±HeaderÀï¼ÓÒ»¸öContent-Type£¬ÖµÎªapplication/json£¬BodyÀï¼ÓÈëÒ»¶ÎÎı¾ÄÚÈÝ{¡°title¡±:
¡°Buy a cell phone¡±}£¬ÇÃCMD+EnterÖ´ÐС£
¸ù¾ÝREST CookbookÒ»ÊéµÄ½¨Ò飬¿ÉÒÔÔÚ·µ»ØµÄÐÂÔötaskÀï¼ÓÈëÒ»¸öuri×ֶΡ£Îª´Ë£¬½¨Ò»¸öÃûΪmake_public_taskµÄº¯Êý£¬ÈçÏ£¬
def make_public_task(task):
new_task = {}
for field in task:
new_task[field] = task[field]
if field == 'id':
new_task['uri'] = url_for('get_task', task_id
= task['id'], _external = True)
return new_task |
ÁíÍ⣬create_taskÖиÄΪ£¬
return jsonify({'task':
make_public_task(task)}), 201 |
get_tasksÖиÄΪ£¬
return jsonify({'tasks':
map(make_public_task, tasks)}) |
get_taskÖиÄΪ£¬
return jsonify({'tasks':
map(make_public_task, tasks)}) |
¸üÐÂÒ»¸ötask
ÏÔÈ»´ËʱµÄHTTP·½·¨ÎªPUT£¬ÏàÓ¦µÄurlºÍ»ñÈ¡taskÀàËÆ¡£
@app.route('/todo/tasks/<int:task_id>',
methods = ['PUT'])
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])
} ) |
ɾ³ýÒ»¸ötask
@app.route('/todo/tasks/<int:task_id>',
methods = ['DELETE'])
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 } ) |
ÐÞ¸ÄPythonÔ´Îļþºó£¬Flask»áreload£¬Õ⽫µ¼ÖÂÉÏÒ»´ÎcreateµÄtask¶ªÊ§£¬ËùÒÔÖ±½Ó³¢ÊÔdelete֮ǰÔö¼ÓµÄtask¿ÉÄܻᱨ404×ÊÔ´ÕÒ²»µ½´íÎó¡£
ΪWEB·þÎñÔö¼Ó°²È«»úÖÆ
»ùÓÚFlaskµÄHTTBasicAuthÀ©Õ¹£¬¶¨ÒåÁ½¸öº¯ÊýÈçÏ£¬
auth = HTTPBasicAuth()
@auth.get_password
def get_password(username):
if username == 'linkoubian':
return '7c4a8d09ca3762af61e59520943dc26494f8941b'
return None
@auth.error_handler
def unauthorized():
return make_response(jsonify( { 'error': 'Unauthorized
access' } ), 401) |
ÆäÖÐget_password·½·¨ÊÇ·µ»ØÖ¸¶¨Óû§µÄÃÜÂëÐÅÏ¢£¨Í¨³£ÊÇ´ÓÊý¾Ý¿âÓû§±í²éѯµÃµ½£©£¬µ±´Ë´¦·µ»ØµÄÖµºÍ¿Í»§¶Ë´«µÝµÄֵƥÅäʱ£¨Æ¥Åä¹ý³ÌÓÉHTTPBasicAuthÍê³É£©³É¹¦£¬·ñÔòÖ´ÐÐerror_handler·µ»Ø´íÎóÐÅÏ¢¡£
¶¨ÒåÍêУÑéÏà¹ØµÄ´úÂ룬»¹Ð轫УÑéÂß¼Ó¦Óõ½ÐèҪУÑéµÄWEB·þÎñ¡£±ÈÈ磬ϣÍûÖ»ÓÐÊÚȨÓû§²Å¿ÉÒÔÐ޸Ļòɾ³ýtask£¬Ôò¿ÉÒÔÔÚupdate_task¼°delete_task·½·¨ÉÏÃæ¼ÓÉÏ@auth.login_required¼´¿É¡£
´ËʱÔÚPawÖÐÐèÌí¼ÓAuthorizationÍ·£¬ÖµÎªHTTP Basic Auth£¬ÔÚusername¼°passwordÎı¾¿òÖзֲ¼ÊäÈëÐÅÏ¢£¬ÇÃCMD+Enter½øÐвâÊÔ¡£

|