flask 与 小程序 下单提交 订单列表展示

mina/pages/order/index.wxml

<view class="container">
     <view class="address-box">
        <view class="add-address" hidden="{
  {default_address}}">
            <view class="title" bindtap="addressSet">新增收货地址</view>
        </view>
        <view class="show-address" hidden="{
  {!default_address}}" bindtap="selectAddress">
            <view class="name-tel">{
  {default_address.name}}  {
  {default_address.mobile}}</view>
            <view class="addr-text">{
  {default_address.detail}}</view>
        </view>
     </view>
     <view class="goods-list">
        <view class="list-title">商品列表</view>
        <view class="a-goods" wx:for-items="{
  {goods_list}}" wx:key="{
  {index}}">
            <view class="img-box">
                <image src="{
  {item.pic_url}}" class="img" />
            </view>
            <view class="text-box">
                <view class="arow arow01">
                    <view class="goods-name">{
  {item.name}}</view>
                    <view class="goods-price">¥ {
  {item.price}}</view>
                </view>
                <view class="arow">
                    <view class="goods-label"></view>
                    <view class="goods-num">x {
  {item.number}}</view>
                </view>
            </view>
        </view>
     </view>
     <view class="peisong-way">
        <view class="row-box">
            <view class="row-label">配送方式</view>
            <view class="right-text" wx:if="{
  {yun_price > 0}}">快递</view>
            <view class="right-text" wx:if="{
  {yun_price == 0}}">包邮</view>
        </view>
        <view class="row-box">
            <view class="row-label">备注</view>
            <view class="right-text">
                <input name="remark" type="text" class="liuyan" placeholder="如需备注请输入" />
            </view>
        </view>
     </view>

     <view class="goods-info">
        <view class="row-box">
            <view class="row-label">商品金额</view>
            <view class="right-text">¥ {
  {pay_price}}</view>
        </view>
        <view class="row-box">
            <view class="row-label">运费</view>
            <view class="right-text">+ ¥ {
  {yun_price}}</view>
        </view>
     </view>

     <view class="jiesuan-box">
        <view class="left-price">
            <view class="total">合计:¥ {
  {total_price}}</view>
        </view>
        <button class="to-pay-btn" bindtap="createOrder">提交订单</button>
    </view>
</view>

mina/pages/order/index.js

//获取应用实例
var app = getApp();

Page({
    data: {
        goods_list: [],
        default_address: null,
        yun_price: "0.00",
        pay_price: "0.00",
        total_price: "0.00",
        params: null,
        express_address_id:0
    },
    onLoad: function (e) {
        var that = this;
        that.setData({
            params: JSON.parse(e.data)
        });
    },
    onShow: function () {
        var that = this;
         this.getOrderInfo();
    },
    createOrder: function (e) {
        wx.showLoading();
        var that = this;
        var data = {
            type: this.data.params.type,
            goods: JSON.stringify(this.data.params.goods),
            express_address_id: that.data.default_address.id
        };
        wx.request({
            url: app.buildUrl("/order/create"),
            header: app.getRequestHeader(),
            method: 'POST',
            data: data,
            success: function (res) {
                wx.hideLoading();
                var resp = res.data;
                if (resp.code != 200) {
                    app.alert({"content": resp.msg});
                    return;
                }
                wx.navigateTo({
                    url: "/pages/my/order_list"
                });
            }
        });

    },
    addressSet: function () {
        wx.navigateTo({
            url: "/pages/my/addressSet?id=0"
        });
    },
    selectAddress: function () {
        wx.navigateTo({
            url: "/pages/my/addressList"
        });
    },
    getOrderInfo: function () {
        var that = this;
        var data = {
            type: this.data.params.type,
            goods: JSON.stringify(this.data.params.goods)
        };
        wx.request({
            url: app.buildUrl("/order/info"),
            header: app.getRequestHeader(),
            method: 'POST',
            data: data,
            success: function (res) {
                var resp = res.data;
                if (resp.code != 200) {
                    app.alert({"content": resp.msg});
                    return;
                }

                that.setData({
                    goods_list: resp.data.food_list,
                    default_address: resp.data.default_address,
                    yun_price: resp.data.yun_price,
                    pay_price: resp.data.pay_price,
                    total_price: resp.data.total_price,
                });

                if( that.data.default_address ){
                    that.setData({
                         express_address_id: that.data.default_address.id
                    });
                }
            }
        });
    }

});

onLoad:function(e){}

params: JSON.parse(e.data)

JSON.parse()是JavaScript中的一个方法,用于将一个JSON字符串解析为对应的JavaScript对象。它接受一个JSON字符串作为参数,并返回一个JavaScript对象。

在你提供的引用中,JSON.parse()的用法如下:

var str = '{"name":"huangxiaojian","age":"23"}';
var obj = JSON.parse(str);
console.log(obj); // 输出:{ name: "huangxiaojian", age: "23" }

JSON.stringify()是JavaScript中的另一个方法,用于将一个JavaScript对象转换为对应的JSON字符串。它接受一个JavaScript对象作为参数,并返回一个JSON字符串。

在你提供的引用中,JSON.stringify()的用法如下:

var obj = { a: 1, b: 2 };
var str = JSON.stringify(obj);
console.log(str); // 输出:{"a":1,"b":2}

params: JSON.parse(e.data)的意思是将变量e.data中的JSON字符串解析为JavaScript对象。

createOrder:function(e){  }

wx.showLoading():

wx.showLoading(Object object) | 微信开放文档

显示 loading 提示框。需主动调用 wx.hideLoading 才能关闭提示框

wx.hideLoading():

web/controllers/api/Order.py

# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from flask import request, jsonify,g
from application import app, db
import json, decimal
from common.models.food.Food import Food
from common.models.pay.PayOrder import PayOrder
from common.libs.UrlManager import UrlManager
from common.libs.Helper import getCurrentDate
from common.libs.pay.PayService import PayService
from common.libs.pay.WeChatService import WeChatService
from common.libs.member.CartService import CartService
from common.models.member.MemberAddress import MemberAddress
from common.models.member.OauthMemberBind import OauthMemberBind


@route_api.route("/order/info", methods=[ "POST" ])
def orderInfo():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	req = request.values
	params_goods = req['goods'] if 'goods' in req else None
	member_info = g.member_info
	params_goods_list = []
	if params_goods:
		params_goods_list = json.loads(params_goods)

	food_dic = {}
	for item in params_goods_list:
		food_dic[item['id']] = item['number']

	food_ids = food_dic.keys()
	food_list = Food.query.filter(Food.id.in_(food_ids)).all()
	data_food_list = []
	yun_price = pay_price = decimal.Decimal(0.00)
	if food_list:
		for item in food_list:
			tmp_data = {
				"id": item.id,
				"name": item.name,
				"price": str(item.price),
				'pic_url': UrlManager.buildImageUrl(item.main_image),
				'number': food_dic[item.id]
			}
			pay_price = pay_price + item.price * int( food_dic[item.id] )
			data_food_list.append(tmp_data)

	# 获取地址
	address_info = MemberAddress.query.filter_by( is_default = 1,member_id = member_info.id,status = 1 ).first()
	default_address = ''
	if address_info:
		default_address = {
			"id": address_info.id,
			"name": address_info.nickname,
			"mobile": address_info.mobile,
			"address":"%s%s%s%s"%( address_info.province_str,address_info.city_str,address_info.area_str,address_info.address )
		}

	resp['data']['food_list'] = data_food_list
	resp['data']['pay_price'] = str(pay_price)
	resp['data']['yun_price'] = str(yun_price)
	resp['data']['total_price'] = str(pay_price + yun_price)
	resp['data']['default_address'] = default_address
	return jsonify(resp)

@route_api.route("/order/create", methods=[ "POST"])
def orderCreate():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	req = request.values
	type = req['type'] if 'type' in req else ''
	note = req['note'] if 'note' in req else ''
	express_address_id = int( req['express_address_id'] ) if 'express_address_id' in req and req['express_address_id'] else 0
	params_goods = req['goods'] if 'goods' in req else None

	items = []
	if params_goods:
		items = json.loads(params_goods)

	if len( items ) < 1:
		resp['code'] = -1
		resp['msg'] = "下单失败:没有选择商品~~"
		return jsonify(resp)

	address_info = MemberAddress.query.filter_by( id = express_address_id ).first()
	if not address_info or not address_info.status:
		resp['code'] = -1
		resp['msg'] = "下单失败:快递地址不对~~"
		return jsonify(resp)

	member_info = g.member_info
	target = PayService()
	params = {
		"note":note,
		'express_address_id':address_info.id,
		'express_info':{
			'mobile':address_info.mobile,
			'nickname':address_info.nickname,
			"address":"%s%s%s%s"%( address_info.province_str,address_info.city_str,address_info.area_str,address_info.address )
		}
	}
	resp = target.createOrder( member_info.id ,items ,params)
	#如果是来源购物车的,下单成功将下单的商品去掉
	if resp['code'] == 200 and type == "cart":
		CartService.deleteItem( member_info.id,items )

	return jsonify( resp )

@route_api.route("/order/pay", methods=[ "POST"])
def orderPay():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	member_info = g.member_info
	req = request.values
	order_sn = req['order_sn'] if 'order_sn' in req else ''
	pay_order_info = PayOrder.query.filter_by( order_sn = order_sn,member_id = member_info.id ).first()
	if not pay_order_info:
		resp['code'] = -1
		resp['msg'] = "系统繁忙。请稍后再试~~"
		return jsonify(resp)

	oauth_bind_info = OauthMemberBind.query.filter_by( member_id =  member_info.id ).first()
	if not oauth_bind_info:
		resp['code'] = -1
		resp['msg'] = "系统繁忙。请稍后再试~~"
		return jsonify(resp)

	config_mina = app.config['MINA_APP']
	notify_url = app.config['APP']['domain'] + config_mina['callback_url']

	target_wechat = WeChatService( merchant_key=config_mina['paykey'] )

	data = {
		'appid': config_mina['appid'],
		'mch_id': config_mina['mch_id'],
		'nonce_str': target_wechat.get_nonce_str(),
		'body': '订餐',  # 商品描述
		'out_trade_no': pay_order_info.order_sn,  # 商户订单号
		'total_fee': int( pay_order_info.total_price * 100 ),
		'notify_url': notify_url,
		'trade_type': "JSAPI",
		'openid': oauth_bind_info.openid
	}

	pay_info = target_wechat.get_pay_info( pay_data=data)

	#保存prepay_id为了后面发模板消息
	pay_order_info.prepay_id = pay_info['prepay_id']
	db.session.add( pay_order_info )
	db.session.commit()

	resp['data']['pay_info'] = pay_info
	return jsonify(resp)

@route_api.route("/order/callback", methods=[ "POST"])
def orderCallback():
	result_data = {
		'return_code': 'SUCCESS',
		'return_msg': 'OK'
	}
	header = {'Content-Type': 'application/xml'}
	config_mina = app.config['MINA_APP']
	target_wechat = WeChatService(merchant_key=config_mina['paykey'])
	callback_data = target_wechat.xml_to_dict( request.data )
	app.logger.info( callback_data  )
	sign = callback_data['sign']
	callback_data.pop( 'sign' )
	gene_sign = target_wechat.create_sign( callback_data )
	app.logger.info(gene_sign)
	if sign != gene_sign:
		result_data['return_code'] = result_data['return_msg'] = 'FAIL'
		return target_wechat.dict_to_xml(result_data), header
	if callback_data['result_code'] != 'SUCCESS':
		result_data['return_code'] = result_data['return_msg'] = 'FAIL'
		return target_wechat.dict_to_xml(result_data), header

	order_sn = callback_data['out_trade_no']
	pay_order_info = PayOrder.query.filter_by(order_sn=order_sn).first()
	if not pay_order_info:
		result_data['return_code'] = result_data['return_msg'] = 'FAIL'
		return target_wechat.dict_to_xml(result_data), header

	if int( pay_order_info.total_price * 100  ) != int( callback_data['total_fee'] ):
		result_data['return_code'] = result_data['return_msg'] = 'FAIL'
		return target_wechat.dict_to_xml(result_data), header

	if pay_order_info.status == 1:
		return target_wechat.dict_to_xml(result_data), header

	target_pay = PayService()
	target_pay.orderSuccess( pay_order_id = pay_order_info.id,params = { "pay_sn":callback_data['transaction_id'] } )
	target_pay.addPayCallbackData( pay_order_id = pay_order_info.id, data = request.data)
	return target_wechat.dict_to_xml(result_data), header

@route_api.route("/order/ops", methods=[ "POST"])
def orderOps():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	req = request.values
	member_info = g.member_info
	order_sn = req['order_sn'] if 'order_sn' in req else ''
	act = req['act'] if 'act' in req else ''
	pay_order_info = PayOrder.query.filter_by(order_sn=order_sn, member_id=member_info.id).first()
	if not pay_order_info:
		resp['code'] = -1
		resp['msg'] = "系统繁忙。请稍后再试~~"
		return jsonify(resp)


	if act == "cancel":
		target_pay = PayService( )
		ret = target_pay.closeOrder( pay_order_id=pay_order_info.id )
		if not ret:
			resp['code'] = -1
			resp['msg'] = "系统繁忙。请稍后再试~~"
			return jsonify(resp)
	elif act == "confirm":
		pay_order_info.express_status = 1
		pay_order_info.updated_time = getCurrentDate()
		db.session.add( pay_order_info )
		db.session.commit()

	return jsonify(resp)




@route_api.route("/order/create", methods=[ "POST"])

type: cart
goods: [{"id":23, "price":"36.00", "number":1}, {"id":18, "price":"36.00", "number":1}]

json.loads()

是Python标准库json模块中的一个方法,用于将JSON字符串转换为Python数据类型。它的使用方法如下所示:

import json

json_str = '{"name": "John", "age": 30, "city": "New York"}'
data = json.loads(json_str)

print(data)  # 输出:{'name': 'John', 'age': 30, 'city': 'New York'}

在上面的例子中,我们首先导入了json模块。然后,我们定义了一个JSON字符串json_str,其中包含了一个名为"name"的键和对应的值"John",一个名为"age"的键和对应的值30,以及一个名为"city"的键和对应的值"New York"。接下来,我们使用json.loads()方法将JSON字符串转换为Python数据类型,并将结果赋值给变量data。最后,我们打印出data的值,即转换后的Python字典。

需要注意的是,json.loads()只适用于读取JSON字符串,如果想要从JSON文件中读取数据,请使用json.load()方法

jsonify()

jsonify()是Flask框架中的一个函数,用于将Python对象转换为JSON格式的响应。它会自动设置响应头部的"Content-Type"为"application/json",简化了返回JSON数据的操作。

以下是两种使用jsonify()函数返回JSON数据的例子:

使用字典作为参数:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/json1', methods=['GET'])
def json_demo1():
    return jsonify({
        "username": 'yoyo',
        "email": "111@qq.com"
    })

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

使用键值对作为参数:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/json2', methods=['GET'])
def json_demo2():
    return jsonify(
        username="yoyo",
        email="111@qq.com"
    )

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

这两个例子中,当访问对应的路由时,会返回一个JSON格式的响应,其中包含了指定的键值对或字典。

Food.query.filter(Food.id.in_(food_ids)).all()中in的作用

Food.query.filter(Food.id.in_(food_ids)).all()中,in_是一个SQLAlchemy的查询操作符,用于判断一个字段的值是否在给定的列表中。它可以用于过滤查询结果,只返回满足条件的记录。

具体来说,Food.id.in_(food_ids)表示筛选出Food表中id字段的值在food_ids列表中的记录。这样,filter()方法就会返回满足这个条件的所有记录。

举个例子,假设food_ids是一个包含[1, 2, 3]的列表,那么Food.query.filter(Food.id.in_(food_ids)).all()将返回Food表中id为1、2、3的所有记录

数据库common/models/member/MemberAddress

DROP TABLE IF EXISTS `member_address`;
CREATE TABLE `member_address` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `member_id` int(11) NOT NULL DEFAULT '0' COMMENT '会员id',
  `nickname` varchar(20) NOT NULL DEFAULT '' COMMENT '收货人姓名',
  `mobile` varchar(11) NOT NULL DEFAULT '' COMMENT '收货人手机号码',
  `province_id` int(11) NOT NULL DEFAULT '0' COMMENT '省id',
  `province_str` varchar(50) NOT NULL DEFAULT '' COMMENT '省名称',
  `city_id` int(11) NOT NULL DEFAULT '0' COMMENT '城市id',
  `city_str` varchar(50) NOT NULL DEFAULT '' COMMENT '市名称',
  `area_id` int(11) NOT NULL DEFAULT '0' COMMENT '区域id',
  `area_str` varchar(50) NOT NULL DEFAULT '' COMMENT '区域名称',
  `address` varchar(100) NOT NULL DEFAULT '' COMMENT '详细地址',
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否有效 1:有效 0:无效',
  `is_default` TINYINT(1)  NOT NULL  DEFAULT '0'  COMMENT '默认地址',
  `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后一次更新时间',
  `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',
  PRIMARY KEY (`id`),
  KEY `idx_member_id_status` (`member_id`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员收货地址';
flask-sqlacodegen 'mysql://root:root@127.0.0.1/food_db' --tables member_address --outfile "common/models/member/MemberAddress.py"  --flask

注意: Order.py   Cart.py Member.py 这些文件要导入到__init__.py中

若不导入则在小程序页面中显示  页面不存在

web/controllers/api/__init__.py

# -*- coding: utf-8 -*-
from flask import Blueprint
route_api = Blueprint( 'api_page',__name__ )
from web.controllers.api.Member import *
from web.controllers.api.Food import *
from web.controllers.api.Order import *

from web.controllers.api.Cart import *


@route_api.route("/")
def index():
    return "Mina Api V1.0~~"

common/libs/pay/PayService.py

# -*- coding: utf-8 -*-
import hashlib,time,random,decimal,json
from application import  app,db
from common.models.food.Food import Food
from common.models.food.FoodSaleChangeLog import FoodSaleChangeLog
from common.models.pay.PayOrder import PayOrder
from common.models.pay.PayOrderItem import PayOrderItem
from common.models.pay.PayOrderCallbackData import PayOrderCallbackData
from common.libs.Helper import getCurrentDate
from common.libs.queue.QueueService import QueueService
from common.libs.food.FoodService import FoodService
class PayService():

    def __init__(self):
        pass

    def createOrder(self,member_id,items = None,params = None):
        resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
        pay_price  = decimal.Decimal( 0.00 )
        continue_cnt = 0
        food_ids = []
        for item in items:
            if decimal.Decimal( item['price'] ) < 0 :
                continue_cnt += 1
                continue

            pay_price = pay_price +  decimal.Decimal( item['price'] ) * int( item['number'] )
            food_ids.append( item['id'] )

        if continue_cnt >= len(items ) :
            resp['code'] = -1
            resp['msg'] = '商品items为空~~'
            return resp

        yun_price = params['yun_price'] if params and 'yun_price' in params else 0
        note = params['note'] if params and 'note' in params else ''
        express_address_id = params['express_address_id'] if params and 'express_address_id' in params else 0
        express_info = params['express_info'] if params and 'express_info' in params else {}
        yun_price = decimal.Decimal( yun_price )
        total_price = pay_price + yun_price
        try:
            #为了防止并发库存出问题了,我们坐下selectfor update, 这里可以给大家演示下
            tmp_food_list = db.session.query( Food ).filter( Food.id.in_( food_ids ) )\
                .with_for_update().all()

            tmp_food_stock_mapping = {}
            for tmp_item in tmp_food_list:
                tmp_food_stock_mapping[ tmp_item.id ] = tmp_item.stock

            model_pay_order = PayOrder()
            model_pay_order.order_sn = self.geneOrderSn()
            model_pay_order.member_id = member_id
            model_pay_order.total_price = total_price
            model_pay_order.yun_price = yun_price
            model_pay_order.pay_price = pay_price
            model_pay_order.note = note
            model_pay_order.status = -8
            model_pay_order.express_status = -8
            model_pay_order.express_address_id = express_address_id
            model_pay_order.express_info = json.dumps(  express_info )
            model_pay_order.updated_time = model_pay_order.created_time = getCurrentDate()
            db.session.add( model_pay_order )
            #db.session.flush()
            for item in items:
                tmp_left_stock =  tmp_food_stock_mapping[ item['id'] ]

                if decimal.Decimal(item['price']) < 0:
                    continue

                if int( item['number'] ) > int( tmp_left_stock ):
                    raise Exception( "您购买的这美食太火爆了,剩余:%s,你购买%s~~"%( tmp_left_stock,item['number'] ) )

                tmp_ret = Food.query.filter_by( id = item['id'] ).update({
                    "stock":int(tmp_left_stock) - int(item['number'])
                })
                if not tmp_ret:
                    raise Exception("下单失败请重新下单")

                tmp_pay_item = PayOrderItem()
                tmp_pay_item.pay_order_id = model_pay_order.id
                tmp_pay_item.member_id = member_id
                tmp_pay_item.quantity = item['number']
                tmp_pay_item.price = item['price']
                tmp_pay_item.food_id = item['id']
                tmp_pay_item.note = note
                tmp_pay_item.updated_time = tmp_pay_item.created_time = getCurrentDate()
                db.session.add( tmp_pay_item )
                #db.session.flush()

                FoodService.setStockChangeLog( item['id'],-item['number'],"在线购买" )
            db.session.commit()
            resp['data'] = {
                'id' : model_pay_order.id,
                'order_sn' : model_pay_order.order_sn,
                'total_price':str( total_price )
            }
        except Exception as e:
            db.session.rollback()
            print( e )
            resp['code'] = -1
            resp['msg'] = "下单失败请重新下单"
            resp['msg'] = str(e)
            return resp
        return resp

    def closeOrder(self,pay_order_id = 0):
        if pay_order_id < 1:
            return False
        pay_order_info = PayOrder.query.filter_by( id =  pay_order_id ,status = -8 ).first()
        if not pay_order_info:
            return False

        pay_order_items = PayOrderItem.query.filter_by( pay_order_id = pay_order_id ).all()
        if pay_order_items:
            #需要归还库存
            for item in pay_order_items:
                tmp_food_info = Food.query.filter_by( id = item.food_id ).first()
                if tmp_food_info:
                    tmp_food_info.stock = tmp_food_info.stock + item.quantity
                    tmp_food_info.updated_time = getCurrentDate()
                    db.session.add( tmp_food_info )
                    db.session.commit()
                    FoodService.setStockChangeLog( item.food_id, item.quantity, "订单取消")

        pay_order_info.status = 0
        pay_order_info.updated_time = getCurrentDate()
        db.session.add( pay_order_info )
        db.session.commit()
        return True

    def orderSuccess(self,pay_order_id = 0,params = None):
        try:
            pay_order_info = PayOrder.query.filter_by( id = pay_order_id ).first()
            if not pay_order_info or pay_order_info.status not in [ -8,-7 ]:
                return True

            pay_order_info.pay_sn = params['pay_sn'] if params and 'pay_sn' in params else ''
            pay_order_info.status = 1
            pay_order_info.express_status = -7
            pay_order_info.updated_time = getCurrentDate()
            db.session.add( pay_order_info  )


            pay_order_items = PayOrderItem.query.filter_by( pay_order_id = pay_order_id ).all()
            for order_item in pay_order_items:
                tmp_model_sale_log = FoodSaleChangeLog()
                tmp_model_sale_log.food_id = order_item.food_id
                tmp_model_sale_log.quantity = order_item.quantity
                tmp_model_sale_log.price = order_item.price
                tmp_model_sale_log.member_id = order_item.member_id
                tmp_model_sale_log.created_time = getCurrentDate()
                db.session.add( tmp_model_sale_log )

            db.session.commit()
        except Exception as e:
            db.session.rollback()
            print(e)
            return False

        #加入通知队列,做消息提醒和
        QueueService.addQueue( "pay",{
            "member_id": pay_order_info.member_id,
            "pay_order_id":pay_order_info.id
        })
        return True

    def addPayCallbackData(self,pay_order_id = 0,type = 'pay',data = ''):
        model_callback = PayOrderCallbackData()
        model_callback.pay_order_id = pay_order_id
        if type == "pay":
            model_callback.pay_data = data
            model_callback.refund_data = ''
        else:
            model_callback.refund_data = data
            model_callback.pay_data = ''

        model_callback.created_time = model_callback.updated_time = getCurrentDate()
        db.session.add( model_callback )
        db.session.commit()
        return True

    def geneOrderSn(self):
        m = hashlib.md5()
        sn = None
        while True:
            str = "%s-%s"%( int( round( time.time() * 1000) ),random.randint( 0,9999999 ) )
            m.update(str.encode("utf-8"))
            sn = m.hexdigest()
            if not PayOrder.query.filter_by( order_sn = sn  ).first():
                break
        return sn

createOrder()

.with_for_update()

.with_for_update()是SQLAlchemy中的一个方法,用于在数据库事务中锁定查询结果,以防止其他事务对查询结果进行修改。

这个方法通常与filter()filter_by()一起使用,用于指定查询条件。在查询结果上调用.with_for_update()方法后,查询结果将被锁定,其他事务将无法修改这些结果,直到当前事务提交或回滚。

以下是两个例子来演示.with_for_update()的使用:

在模型查询中使用.with_for_update()

# 假设有一个名为User的模型类
user = User.query.filter(User.id == 1).with_for_update().first()
# 对查询结果进行操作
user.name = 'New Name'
db.session.commit()

在数据库会话中使用.with_for_update()

# 假设有一个名为Address的模型类
addr = Address.query.filter_by(user_id=3).with_for_update().first()
if addr.status == 0:
    addr.status = 1
    db.session.commit()

这些例子展示了如何在查询结果上使用.with_for_update()方法,并在事务中对查询结果进行修改。

.with_for_update()的作用是在数据库事务中对查询结果进行加锁,以确保其他事务无法修改这些记录,直到当前事务结束。

在给定的代码中,.with_for_update()被用于查询语句中的db.session.query()方法后面。这意味着查询结果将被锁定,并且其他事务无法修改这些记录,直到当前事务结束。

这在并发环境中非常有用,可以防止其他事务在当前事务处理期间修改查询结果。这样可以确保查询结果的一致性和可靠性。

json.dumps()

Python JSON_w3cschool

函数 描述
json.dumps 将 Python 对象编码成 JSON 字符串
json.loads 将已编码的 JSON 字符串解码为 Python 对象


订单列表展示功能

mina/pages/my/order_list.wxml

<view class="container">
    <view class="status-box">
        <view bindtap="statusTap" class="status-label {
  {index == currentType ? 'active' : ''}}" wx:for-items="{
  {statusType}}" wx:key="{
  {index}}" data-index="{
  {index}}">
            {
  {item}}
            <view class="{
  {tabClass[index]}}"></view>
        </view>
    </view>
    <view class="no-order" wx:if="{
  {!order_list.length}}">
        <image src="/images/no-order.png" class="no-order-img"></image>
        <view class="text">暂无订单</view>
    </view>
    <view class="order-list" wx:if="{
  {order_list.length}}">
        <view class="a-order" wx:for="{
  {order_list}}" wx:key="{
  {index}}" wx:for-item="item">
            <view class="order-date" data-id="{
  {item.order_sn}}" bindtap="orderDetail">
                <view class="date-box">下单时间:{
  {item.date}}</view>
                <view class="status {
  {(item.status==0 || item.status==1) ? '':'red'}}">{
  {item.status_desc}}</view>
            </view>
            <view class="goods-info"  data-id="{
  {item.order_sn}}" bindtap="orderDetail">
                <view class="goods-des">
                   <view>订单号:{
  {item.order_number}} </view>
                   <view wx:if="{
  {item.note && item.note != ''}}">备注: {
  {item.note}}</view>
                </view>
            </view>
            <view >
                <scroll-view class="goods-img-container" scroll-x="true">
                    <view class="img-box" wx:for="{
  {item.goods_list}}" wx:for-item="itemGood">
                        <image src="{
  {itemGood.pic_url}}" class="goods-img"></image>
                    </view>
                </scroll-view>
            </view>
            <view class="price-box">
                <view class="total-price">合计:¥ {
  {item.total_price}}</view>
                <view class="btn cancel-btn" bindtap="orderCancel" data-id="{
  {item.order_sn}}" wx:if="{
  {item.status==-8}}">取消订单</view>
                <view class="btn topay-btn" bindtap="toPay" data-id="{
  {item.order_sn}}" wx:if="{
  {item.status==-8}}">马上付款</view>

                <view class="btn topay-btn" bindtap="orderConfirm" data-id="{
  {item.order_sn}}" wx:if="{
  {item.status==-6}}">确认收货</view>
                <view class="btn topay-btn" bindtap="orderComment" data-id="{
  {item.order_sn}}" wx:if="{
  {item.status==-5}}">走,去评价</view>
            </view>
        </view>
    </view>
</view>

mina/pages/my/order_list.js

var app = getApp();
Page({
    data: {
        order_list:[],
        statusType: ["待付款", "待发货", "待确认", "待评价", "已完成","已关闭"],
        status:[ "-8","-7","-6","-5","1","0" ],
        currentType: 0,
        tabClass: ["", "", "", "", "", ""]
    },
    statusTap: function (e) {
        var curType = e.currentTarget.dataset.index;
        this.setData({
            currentType: curType
        });
        this.getPayOrder();
    },
    orderDetail: function (e) {
        wx.navigateTo({
            url: "/pages/my/order_info?order_sn=" + e.currentTarget.dataset.id
        })
    },
    onLoad: function (options) {
        // 生命周期函数--监听页面加载
    },
    onShow: function () {
        this.getPayOrder();
    },
    orderCancel:function( e ){
        this.orderOps( e.currentTarget.dataset.id,"cancel","确定取消订单?" );
    },
    getPayOrder:function(){
        var that = this;
        wx.request({
            url: app.buildUrl("/my/order"),
            header: app.getRequestHeader(),
            data: {
                status: that.data.status[ that.data.currentType ]
            },
            success: function (res) {
                var resp = res.data;
                if (resp.code != 200) {
                    app.alert({"content": resp.msg});
                    return;
                }

                that.setData({
                   order_list:resp.data.pay_order_list
                });
            }
        });
    },
    toPay:function( e ){
        var that = this;
        wx.request({
            url: app.buildUrl("/order/pay"),
            header: app.getRequestHeader(),
            method: 'POST',
            data: {
                order_sn: e.currentTarget.dataset.id
            },
            success: function (res) {
                var resp = res.data;
                if (resp.code != 200) {
                    app.alert({"content": resp.msg});
                    return;
                }
                var pay_info = resp.data.pay_info;
                wx.requestPayment({
                    'timeStamp': pay_info.timeStamp,
                    'nonceStr': pay_info.nonceStr,
                    'package': pay_info.package,
                    'signType': 'MD5',
                    'paySign': pay_info.paySign,
                    'success': function (res) {
                    },
                    'fail': function (res) {
                    }
                });
            }
        });
    },
    orderConfirm:function( e ){
        this.orderOps( e.currentTarget.dataset.id,"confirm","确定收到?" );
    },
    orderComment:function( e ){
        wx.navigateTo({
            url: "/pages/my/comment?order_sn=" + e.currentTarget.dataset.id
        });
    },
    orderOps:function(order_sn,act,msg){
        var that = this;
        var params = {
            "content":msg,
            "cb_confirm":function(){
                wx.request({
                    url: app.buildUrl("/order/ops"),
                    header: app.getRequestHeader(),
                    method: 'POST',
                    data: {
                        order_sn: order_sn,
                        act:act
                    },
                    success: function (res) {
                        var resp = res.data;
                        app.alert({"content": resp.msg});
                        if ( resp.code == 200) {
                            that.getPayOrder();
                        }
                    }
                });
            }
        };
        app.tip( params );
    }
});

web/controllers/api/My.py

# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from flask import request, jsonify,g
from common.models.food.Food import Food
from application import app,db
from common.models.pay.PayOrder import PayOrder
from common.models.pay.PayOrderItem import PayOrderItem
from common.libs.UrlManager import UrlManager
from common.libs.Helper import selectFilterObj,getDictFilterField,getCurrentDate
from common.models.member.MemberComments import MemberComments
import json,datetime

@route_api.route("/my/order")
def myOrderList():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	member_info = g.member_info
	req = request.values
	status = int( req['status'] ) if 'status' in req else 0
	query = PayOrder.query.filter_by( member_id = member_info.id )
	if status == -8 :#等待付款
		query = query.filter( PayOrder.status == -8 )
	elif status == -7:#待发货
		query = query.filter( PayOrder.status == 1,PayOrder.express_status == -7,PayOrder.comment_status == 0 )
	elif status == -6:#待确认
		query = query.filter(PayOrder.status == 1, PayOrder.express_status == -6,PayOrder.comment_status == 0)
	elif status == -5:#待评价
		query = query.filter(PayOrder.status == 1, PayOrder.express_status == 1,PayOrder.comment_status == 0)
	elif status == 1:#已完成
		query = query.filter(PayOrder.status == 1, PayOrder.express_status == 1,PayOrder.comment_status == 1 )
	else:
		query = query.filter( PayOrder.status == 0 )

	pay_order_list = query.order_by( PayOrder.id.desc() ).all()
	data_pay_order_list = []
	if pay_order_list:
		pay_order_ids = selectFilterObj( pay_order_list,"id" )
		pay_order_item_list = PayOrderItem.query.filter( PayOrderItem.pay_order_id.in_( pay_order_ids ) ).all()
		food_ids = selectFilterObj( pay_order_item_list,"food_id" )
		food_map = getDictFilterField( Food,Food.id,"id",food_ids )
		pay_order_item_map = {}
		if pay_order_item_list:
			for item in pay_order_item_list:
				if item.pay_order_id not in pay_order_item_map:
					pay_order_item_map[ item.pay_order_id ] = []

				tmp_food_info = food_map[ item.food_id ]
				pay_order_item_map[item.pay_order_id].append({
					'id':item.id,
					'food_id':item.food_id,
					'quantity':item.quantity,
					'price':str( item.price ),
					'pic_url':UrlManager.buildImageUrl( tmp_food_info.main_image ),
					'name':tmp_food_info.name
				})


		for item in pay_order_list:
			tmp_data = {
				'status':item.pay_status,
				'status_desc':item.status_desc,
				'date':item.created_time.strftime("%Y-%m-%d %H:%M:%S"),
				'order_number':item.order_number,
				'order_sn':item.order_sn,
				'note':item.note,
				'total_price':str( item.total_price ),
				'goods_list':pay_order_item_map[ item.id ]
			}

			data_pay_order_list.append( tmp_data )
	resp['data']['pay_order_list'] = data_pay_order_list
	return jsonify(resp)

@route_api.route("/my/order/info")
def myOrderInfo():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	member_info = g.member_info
	req = request.values
	order_sn = req['order_sn'] if 'order_sn' in req else ''
	pay_order_info = PayOrder.query.filter_by( member_id=member_info.id ,order_sn = order_sn).first()
	if not pay_order_info:
		resp['code'] = -1
		resp['msg'] = "系统繁忙,请稍后再试~~"
		return jsonify(resp)

	express_info = {}
	if pay_order_info.express_info:
		express_info = json.loads( pay_order_info.express_info )

	tmp_deadline = pay_order_info.created_time + datetime.timedelta(minutes=30)
	info = {
		"order_sn":pay_order_info.order_sn,
		"status":pay_order_info.pay_status,
		"status_desc":pay_order_info.status_desc,
		"pay_price":str( pay_order_info.pay_price),
		"yun_price":str( pay_order_info.yun_price),
		"total_price":str( pay_order_info.total_price),
		"address":express_info,
		"goods": [],
		"deadline":tmp_deadline.strftime("%Y-%m-%d %H:%M")
	}

	pay_order_items = PayOrderItem.query.filter_by( pay_order_id = pay_order_info.id  ).all()
	if pay_order_items:
		food_ids = selectFilterObj( pay_order_items , "food_id")
		food_map = getDictFilterField(Food, Food.id, "id", food_ids)
		for item in pay_order_items:
			tmp_food_info = food_map[item.food_id]
			tmp_data = {
				"name": tmp_food_info.name,
				"price": str( item.price ),
				"unit": item.quantity,
				"pic_url": UrlManager.buildImageUrl( tmp_food_info.main_image ),
			}
			info['goods'].append( tmp_data )
	resp['data']['info'] = info
	return jsonify(resp)


@route_api.route("/my/comment/add",methods = [ "POST" ])
def myCommentAdd():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	member_info = g.member_info
	req = request.values
	order_sn = req['order_sn'] if 'order_sn' in req else ''
	score = req['score'] if 'score' in req else 10
	content = req['content'] if 'content' in req else ''

	pay_order_info = PayOrder.query.filter_by( member_id=member_info.id ,order_sn = order_sn).first()
	if not pay_order_info:
		resp['code'] = -1
		resp['msg'] = "系统繁忙,请稍后再试~~"
		return jsonify(resp)

	if pay_order_info.comment_status:
		resp['code'] = -1
		resp['msg'] = "已经评价过了~~"
		return jsonify(resp)

	pay_order_items = PayOrderItem.query.filter_by( pay_order_id = pay_order_info.id ).all()
	food_ids = selectFilterObj( pay_order_items,"food_id" )
	tmp_food_ids_str = '_'.join(str(s) for s in food_ids if s not in [None])
	model_comment = MemberComments()
	model_comment.food_ids = "_%s_"%tmp_food_ids_str
	model_comment.member_id = member_info.id
	model_comment.pay_order_id = pay_order_info.id
	model_comment.score = score
	model_comment.content = content
	db.session.add( model_comment )

	pay_order_info.comment_status = 1
	pay_order_info.updated_time = getCurrentDate()
	db.session.add( pay_order_info )

	db.session.commit()
	return jsonify(resp)

@route_api.route("/my/comment/list" )
def myCommentList():
	resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
	member_info = g.member_info
	comment_list = MemberComments.query.filter_by( member_id=member_info.id )\
		.order_by(MemberComments.id.desc()).all()
	data_comment_list = []
	if comment_list:
		pay_order_ids = selectFilterObj( comment_list,"pay_order_id" )
		pay_order_map = getDictFilterField( PayOrder,PayOrder.id,"id",pay_order_ids )
		for item in comment_list:
			tmp_pay_order_info = pay_order_map[ item.pay_order_id ]
			tmp_data = {
				"date":item.created_time.strftime("%Y-%m-%d %H:%M:%S"),
				"content":item.content,
				"order_number":tmp_pay_order_info.order_number
			}
			data_comment_list.append( tmp_data )
	resp['data']['list'] = data_comment_list
	return jsonify(resp)



相关推荐

  1. Flask 会员列表展示

    2024-01-21 14:42:02       32 阅读
  2. 微信程序 ---- 慕尚花坊 订单列表

    2024-01-21 14:42:02       17 阅读
  3. 微信程序 提交

    2024-01-21 14:42:02       18 阅读
  4. flask 程序 菜品详情和分享功能

    2024-01-21 14:42:02       39 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-21 14:42:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-21 14:42:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-21 14:42:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-21 14:42:02       20 阅读

热门阅读

  1. SQL字典

    2024-01-21 14:42:02       31 阅读
  2. 肿瘤面积(c++题解)

    2024-01-21 14:42:02       35 阅读
  3. docker 部署 springboot 2.6.13 jar包流程笔记

    2024-01-21 14:42:02       37 阅读
  4. 191. 位1的个数

    2024-01-21 14:42:02       34 阅读
  5. ElasticSearch 7.x现网运行问题汇集2

    2024-01-21 14:42:02       32 阅读
  6. [LeetCode]-动态规划-4

    2024-01-21 14:42:02       28 阅读
  7. 单例模式实现及优化(C++11)

    2024-01-21 14:42:02       31 阅读