【问题标题】:How to add a new parameter to a Python API created using Flask如何向使用 Flask 创建的 Python API 添加新参数
【发布时间】:2020-01-08 20:01:51
【问题描述】:

我正在使用Flask 编写我的 Python API。此 API 仅接受 1 个名为 questionID 的参数。我希望它接受名为lastDate 的第二个参数。我试图四处寻找如何添加这个参数,但找不到一个好的方法来做到这一点。我当前的代码如下所示:

from flask import Flask, request
from flask_restful import Resource, Api, reqparse
from sqlalchemy import create_engine
from json import dumps
from flask_jsonpify import jsonify
import psycopg2
from pandas import read_sql
connenction_string = "DB Credentials'";

app = Flask(__name__)
api = Api(app)

class GetUserAnswers(Resource):
    def get(self, questionID):
        conn = psycopg2.connect(connenction_string);
        cursor = conn.cursor();

        userAnswers = read_sql('''
        select * from <tablename> where questionid = ''' + "'" + questionID + "' order by timesansweredincorrectly desc limit 15" +'''
        ''', con=conn)

        conn.commit();
        conn.close();

        result = {}
        for index, row in userAnswers.iterrows():
            result[index] = dict(row)
        return jsonify(result)

api.add_resource(GetUserAnswers, '/GetUserAnswers/<questionID>')

if __name__ == '__main__':
     app.run(port='5002')

问题 1: 我猜我可以接受 get 定义中的第二个参数。如果不是这样,我应该如何接受第二个参数?

问题2:如何修改api.add_resource()调用以接受第二个参数?

问题3:我目前使用http://localhost:5002/GetUserAnswers/&lt;some question ID&gt;从浏览器调用这个API。如果使用第二个参数,这个调用会如何变化?

我以前从未开发过 API,因此非常感谢任何帮助。

【问题讨论】:

标签: python api flask flask-sqlalchemy


【解决方案1】:

如果要在url路径中添加多个参数例如:

http://localhost:5002/GetUserAnswers/&lt;question_id&gt;/answers/&lt;answer_id&gt;

那么你需要给你的get方法添加多个参数:

def get(self, question_id, answer_id):
    # your code here

但是,如果您想在 url 中添加多个查询参数,例如: http://localhost:5002/GetUserAnswers/&lt;question_id&gt;?lastDate=2020-01-01&amp;totalCount=10&gt;

然后你可以使用请求参数:

def get(self, question_id):
    lastDate = request.args.get('lastDate')
    totalCount = request.args.get('totalCount')
    # your code here

【讨论】:

    【解决方案2】:

    考虑对您的代码进行一些调整:

    1. 如需更简单的实现,请在 Flask API 中使用decorators,避免初始化和调用类对象;
    2. 在 SQL 中使用parameterization,避免潜在的危险和混乱的字符串连接;
    3. 避免使用繁重的数据分析库pandas 及其低效的逐行iterrows 循环。相反,使用光标对象处理所有内容,特别是在psycopg2 中使用DictCursor

    重构的 Python 代码(调整如何使用lastDate 的假设):

    #... leave out the heavy pandas ...
    
    app = Flask(__name__)
    
    @app.route('/GetUserAnswers', methods= ['GET'])
    def GetUserAnswers():
        questionID = request.args.get('questionID', None)
        lastDate = request.args.get('lastDate', None)
    
        conn = psycopg2.connect(connenction_string)
        cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    
        userAnswers = '''SELECT * FROM <tablename> 
                         WHERE questionid = %s
                           AND lastdate = %s
                         ORDER BY timesansweredincorrectly DESC
                         LIMIT 15
                     '''
        # EXECUTE SQL WITH PARAMS
        cur.execute(userAnswers, (questionID, lastDate))
    
        # SAVE TO LIST OF DICTIONARIES
        result = [dict(row) for row in cur.fetchall()]
        cur.close()
        conn.close()
    
        return jsonify(result)
    
    
    if __name__ == '__main__':
         app.run(port='5002')
    

    浏览器调用

    http://localhost:5002/GetUserAnswers?questionID=8888&lastDate=2020-01-08
    

    【讨论】:

    • 我不建议使用装饰器,特别是如果您专门为此目的使用 flask_restful。从长远来看,在主文件中添加资源及其路由以及从外部文件链接类比在装饰器中分布在各处的路由要方便 10 倍。必须将应用程序导入外部文件可能会立即导致循环导入死锁。为了避免使用路径参数,您对原始问题进行了大量修改和假设更改,这显然是他正在尝试做的事情。 (使用 flask_restful)
    • 有趣的点,@c8999c3f964f64!诚然,我不是一个热衷于 Flask 的开发人员,并且作为更简单实现的前言,我推荐了装饰器方法,但将类用于扩展应用程序是有意义的。但我当然支持后一种 SQL 参数化方法和我热衷的非 Pandas 使用方法!
    • 绝对,我也同意这些。但是下面的答案有一个更直接的方法来解决路径中参数的“另一个参数” - 问题。
    猜你喜欢
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-01
    • 1970-01-01
    • 2017-06-14
    • 1970-01-01
    • 2020-06-16
    相关资源
    最近更新 更多