微信小程序结合Flask+SQLAlchemy实现数据库访问 + JSON数据处理方法

以下是在进行微信小程序开发过程中积累的经验,有不足之处请指教。谢谢。

基础知识

微信小程序是基于微信自己的框架。无法像其它语言一样直接访问数据库,只能通过以https方式提交数据到后台,后台写一个操作本地数据库的服务端web应用程序,提供https接口让小程序调用。

基本方法

1. 首先看微信小程序端是如何像后台数据库接口应用发起请求的。

在微信小程序的js文件中的某个事件中,通常是按钮事件,发起请求:

formSubmit: function(event) {
console.log("提交表单");
console.log(event.detail.value);
var that=this;
wx.request({
  url: 'http://localhost:5000/science',
  data: {
    schoolname: "*",
    maxscore:"800",
    minscore:"500",
    year:"2018",
  },
  method: 'POST',
  header: { 'content-type': 'application/x-www-form-urlencoded' },
  success: function (res) {
    wx.hideLoading();
    console.log(res.data, 'category data acquisition success');
    that.setData({ category: res.data.data });
  },
  fail: function (res) {
    console.log('submit fail');
  },
  complete: function (res) {
    console.log('submit complete');
  }
});
},

看上面的代码,url就是提供数据库访问的后台程序的入口地址,这里需要注意,因为在调试过程中,通常使用本地地址进行,所以要在微信小程序开发工具的“设置”->“项目设置”中,选中“不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书”,否则会报错:“http://localhost:5000 不在以下 request 合法域名列表中,请参考文档:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/network.html”
data字典中的数据就是通过request的POST方法传递给后台的数据,相当于URL中?后面的部分,上面的例子转换为URL就是:“http://localhost:5000/science?schoolname=*&maxscore=800&minscore=500&year=2018”
上面的代码定义了success、fail、complete三个回调函数,其中,success函数的参数res就是后台程序返回的json格式数据。

其次看后台对数据库进行操作的程序,我用Python+Flask实现

(可选)对是否来自微信服务器的请求的验证

@app.before_request
def check_source():

    """进行验证是否来自微信服务器"""
    """
    signature = request.args.get('signature')
    timestamp = request.args.get('timestamp')
    nonce = request.args.get('nonce')
    # echostr = request.args.get('echostr')
    tmp = [WECHAT_TOKEN, timestamp, nonce]
    tmp.sort()
    tmp = "".join(tmp).encode('utf-8')
    tmp = hashlib.sha1(tmp).hexdigest()
    if tmp != signature:
        return 'error'
    """
    return

处理小程序请求的视图函数

@app.route('/science', methods=['GET', 'POST'])
def science():
    html_url = 'science.html'

    #初始化查询返回值变量为空,如果查询结果为空,则返回空值
    queryResult = []

    if request.method == 'POST': 
        #从request获取查询参数
        session['science_schoolname'] = request.values.get("schoolname")
        session['science_maxscore'] = request.values.get("maxscore")
        session['science_minscore'] = request.values.get("minscore")
        session['science_year'] = request.values.get("year")

    if session.get('science_schoolname'):
        queryResult = base_query_admission(tbl_admission, 0).all()
    
    #rts用于构建返回值的json数据
    rts=[]

    for item in queryResult:
        temp=dict(schoolserial=item.school_serial, 
            schoolname=item.school_name,admissionscore=item.admission_score, 
            batch=item.school_related_batch.batch_name)
        rts.append(temp)

    return json.dumps(rts,ensure_ascii=False) #rts

备注:从SQLAlchemy查询结果构建JSON数据的三种方式
一、SQLAlchemy自带方法
新版的SQLAlchemy自带dumps方法,将查询结果构造成JSON格式数据

from sqlalchemy.ext.serializer import loads, dumps

query = table.query.filter(
                table.score == score).order_by(
                    table.year.desc()).all()

# 将查询结果格式化为JSON数据
serialized = dumps(query)

可能是我没研究明白dumps都提供什么参数,我用这个方法赶回的JSON数据乱码(数据库字段值含中文)

二、网络上大多数推荐的方法,经测试有效且不乱码

from sqlalchemy.ext.declarative import DeclarativeMeta  
import json
import decimal, datetime

# 定义
class AlchemyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj.__class__, DeclarativeMeta):
            # an SQLAlchemy class
            fields = {}
            for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
                data = obj.__getattribute__(field)
                try:
                    json.dumps(data)     # this will fail on non-encodable values, like other classes
                    fields[field] = data
                except TypeError:    # 添加了对datetime的处理
                    if isinstance(data, datetime.datetime):
                        fields[field] = data.isoformat()
                    elif isinstance(data, datetime.date):
                        fields[field] = data.isoformat()
                    elif isinstance(data, datetime.timedelta):
                        fields[field] = (datetime.datetime.min + data).time().isoformat()
                    else:
                        fields[field] = None
            # a json-encodable dict
            return fields
 
        return json.JSONEncoder.default(self, obj)

#使用
rts = json.dumps(queryResult, cls=AlchemyEncoder,ensure_ascii=False)
#加上ensure_ascii=False参数的目的是避免中文乱码

但上面的方法有个问题,外链无法处理。
只好自己处理吧。

import json

@app.route('/science', methods=['GET', 'POST'])
def science():
    html_url = 'science.html'

    #初始化查询返回值变量为空,如果查询结果为空,则返回空值

    queryResult = []

    if request.method == 'POST': 
        session['science_schoolname'] = request.values.get("schoolname")
        session['science_maxscore'] = request.values.get("maxscore")
        session['science_minscore'] = request.values.get("minscore")
        session['science_year'] = request.values.get("year")

    if session.get('science_schoolname'):
        queryResult = base_query_admission(tbl_admission, 0).all()

    rts=[]

    for item in queryResult:
        temp=dict(schoolserial=item.school_serial, 
            schoolname=item.school_name,admissionscore=item.admission_score, 
            #school_related_batch是外链
            batch=item.school_related_batch.batch_name)
        rts.append(temp)

    #rts = json.dumps(queryResult, cls=AlchemyEncoder,ensure_ascii=False)
    return json.dumps(rts,ensure_ascii=False) #rts

运行结果:

Flask后台应用完美的返回数据库查询结果给微信小程序
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

steventian72

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值