当前位置:   article > 正文

微信小程序结合Flask+SQLAlchemy实现数据库访问 + JSON数据处理方法_flask sqlalchemy json字段如何通过中间件封装,在存储和获取的时候通过dumps和

flask sqlalchemy json字段如何通过中间件封装,在存储和获取的时候通过dumps和loa

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

基础知识

微信小程序是基于微信自己的框架。无法像其它语言一样直接访问数据库,只能通过以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');
  }
});
},
  • 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

看上面的代码,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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

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

@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
  • 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

备注:从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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

可能是我没研究明白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参数的目的是避免中文乱码
  • 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
  • 31
  • 32

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

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
  • 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

运行结果:

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/181065
推荐阅读
相关标签
  

闽ICP备14008679号