首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何优化RestFul接口

如何优化RestFul接口
EN

Code Review用户
提问于 2017-03-28 12:33:40
回答 1查看 969关注 0票数 0

本教程为这里

我想要构建一个RestFul API,它可以查询用户代理数据。卷曲脚本如下所示。api应该使用三个或两个,或者一个,甚至零参数。

那么,如何更改代码,使其更加简单和可读性呢?

代码语言:javascript
复制
curl -i http://localhost:5000/todo/api/v1.0/tasks -u miguel:python -i -H "Content-Type: application/json" -X POST -d '{"os_family":"iOS","device_brand":"Apple"}'


None: return default data

One: {"os_family":"iOS"}

Two : {"os_family":"iOS","device_brand":"Apple"}, or {"os_family":"iOS","browser":"Mobile Safari"}, or {"device_brand":"Apple","browser":"Mobile Safari"}

Three :{"device_brand":"Apple","browser":"Mobile Safari","device_brand":"Apple"}

源代码

代码语言:javascript
复制
#!flask/bin/python

"""Alternative version of the ToDo RESTful server implemented using the
Flask-RESTful extension."""

from flask import Flask, jsonify, abort, make_response
from flask_restful import Api, Resource, reqparse, fields, marshal
from flask_httpauth import HTTPBasicAuth
from pymongo import MongoClient
import random

client = MongoClient('10.211.55.12', 27018)
db = client.useragent
post = db.ua_final

app = Flask(__name__, static_url_path="")
api = Api(app)
auth = HTTPBasicAuth()

import time
import datetime


@auth.get_password
def get_password(username):
    if username == 'miguel':
        return 'python'
    return None


@auth.error_handler
def unauthorized():
    # return 403 instead of 401 to prevent browsers from displaying the default
    # auth dialog
    return make_response(jsonify({'message': 'Unauthorized access'}), 403)

tasks = [
    {
        'id': 1,
        'ua': u"Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B179 Safari/7534.48.3",
        'done': False
    },
    {
        'id': 2,
        'ua': u"Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
        'done': False
    }
]

task_fields = {
    'ua': fields.String,
    'done': fields.Boolean,
    'uri': fields.Url('task')
}


class TaskListAPI(Resource):
    decorators = [auth.login_required]

    def __init__(self):
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument('ua', type=str, required=True,
                                   help='No ua provided',
                                   location='json')
        self.reqparse.add_argument('description', type=str, default="",
                                   location='json')
        super(TaskListAPI, self).__init__()

    def get(self):
        return {'tasks': [marshal(task, task_fields) for task in tasks]}


class TaskAPI(Resource):
    decorators = [auth.login_required]

    def __init__(self):
        self.reqparese = reqparse.RequestParser()
        self.reqparese.add_argument(
            'number', type=int, default=10, location='json')
        self.reqparese.add_argument(
            'browser', type=str, default='', location='json')
        self.reqparese.add_argument(
            'os_family', type=str, default='', location='json')
        self.reqparese.add_argument(
            'device_brand', type=str, default='', location='json')
        super(TaskAPI, self).__init__()

    def delete_id(self, newDict):
        del newDict['_id']
        return newDict['UA']

    def post(self):
        args = self.reqparese.parse_args()
        # print args
        if args['browser'] == '' and args['os_family'] == '' and args['device_brand'] == '':
            return {'results': random.sample([self.delete_id(i) for i in post.find().limit(1000)], 10)}

        if args['browser'] == '' or args['os_family'] == '' or args['device_brand'] == '':
            if len([self.delete_id(i) for i in post.find({'device_brand': args['device_brand'], 'os_family':args['os_family'], 'browser_family':args['browser']}).limit(1000)]) != 0:
                return {'results': random.sample([self.delete_id(i) for i in post.find({"$or": [{'os_family': args['os_family']}, {'browser_family': args['browser']}]}).limit(1000)], 10)}
            else:
                return {'results': None}
        if args['browser'] != '' and args['os_family'] != '' and args['device_brand'] != '':
            if len([self.delete_id(i) for i in post.find({'device_brand': args['device_brand'], 'os_family':args['os_family'], 'browser_family':args['browser']}).limit(1000)]) != 0:
                return {'results': random.sample([self.delete_id(i) for i in post.find({'device_brand': args['device_brand'], 'os_family':args['os_family'], 'browser_family':args['browser']}).limit(1000)], 10)}
            else:
                return {'results': None}

        # result = [i del i['_id'] for i in post.find(limit=10)]
        # return {'results': random.sample(result,1)}


api.add_resource(TaskListAPI, '/todo/api/v1.0/tasks', endpoint='tasks')
api.add_resource(TaskAPI, '/todo/api/v1.0/tasks', endpoint='task')


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

源数据

代码语言:javascript
复制
/* 1 */
{
    "_id" : "3e55d425bf7e8bd95be302fb76e47371",
    "device_family" : "Other",
    "device_model" : null,
    "browser_version_string" : "",
    "os_version_string" : "",
    "os_version" : [],
    "browser_version" : [],
    "os_family" : "Mac OS X",
    "device_brand" : null,
    "UA" : "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/419 (KHTML, like Gecko, Safari/419.3) Cheshire/1.0.ALPHA",
    "browser_family" : "Safari"
}

/* 2 */
{
    "_id" : "64b0d163d57ea36f0a8bf0a827e6d94f",
    "device_family" : "Other",
    "device_model" : null,
    "browser_version_string" : "",
    "os_version_string" : "",
    "os_version" : [],
    "browser_version" : [],
    "os_family" : "Mac OS X",
    "device_brand" : null,
    "UA" : "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.9 (KHTML, like Gecko, Safari/111) Cheshire/1.0.ALPHA",
    "browser_family" : "Safari"
}

/* 3 */
{
    "_id" : "b0de66dc426faf27832b6649d39450b7",
    "device_family" : "Other",
    "device_model" : null,
    "browser_version_string" : "",
    "os_version_string" : "",
    "os_version" : [],
    "browser_version" : [],
    "os_family" : "Mac OS X",
    "device_brand" : null,
    "UA" : "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.9 (KHTML, like Gecko, Safari) Safari/419.3 Cheshire/1.0.ALPHA",
    "browser_family" : "Safari"
}

/* 4 */
{
    "_id" : "bc4915d3c02ba508cbeb5d3a2584fb87",
    "device_family" : "Other",
    "device_model" : null,
    "browser_version_string" : "",
    "os_version_string" : "",
    "os_version" : [],
    "browser_version" : [],
    "os_family" : "Mac OS X",
    "device_brand" : null,
    "UA" : "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.9 (KHTML, like Gecko) Safari/419.3 Cheshire/1.0.ALPHA",
    "browser_family" : "Safari"
}

/* 5 */
{
    "_id" : "b08637a6eb4a57310d9105d527fee5ba",
    "device_family" : "Other",
    "device_model" : null,
    "browser_version_string" : "",
    "os_version_string" : "",
    "os_version" : [],
    "browser_version" : [],
    "os_family" : "Mac OS X",
    "device_brand" : null,
    "UA" : "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/419 (KHTML, like Gecko, Safari/419.3) Cheshire/1.0.ALPHA",
    "browser_family" : "Safari"
}

/* 6 */
{
    "_id" : "b489e2d84b8f6543e2ebfe36700ae023",
    "device_family" : "Other",
    "device_model" : null,
    "browser_version_string" : "",
    "os_version_string" : "",
    "os_version" : [],
    "browser_version" : [],
    "os_family" : "Mac OS X",
    "device_brand" : null,
    "UA" : "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/419 (KHTML, like Gecko, Safari/125) Cheshire/1.0.ALPHA",
    "browser_family" : "Safari"
}

/* 7 */
{
    "_id" : "069aaf22239724549b9c21711e3d69a2",
    "device_family" : "Other",
    "device_model" : null,
    "browser_version_string" : "7.0.3",
    "os_version_string" : "10.9.3",
    "os_version" : [ 
        10, 
        9, 
        3
    ],
    "browser_version" : [ 
        7, 
        0, 
        3
    ],
    "os_family" : "Mac OS X",
    "device_brand" : null,
    "UA" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A",
    "browser_family" : "Safari"
}

/* 8 */
{
    "_id" : "c15ec0412f029f692ec01fae06c68b53",
    "device_family" : "iPad",
    "device_model" : "iPad",
    "browser_version_string" : "6.0",
    "os_version_string" : "6.0",
    "os_version" : [ 
        6, 
        0
    ],
    "browser_version" : [ 
        6, 
        0
    ],
    "os_family" : "iOS",
    "device_brand" : "Apple",
    "UA" : "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25",
    "browser_family" : "Mobile Safari"
}

/* 9 */
{
    "_id" : "5d265f6e2bc2aa0905a72770ce4dc3ea",
    "device_family" : "Other",
    "device_model" : null,
    "browser_version_string" : "5.1.3",
    "os_version_string" : "10.7.3",
    "os_version" : [ 
        10, 
        7, 
        3
    ],
    "browser_version" : [ 
        5, 
        1, 
        3
    ],
    "os_family" : "Mac OS X",
    "device_brand" : null,
    "UA" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10",
    "browser_family" : "Safari"
}

/* 10 */
{
    "_id" : "25740aba95599f5ea63181821f0d56d7",
    "device_family" : "iPad",
    "device_model" : "iPad",
    "browser_version_string" : "5.1",
    "os_version_string" : "5.1",
    "os_version" : [ 
        5, 
        1
    ],
    "browser_version" : [ 
        5, 
        1
    ],
    "os_family" : "iOS",
    "device_brand" : "Apple",
    "UA" : "Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko ) Version/5.1 Mobile/9B176 Safari/7534.48.3",
    "browser_family" : "Mobile Safari"
}
EN

回答 1

Code Review用户

发布于 2017-03-28 15:52:01

如果您运行flake8,您将得到以下备注:

代码语言:javascript
复制
test.py:6:1: F401 'flask.abort' imported but unused
test.py:20:1: E402 module level import not at top of file
test.py:20:1: F401 'time' imported but unused
test.py:21:1: E402 module level import not at top of file
test.py:21:1: F401 'datetime' imported but unused
test.py:37:1: E305 expected 2 blank lines after class or function definition, found 1
test.py:40:80: E501 line too long (152 > 79 characters)
test.py:45:80: E501 line too long (157 > 79 characters)
test.py:95:80: E501 line too long (92 > 79 characters)
test.py:96:80: E501 line too long (103 > 79 characters)
test.py:98:80: E501 line too long (90 > 79 characters)
test.py:99:80: E501 line too long (181 > 79 characters)
test.py:100:80: E501 line too long (187 > 79 characters)
test.py:103:80: E501 line too long (92 > 79 characters)
test.py:104:80: E501 line too long (181 > 79 characters)
test.py:105:80: E501 line too long (210 > 79 characters)

这些天生的长队尤其糟糕。

如果您查看一下烧瓶_restful.reqparse,您会发现它被标记为过时,并将在将来删除。我建议使用塞伯鲁斯库来授权、强制和解析传递的JSON数据。

没有理由让task_fields全球化。您可能应该将它移到TaskListAPI类中,因为它是唯一使用它的类,并将其大写,因为它意味着用作contanst:

代码语言:javascript
复制
class TaskListAPI(Resource):
    TASK_FIELDS = ..

这段具有多个and的代码看起来非常糟糕:

代码语言:javascript
复制
if args['browser'] == '' and args['os_family'] == '' and args['device_brand'] == ''

可以重写如下:

代码语言:javascript
复制
if not any([args['browser'], args['os_family'], args['device_brand'])

TaskAPI.post内部的这一复杂逻辑应该使用临时变量重写。正如flake8所报告的,如果一行中有超过80个字符,则需要重写它。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/159119

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档