以下是在进行微信小程序开发过程中积累的经验,有不足之处请指教。谢谢。
基础知识
微信小程序是基于微信自己的框架。无法像其它语言一样直接访问数据库,只能通过以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后台应用完美的返回数据库查询结果给微信小程序