Python 在单个视图方法中接受多个请求类型的更好方法?

Python 在单个视图方法中接受多个请求类型的更好方法?,python,flask,Python,Flask,我试图将API公开给各种请求方法(GET、url x-www-form-urlencoded POST和json POST): 上述内容似乎过于冗长。有没有更简单或更好的写作方法?谢谢。没有什么可以阻止您将代码改写为: @app.route('/create', methods=['GET', 'POST']) def create_file(): params = None if request.method == 'GET': params = request

我试图将API公开给各种请求方法(GET、url x-www-form-urlencoded POST和json POST):


上述内容似乎过于冗长。有没有更简单或更好的写作方法?谢谢。

没有什么可以阻止您将代码改写为:

@app.route('/create', methods=['GET', 'POST'])
def create_file():
    params = None
    if request.method == 'GET':
        params = request.args
    if request.method == 'POST':
        if request.json:
            params = request.json
        else:
            params = request.form

    n = params.get('n')
    t = params.get('t')

    try:
        n = int(n)
    except:
        n = 1
    ...

这个好看吗?在我看来,如果您可以接受将JSON POST请求移动到不同的路由(无论如何,您确实应该这样做),那么这会更干净一些

按照其他人的建议使用扩展名。然后,您可以执行以下操作:

class CreateFile(Resource):
    def get(self):
       args = parser.parse_args()
       n,t = args['n'], args['t']

    def post(self, todo_id):
       # do post stuff

诸如此类……

我不知道这是否是您正在寻找的,因为您已经接受了答案,但您可以通过应用标准重构技术来消除很多冗长的内容。首先,每个职能的单一责任:

@app.route('/create', methods=['GET', 'POST'])
def create_file():
    n, t = get_nt_request_data()
    return process_n(n)

def get_nt_request_data():
    if request.method == 'GET':
        return get_nt_query_params()
    if request.method == 'POST':
        if request.json:
            return get_nt_json()
        else:
            return get_nt_form()
    return n, t

def get_nt_query_params():
    n = request.args.get('n')
    t = request.args.get('t')
    return n, t

def get_nt_json():
    n = request.json['n']
    t = request.json['t']
    return n, t

def get_nt_form():
    n = request.form['n']
    t = request.form['t']
    return n, t

def process_n(n):
    try:
        n = int(n)
    except:
        n = 1
现在,这肯定不是更短,但我个人认为它更清楚。每个单独的功能都有一个明确定义的目的,并且不会杂乱无章。我个人会把“n,t”变成一个有两个字段的对象,但这完全取决于你和你的应用程序。步骤2:我们有一些非常明显的复制/粘贴。让我们把它清理干净

@app.route('/create', methods=['GET', 'POST'])
def create_file():
    n, t = get_nt_request_data()
    return process_n(n)

def get_nt_request_data():
    if request.method == 'GET':
        return get_nt_query_params()
    if request.method == 'POST':
        if request.json:
            return get_nt_json()
        else:
            return get_nt_form()
    return n, t

def get_nt_query_params():
    return build_nt(request.args)

def get_nt_json():
    return build_nt(request.json)

def get_nt_form():
    return build_nt(request.form)

def build_nt(resource):
    return resource.get("n"), resource.get("t")

def process_n(n):
    try:
        n = int(n)
    except:
        n = 1
现在我们有进展了!但是,如果我们对20种不同的资源执行此操作(假设您的不同端点遵循HTTP谓词的类似规则),那么我们将拥有一组get_xx_request_数据函数,它们基本上都执行相同的操作。让我们参数化

@app.route('/create', methods=['GET', 'POST'])
def create_file():
    n, t = get_request_data(build_nt)
    return process_n(n)

def build_nt(resource):
    return resource.get("n"), resource.get("t")

def process_n(n):
    try:
        n = int(n)
    except:
        n = 1

# in a shared module somewhere
def get_request_data(builder):
    if request.method == 'GET':
        return builder(request.args)
    if request.method == 'POST':
        if request.json:
            return builder(request.json)
        else:
            return builder(request.form)
    return n, t
对于端点,只需11行代码,以及一个可供其他人重用的共享函数。(我假设这在概念上类似于可用框架的最终功能;我还没有机会检查它们。)


最后一点注意:创建一个带有GET请求的文件会让您大吃一惊,可能还会出现一些奇怪的错误,这取决于您对客户端和中间代理的控制程度。GET应该是这样的,所以客户端应该能够随意地重试它们,而不需要服务器上的任何状态更改(创建某些东西肯定是一种状态更改)。理论上,代理应该能够在网络中断后重播GET命令,甚至不告诉原始客户端它尝试了两次,但在实践中,这从来没有给我带来麻烦。

我通常将API方法移动到一个单独的蓝图中,而不是web方法。通过这种方式,功能不会相互混乱,并允许更容易的维护。我还要看一看,我们必须进一步研究蓝图。现在我选择了@Miguel的答案。谢谢,情况并没有好转。不是一件容易用烧瓶(IMHO)完成的事情。默认情况下,仅通过URL和方法发送请求。我不知道根据头值进行调度需要做多少工作。那么你应该谨慎地看一看,我绝对不会这样做。我宁愿使用少于150 LOC的。这如何使内容协商变得更短?这只是一个建议。OP要求的是“更简单或更好的方式”,而不一定要更短。那么,用“更简单或更好”替换“更短”。是的,这就是我选择的。谢谢
@app.route('/create', methods=['GET', 'POST'])
def create_file():
    n, t = get_nt_request_data()
    return process_n(n)

def get_nt_request_data():
    if request.method == 'GET':
        return get_nt_query_params()
    if request.method == 'POST':
        if request.json:
            return get_nt_json()
        else:
            return get_nt_form()
    return n, t

def get_nt_query_params():
    return build_nt(request.args)

def get_nt_json():
    return build_nt(request.json)

def get_nt_form():
    return build_nt(request.form)

def build_nt(resource):
    return resource.get("n"), resource.get("t")

def process_n(n):
    try:
        n = int(n)
    except:
        n = 1
@app.route('/create', methods=['GET', 'POST'])
def create_file():
    n, t = get_request_data(build_nt)
    return process_n(n)

def build_nt(resource):
    return resource.get("n"), resource.get("t")

def process_n(n):
    try:
        n = int(n)
    except:
        n = 1

# in a shared module somewhere
def get_request_data(builder):
    if request.method == 'GET':
        return builder(request.args)
    if request.method == 'POST':
        if request.json:
            return builder(request.json)
        else:
            return builder(request.form)
    return n, t