zoukankan      html  css  js  c++  java
  • REST API请求

    Python中Flask-RESTful编写API接口(小白入门)

     更新时间:2019年12月11日 10:54:00   作者:Alien-Hu  
     
    这篇文章主要介绍了Python中Flask-RESTful编写API接口(小白入门),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    1.API接口:hello world 案例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    from flask import Flask
    from flask_restful import Api, Resource
     
    app = Flask(__name__)
    api = Api(app)
     
    class HelloWorld(Resource):
     def get(self):
      return {'hello': 'world'}
     
    api.add_resource(HelloWorld, '/')
     
    if __name__ == '__main__':
     app.run(debug=True)

    这里写图片描述

    2.API接口:Resource充当路由的角色

    官方文档的说法:
    Flask-RESTful 提供的最主要的基础就是资源(resources)。资源(Resources)是构建在 Flask 可拔插视图 之上,只要在你的资源(resource)上定义方法就能够容易地访问多个 HTTP 方法.

    其实就是想表达,在资源路由上(resources)定义多个方法(get,post,put等),就可以实现多种效果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    from flask import Flask, request
    from flask_restful import Api, Resource
     
    app = Flask(__name__)
    api = Api(app)
     
    todos = {}
     
    class TodoSimple(Resource):
     def get(self, todo_id):
      return {todo_id: todos[todo_id]}
     
     def put(self, todo_id):
      todos[todo_id] = request.form['data']
      return {todo_id: todos[todo_id]}
     
    api.add_resource(TodoSimple, '/<string:todo_id>')
     
    if __name__ == '__main__':
     app.run(debug=True)

    解释:
    (1)TodoSimple类定义了2种方法,最终地址/string:todo_id'下面,就可以实现2种请求方法
    (2)add_resource方法中第一个参数:视图函数名;第二个参数:路由的具体地址,以及string:todo_id代表传递的是一个字符串,且是必要参数。
    (3)request.form[‘data']获取request里面,form表单的key为data的参数,如果request里面,没有data参数,那报错。如果有包含data的多个参数,那也只会取data这一个参数

    step1:为字典todos定义参数,key为todo1

    这里写图片描述

    step2:获取todos里面的todo1的参数

    这里写图片描述

    step3:更新老的数据,多传递其他参数

    这里写图片描述

    step4:获取最新的参数:

    这里写图片描述

    step5:不传递data参数,查看报错情况:

    这里写图片描述

    3.API接口:endpoint(端口)的理解:

    这个问题详情可以参考如下博文,已经解释很详细了:
    https://www.jb51.net/article/176173.htm

    简单理解是:
    url通过endpoint来去查找视图函数(通常endpoint的名字与视图函数名一致),但是如果不一致的时候,就需要有针对性的指定某个视图函数去执行,也或者多个蓝图里面有一样的视图函数的场景下,需要指定具体的endpoint

    4.API接口:参数解析

    官方文档:
    (1)尽管 Flask 能够简单地访问请求数据(比如查询字符串或者 POST 表单编码的数据),验证表单数据仍然很痛苦。Flask-RESTful 内置了支持验证请求数据,它使用了一个类似 argparse 的库。
    (2)需要注意地是与 argparse 模块不同,reqparse.RequestParser.parse_args() 返回一个 Python 字典而不是一个自定义的数据结构。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    from flask import Flask
    from flask_restful import reqparse, abort, Api, Resource
     
    app = Flask(__name__)
    api = Api(app)
     
    parser = reqparse.RequestParser()
    parser.add_argument('task', type=str)
    parser.add_argument('name', type=str)
     
     
    # 获取 & 更新
    class Get_Modify(Resource):
     def post(self):
      args = parser.parse_args()
      print(args)
      return args, 201
     
     
    api.add_resource(Get_Modify, '/get_modify')
     
    if __name__ == '__main__':
     app.run(debug=True)

    step1:从form表单里面获取定义的参数

    这里写图片描述

    解释:
    即使传递其他参数,最终也只会读取定义的2个参数的值
    通过如上代码说明:reqparse.RequestParser.parse_args(),即如上的args可以获取到request的form表单的参数,最终是一个字典

    5.API接口:案例一(在form表单里面传递参数)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    from flask import Flask
    from flask_restful import reqparse, abort, Api, Resource
     
    app = Flask(__name__)
    api = Api(app)
     
    Tasks = {
     't1': {'task': 'eat an app'},
     't2': {'task': 'play football'},
     't3': {'task': 'watching TV'},
    }
     
    def abort_if_todo_doesnt_exist(t_id):
     if t_id not in Tasks:
      abort(404, message="Todo {} doesn't exist".format(t_id))
     
     
    parser = reqparse.RequestParser()
    parser.add_argument('task', type=str)
     
     
    # 获取 & 更新
    class Get_Modify(Resource):
     def get(self):
      return Tasks
     
     def post(self):
      args = parser.parse_args()
      t_id = int(max(Tasks.keys()).lstrip('t')) + 1
      t_id = 't%i' % t_id
      Tasks[t_id] = {'task': args['task']}
      return Tasks[t_id], 201
     
     
    # 设置每个视图函数的访问格式
    api.add_resource(Get_Modify, '/get_modify')
     
    if __name__ == '__main__':
     app.run(debug=True)

    解释:
    (1)如上的函数,get是获取总的列表Tasks
    (2)post是添加最新的一个key的值,且key的值是以“t”开头,数字自增的一种形式
    (3)max(Tasks.keys())这个可以获取到Tasks列表里面,索引最大的key值,在没添加的时候,索引最大为t3
    (4)x_string.lstrip(‘t'),这个可以截取x_string字符串里面以't'开始的剩余字符串。例如t3最终得到3,最终int(max(Tasks.keys()).lstrip(‘t')) + 1这一行的意思是,得到列表最大的一个key的索引,然后自增到下一个。
    (5)在希望在form表单里面传递参数,需要在函数里面,使用args = parser.parse_args()接收传递的参数,具体key值通过add_argument函数设置

    step1:第一次get请求,获取原始的Tasks列表

    这里写图片描述

    step2:第二次post请求,添加value的值为studying,且第三次get请求,查看最新Tasks

    这里写图片描述

    这里写图片描述

    6.API接口:案例二(通过url里面的参数作为查询的参数)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    from flask import Flask
    from flask_restful import reqparse, abort, Api, Resource
     
    app = Flask(__name__)
    api = Api(app)
     
    Tasks = {
     't1': {'task': 'eat an app'},
     't2': {'task': 'play football'},
     't3': {'task': 'watching TV'},
    }
     
     
    def abort_if_todo_doesnt_exist(t_id):
     if t_id not in Tasks:
      abort(404, message="Todo {} doesn't exist".format(t_id))
     
     
    parser = reqparse.RequestParser()
    parser.add_argument('task', type=str)
     
     
    # 更新 & 删除 任务
    class Updata_Delete(Resource):
     def get(self, t_id):    # 根据t_id获取对应的value
      abort_if_todo_doesnt_exist(t_id)
      return Tasks[t_id]
     
     def delete(self, t_id):   # 根据t_id删除对应的value
      abort_if_todo_doesnt_exist(t_id)
      del Tasks[t_id]
      return 'delete success', 204
     
     def post(self, t_id):   # 判断t_id是否存在,并返回Tasks整个列表
      abort_if_todo_doesnt_exist(t_id)
      return Tasks,201
     
     def put(self, t_id):   # 根据t_id添加对应的value,并返回所有值
      args = parser.parse_args()
      task = {'task': args['task']}
      Tasks[t_id] = task
      return Tasks, 201
     
     
    api.add_resource(Updata_Delete, '/update_delete/<t_id>')
     
    if __name__ == '__main__':
     app.run(debug=True)

    step1:查看Tasks完整信息

    这里写图片描述

    step2:添加信息key值为:t5,内容为:studying

    这里写图片描述

    step3:查看t5值的情况

    这里写图片描述

    step4:删除t1的值,然后查看Tasks的完整信息

    这里写图片描述

    这里写图片描述

    解释:
    (1)通过url传递参数,给视图函数,这种方式一般用在get请求,post请求通过form表单形式比较实用
    (2)通过url传递参数,需要定义函数时候,使用形参t_id,且在使用add_resource()函数的使用,url参数形式最后添加<t_id>变量,例如'/update_delete/<t_id>'这个形式。
    (3)delete这个函数,最终执行删除是成功的,但是最终并没有返回return的字符串"delete success",具体原因不详,可能是用法不对,后续再更新中说明.
    (return ‘delete success', 204 将 204去掉即可)

     
     

    本文主要介绍python中调用REST API的几种方式,下面是python中会用到的库。

    • - urllib2
    • - httplib2
    • - pycurl
    • - requests

    urllib2

    - Sample1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import urllib2, urllib
    password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
    password_manager.add_password(None, github_url, 'user', '***')
    auth = urllib2.HTTPBasicAuthHandler(password_manager) # create an authentication handler
    opener = urllib2.build_opener(auth) # create an opener with the authentication handler
    urllib2.install_opener(opener) # install the opener...
    request = urllib2.Request(github_url, urllib.urlencode({'name':'Test repo', 'description': 'Some test repository'})) # Manual encoding required
    handler = urllib2.urlopen(request)
    print handler.read()

    - Sample2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import urllib2
    req = urllib2.Request(url)
    req.add_header('IAF',abc.token_authiaas)
    try:
      resp = urllib2.urlopen(req)
    except urllib2.HTTPError, error:
      print "Cannot remove service instance!", error
      sys.exit(1)
    response = resp.read()
    print response

    - Sample3

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import urllib2, urllib, base64
    data = urllib.urlencode({
            'reservedResource':'RR-Hadoop',
            'resourceCapability':'Production',
            'movetoironic':'False',
            'output':'json'
        })
    print "Bootstrap Asset jobs starting .............."
     
    base64string = base64.encodestring('%s:%s' % (user, passwd)).replace(' ', '')
    request = urllib2.Request(url, data, headers={"Authorization" : "Basic %s" % base64string})
    response = urllib2.urlopen(request).read()
    response_json = json.loads(response)
    response_status = response_json['status']
    status_code = response_status['statusCode']
    status = response_status['status']
    message = response_status['message']     
    print status_code , status, message

    2. httplib2

    1
    2
    3
    4
    5
    6
    7
    import urllib, httplib2
    github_url = '
    h = httplib2.Http(".cache")
    h.add_credentials("user", "******", "
    data = urllib.urlencode({"name":"test"})
    resp, content = h.request(github_url, "POST", data)
    print content

    3. pycurl

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import pycurl, json
    github_url = "
    user_pwd = "user:*****"
    data = json.dumps({"name": "test_repo", "description": "Some test repo"})
    c = pycurl.Curl()
    c.setopt(pycurl.URL, github_url)
    c.setopt(pycurl.USERPWD, user_pwd)
    c.setopt(pycurl.POST, 1)
    c.setopt(pycurl.POSTFIELDS, data)
    c.perform()

    4. requests

    1
    2
    3
    4
    5
    import requests, json
    github_url = "
    data = json.dumps({'name':'test', 'description':'some test repo'})
    r = requests.post(github_url, data, auth=('user', '*****'))
    print r.json

    以上几种方式都可以调用API来执行动作,但requests这种方式代码最简洁,最清晰,建议采用。

     
  • 相关阅读:
    spring中bean的生命周期
    【数据结构与算法】2.2 数组实现循环队列思路、代码
    【数据结构与算法】2.1、数组队列场景、思路、实现
    【Java 基础领域】手气红包实现思路、代码
    【数据结构与算法】1、稀疏数组场景、思路、代码实现
    【Java基础领域】 byte num = 100 没有强制类型转换,为什么也可以编译通过
    【程序人生】程序员发展的7大方向
    【读书笔记】老许的架构
    对于开发中为什么很少用设计模式的思考
    Java编程思想目录
  • 原文地址:https://www.cnblogs.com/wenqiang-leo/p/14652764.html
Copyright © 2011-2022 走看看