0%

flask提供python脚本api查询数据库

利用python的Flask库将脚本打包成api,实现通过url实现前端sql查询,访问数据库

起因是《GIS综合实验》这门课要求一个大作业,其中一项为WebGIS开发。对于接受了过多地学原理性课程教学而疏于计算机水平训练的学生来说,即使简单的Web开发也是一件比较头疼的事情,况且为了必须使用一个国产平台,在众多服务与文档中饶了很久的圈子。原本以为,将postgis数据库部署到平台上后,通过REST请求或者是WFS协议能够方便地实现增删改查,至少GET数据不是一件难事,但实现与设想相去甚远。和工作人员交流才知道,该平台上传的postgis数据库一般作为一个数据源为发布文件型的工作空间服务,直接查询该数据库是非常规的操作。这让我非常郁闷,原本实现的逻辑中包括读取数据库中几十万个点数据,通过deck.gl为mapbox开发的高效率点图层渲染到底图上,以及使用postgis特有的一些空间查询语句等等,如果不能直接访问数据库,那么这些设计好的逻辑、代码都要修改甚至报废。无奈之下,只能自己上手连接后端数据库,下面是实现的过程。
不知道答辩的时候能不能耍小聪明,堂而皇之的告诉评委这是用该国产平台实现的。
Flask 是一个轻量级的 Python Web 框架,用于构建 Web 应用程序,使用 Flask 可以通过定义路由来映射 URL 到相应的处理函数。这使得开发者能够轻松地构建 Web 应用的不同页面和功能(GPT语)首先在后端代码定义一个类Database,因为我的需求中暂时不需要对数据库的增删改,因此仅在该类中定义基础的打开关闭与查询功能。创建api.py,引入依赖库并进行基础定义:

1
2
3
4
5
6
7
8
from psql.postsqlConnect import Database
from flask import Flask, request
import re
from flask_cors import CORS

app = Flask(__name__)
CORS(app, supports_credentials=True)
app.config['JSON_AS_ASCII'] = False

其中Database是我预先写好的数据库查询类,CORS(app, supports_credentials=True)是为了保障跨端口调用时不出现浏览器安全协议问题,而app.config['JSON_AS_ASCII'] = False用于约束查询返回的json不以二进制的形式出现。
接下来我们定义一个sql查询,在url中加入m_id, area_id, rating三个约束字段,以查询数据库:
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
@app.route('/api/sqlSearch', methods = ['GET'])
def sqlSearch():
    m_id = request.args.get('m_id','')
    area_id = request.args.get('area_id','')
    rating = request.args.get('rating','')

    DB = Database(name="restaurant", username="postgres", password="20020405", host="10.20.72.101", port="5432")
    DB.connect()

    baseSql = "SELECT id, ST_X(geom) AS lon, ST_Y(geom) AS lat FROM public.shanghai_restaurants"

    if m_id != "" or area_id != "" or rating != "":
        m_idSql, area_idSql, ratingSql = "", "", ""
        if m_id != "":
            m_idSql = "m_id = " + str(m_id)
        if area_id != "":
            area_idSql = "area_id = " + str(area_id)
        if rating != "":
            match = re.match(r"\((\d+),(\d+)\)", rating)
            a, b = map(str, match.groups())
            ratingSql = f"rating BETWEEN {a} AND {b}"
           
        whereSql = " WHERE "+' AND '.join(s for s in [m_idSql, area_idSql, ratingSql] if s)
        finalSql = baseSql + whereSql
    else:
        finalSql = baseSql
       
    json_data = DB.select(finalSql)
    DB.close()
    return json_data

由于我的需求仅限于查找,因此在定义时设置的是 methods = [‘GET’],如果需要增删改,那么请使用POST请求。对于这个功能,我们定义的基础的url是端口+/api/sqlSearch,其中api是我这个python脚本的文件名,sqlSearch是我接下来要定义的函数名。
在sqlSearch函数中,首先通过request.args.get方法获取url中的参数,随后连接数据库,将这些参数解析为sql语句并提交查找,返回json文件。
运行该程序,会返回给你一个端口,例如我的终端提示为:Running on http://127.0.0.1:5000。在这个url后面再加上/api/sqlSearch,浏览器就会返回数据库所有记录的json。在Running on http://127.0.0.1:5000/api/sqlSearch后用?(英文)拼接查询语句,可以实现sql查询,其固定句式为?参数一=x&参数二=y,当然,不写某个参数(数据库里的字段)的查询条件也可以,这完全取决于上面的查询函数中是如何定义的,parameter = request.args.get('参数一','')获取的就是上述url中的x,一般来说,可以设计为当x非空时,加入sql查询中的WHERE语句。
运行程序开启服务后,在web中输入url:http://127.0.0.1:5000/api/sqlSearch?m_id=116&area_id=3&rating=(3,3),返回的页面如下所示:

在JavaScript中,只需解析用户输入的参数为url,就可渐变快速地查询访问数据库,使用deck.gl渲染在底图上: