Python 如何使用flask restplus为web设计api实现?

Python 如何使用flask restplus为web设计api实现?,python,flask,swagger,flask-restplus,Python,Flask,Swagger,Flask Restplus,我第一次在烧瓶中编写RESTAPI 现在我有了这样的东西: import uuid import pytz from datetime import datetime from flask_restplus import Resource, Api, fields from ..models import publicip_schema from ..controller import ( jsonified, get_user_ip, add_new_userIp,

我第一次在烧瓶中编写RESTAPI

现在我有了这样的东西:

import uuid
import pytz
from datetime import datetime
from flask_restplus import Resource, Api, fields
from ..models import publicip_schema

from ..controller import (
    jsonified,
    get_user_ip,
    add_new_userIp,
    get_specificIp,
    get_all_publicIp
    )

from flask import request, jsonify

from src import app
from src import db
from src import models

api = Api(app, endpoint="/api", versio="0.0.1", title="Capture API", description="Capture API to get, modify or delete system services")

add_userIp = api.model("Ip", {"ip": fields.String("An IP address.")})
get_userIp = api.model("userIp", {
    "ipid": fields.String("ID of an ip address."), 
    "urlmap" : fields.String("URL mapped to ip address.")
    })

class CaptureApi(Resource):

    # decorator = ["jwt_required()"]

    # @jwt_required()
    @api.expect(get_userIp)
    def get(self, ipid=None, urlmap=None):
        """
           this function handles request to provide all or specific ip
        :return:
        """
        # handle request to get detail of site with specific location id.
        if ipid:
            ipobj = get_user_ip({"id": ipid})
            return jsonified(ipobj)

        # handle request to get detail of site based on  site abbreviation
        if urlmap:
            locate = get_user_ip({"urlmap": urlmap})
            return jsonified(locate)

        return jsonify(get_all_publicIp())

    # @jwt_required()
    @api.expect(add_userIp)
    def post(self, username=None):
        """
            Add a new location.
            URI /location/add
        :return: json response of newly added location
        """
        data = request.get_json(force=True)
        if not data:
            return jsonify({"status": "no data passed"}), 200

        if not data["ip"]:
            return jsonify({"status" : "please pass the new ip you want to update"})

        if get_user_ip({"ipaddress": data["ip"]}):
                return jsonify({"status": "IP: {} is already registered.".format(data["ip"])})

        _capIpObj = get_user_ip({"user_name": username})

        if _capIpObj:
            # update existing ip address
            if "ip" in data:
                if _capIpObj.ipaddress == data["ip"]:
                    return jsonify({"status": "nothing to update."}), 200
                else:
                    _capIpObj.ipaddress = data["ip"]
            else:
                return jsonify({
                    "status" : "please pass the new ip you want to update"
                    })

            db.session.commit()
            return jsonified(_capIpObj)
        else:
            device = ""
            service = ""
            ipaddress = data["ip"]
            if "port" in data:
                port = data["port"]
            else:
                port = 80
            if "device" in data:
                device = data["device"]
            if "service" in data:
                service = data["service"]
            date_modified = datetime.now(tz=pytz.timezone('UTC'))
            urlmap = str(uuid.uuid4().get_hex().upper()[0:8])    
            new_public_ip = add_new_userIp(username, ipaddress, port, urlmap, device, service, date_modified)
            return publicip_schema.jsonify(new_public_ip)


api.add_resource(
    CaptureApi,
    "/getallips",  # GET
    "/getip/id/<ipid>",  # GET
    "/getip/urlmap/<urlmap>",  # GET
    "/updateip/username/<username>" # POST
                 )
导入uuid
进口皮茨
从日期时间导入日期时间
从restplus导入资源、Api和字段
从..模型导入公共IP_架构
从..控制器导入(
jsonified,
获取用户ip,
添加新的用户IP,
获取详细信息,
让大家都知道
)
从flask导入请求,jsonify
从src导入应用程序
从src导入数据库
从src导入模型
api=api(应用程序,endpoint=“/api”,versio=“0.0.1”,title=“捕获api”,description=“捕获api以获取、修改或删除系统服务”)
add_userIp=api.model(“Ip”,“Ip”:fields.String(“Ip地址”)})
get_userIp=api.model(“userIp”{
“ipid”:fields.String(“ip地址的ID”),
“urlmap”:fields.String(“URL映射到ip地址”)
})
类CaptureApi(资源):
#decorator=[“jwt_required()”]
#@jwt_必需()
@expect(get_userIp)
def get(self,ipid=None,urlmap=None):
"""
此函数处理提供所有或特定ip的请求
:返回:
"""
#处理请求以获取具有特定位置id的站点详细信息。
如果ipid:
ipobj=get_user_ip({“id”:ipid})
返回jsonified(ipobj)
#根据站点缩写处理获取站点详细信息的请求
如果URL映射:
locate=get_user_ip({“urlmap”:urlmap})
返回jsonified(定位)
返回jsonify(get_all_publicIp())
#@jwt_必需()
@api.expect(添加用户IP)
def post(自我,用户名=无):
"""
添加一个新位置。
URI/位置/添加
:return:新添加位置的json响应
"""
data=request.get_json(force=True)
如果没有数据:
返回jsonify({“status”:“未传递数据”}),200
如果不是数据[“ip”]:
返回jsonify({“status”:“请传递要更新的新ip”})
如果获取用户ip({“ipaddress”:数据[“ip”]}):
返回jsonify({“status”:“IP:{}已注册。”.format(数据[“IP”]))
_capIpObj=get_user_ip({“user_name”:username})
如果_capIpObj:
#更新现有ip地址
如果数据中有“ip”:
如果_capIpObj.ipaddress==数据[“ip”]:
返回jsonify({“status”:“nothing to update.”),200
其他:
_capIpObj.ipaddress=数据[“ip”]
其他:
返回jsonify({
“状态”:“请传递要更新的新ip”
})
db.session.commit()
返回jsonified(_capIpObj)
其他:
device=“”
service=“”
ip地址=数据[“ip”]
如果数据中有“端口”:
端口=数据[“端口”]
其他:
端口=80
如果数据中有“设备”:
设备=数据[“设备”]
如果数据中有“服务”:
服务=数据[“服务”]
修改日期=datetime.now(tz=pytz.timezone('UTC'))
urlmap=str(uuid.uuid4().get_hex().upper()[0:8])
new\u public\u ip=add\u new\u userIp(用户名、ip地址、端口、urlmap、设备、服务、修改日期)
返回publicip_schema.jsonify(新的公共ip)
api.add_资源(
CaptureApi,
“/getallips”,#获取
“/getip/id/”,#获取
“/getip/urlmap/”,#获取
“/updateip/username/”发布
)
我面临两个问题

  • 如果我指定

    get\u userIp=api.model(“userIp”{
    “ipid”:fields.String(“ip地址的ID”),
    “urlmap”:fields.String(“URL映射到ip地址”)
    })

  • 并在上面的get方法上添加
    @api.expect(get_userIp)
    。我被迫用任何值传递可选参数(甚至从“/getallips”获取所有ip的列表):见下面的屏幕截图

    但是,设置所有IP并不需要这些选项参数,但我确实需要使用这些参数根据
    ipid
    ,或使用
    get
    方法获取IP

  • 查看由
    flask\u restplus.Api生成的招摇过市文档
  • 所有端点的get和post,而我只定义了端点get和post。所以从技术上讲,
    updateip/username/
    不应该列出
    get


    如何修复此问题?

    好问题!您可以通过为每个端点定义单独的
    Resource
    子类来解决这两个问题。下面是一个示例,其中我拆分了“/getallips”、“/getip/id/”和“/getip/urlmap/”的端点

    Ip=api.model(“Ip”,“Ip”:fields.String(“Ip地址”)})
    Urlmap=api.model(“Urlmap”,“Urlmap”:fields.String(“URL映射到ip地址”)})
    @api.路线(“/getallips”)
    类别列表(资源):
    def get(自我):
    返回jsonify(get_all_publicIp())
    @api.route(“/getip/id/”)
    类IpById(资源):
    @api.expect(Ip)
    def get(自我,ipid):
    ipobj=get_user_ip({“id”:ipid})
    返回jsonified(ipobj)
    @api.route(“/getip/urlmap/”)
    类IpByUrlmap(资源):
    @expect(Urlmap)
    def get(self,urlmap):
    ipobj=get_user_ip({“id”:ipid})
    返回jsonified(ipobj)
    
    请注意,您可以免费解决
    expect
    问题-因为每个端点现在都完全定义了它的接口,所以很容易为它附加一个明确的期望。您还可以解决“为不应该的端点定义get和post”问题,您可以为每个端点决定是应该有
    get
    还是
    post

    我正在使用decorator而不是调用
    api。由于个人喜好,为每个类添加_resource
    。您可以通过为每个新的
    resource
    子类(例如
    api.add\u resource)调用
    api.add\u resource(,)
    来获得相同的行为
    Ip = api.model("Ip", {"ip": fields.String("An IP address.")})
    Urlmap = api.model("UrlMap", {"urlmap": fields.String("URL mapped to ip address.")})
    
    @api.route("/getallips")
    class IpList(Resource):
        def get(self):
            return jsonify(get_all_publicIp())
    
    @api.route("/getip/id/<ipid>")
    class IpById(Resource):
        @api.expect(Ip)
        def get(self, ipid):
            ipobj = get_user_ip({"id": ipid})
            return jsonified(ipobj)
    
    @api.route("/getip/urlmap/<urlmap>")
    class IpByUrlmap(Resource):
        @api.expect(Urlmap)
        def get(self, urlmap):
            ipobj = get_user_ip({"id": ipid})
            return jsonified(ipobj)