flask 与 小程序 购物车 展示功能

flask 与 小程序 购物车 展示功能_第1张图片

mina/pages/cart/index.wxml



    
        购物车空空如也~
    
    
        去逛逛
    

    
        购物车
        
        
    

    
        
            
                
                    
                        
                    
                    
                        {{item.name}}
                        ¥ {{item.price}}
                        
                            -
                            
                            +
                        
                    
                
            
        
    
    
        
            全选
            
        
        
        
    

知识点一:简要代码分析

根据提供的代码,是一个视图组件,它有一个类名为to-pay-btn,并根据noSelectsaveHidden的值来动态添加或移除no-select类。当saveHiddenfalse时,该视图组件会被隐藏。同时,当用户点击该视图组件时,会触发toPayOrder方法。

web/controllers/api/Cart.py

@route_api.route("/cart/index")
def cartIndex():
    resp = {'code': 200, 'msg': '添加购物车成功~', 'data': {}}
    member_info = g.member_info
    if not member_info:
        resp['code'] = -1
        resp['msg'] = "获取失败,伪登录~~"
        return jsonify(resp)
    cart_list = MemberCart.query.filter_by( member_id=member_info.id).all()
    data_cart_list = []
    if cart_list:
        food_ids = selectFilterObj( cart_list,"food_id" )
        food_map = getDictFilterField( Food,Food.id,"id",food_ids )
        for item in cart_list:
            tmp_food_info = food_map[ item.food_id ]
            tmp_data = {
                "id":item.id,
                "number":item.quantity,
                "food_id": item.food_id,
                "name":tmp_food_info.name,
                "price":str( tmp_food_info.price ),
                "pic_url": UrlManager.buildImageUrl( tmp_food_info.main_image ),
                "active":True
            }
            data_cart_list.append( tmp_data )

    resp['data']['list'] = data_cart_list
    return jsonify(resp)

common/libs/Helper.py

'''
根据某个字段获取一个dic出来
'''
def getDictFilterField( db_model,select_filed,key_field,id_list ):
    ret = {}
    query = db_model.query
    if id_list and len( id_list ) > 0:
        query = query.filter( select_filed.in_( id_list ) )

    list = query.all()
    if not list:
        return ret
    for item in list:
        if not hasattr( item,key_field ):
            break

        ret[ getattr( item,key_field ) ] = item
    return ret



def selectFilterObj( obj,field ):
    ret = []
    for item in obj:
        if not hasattr(item, field ):
            break
        if getattr( item,field )  in ret:
            continue
        ret.append( getattr( item,field ) )
    return ret

food_ids = selectFilterObj( cart_list,"food_id" )

从cart_list里取得food_id

Python getattr() 函数_w3cschool

然后通过下面代码获取mapping的一个信息

food_map = getDictFilterField( Food,Food.id,"id",food_ids )

第一个查 Food对象,

再在Food表里查询id字段等于  “id” 这个值里面的,它的key值 是 ”id“

最终返回的结果集与  fodd_ids 相关

问题1: query = query.filter( select_filed.in_( id_list ) ) 中in_是什么

in_是SQLAlchemy中的一个操作符,用于在查询中判断某个字段的值是否在给定的列表中。它类似于SQL中的IN操作符。

下面是一个示例演示如何使用in_操作符:

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

# 创建数据库连接
engine = create_engine('sqlite:///test.db')
Session = sessionmaker(bind=engine)
session = Session()
# 创建模型类
Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)

# 查询name字段值在给定列表中的记录
id_list = [1, 2, 3]
query = session.query(User).filter(User.name.in_(id_list))
result = query.all()

# 输出查询结果
for user in result:
    print(user.name)

这个示例中,我们创建了一个名为users的表,其中包含idname两个字段。然后我们使用in_操作符来查询name字段值在给定列表id_list中的记录,并将结果打印出来。

问题2: 为什么此处用filter而不是filter_by?

filter和filter_by都是SQLAlchemy中用于查询的方法,它们的区别如下:

  • filter是基于关键字参数的查询方法,可以根据指定的条件进行过滤。例如,可以使用filter方法查询年龄大于18岁的用户:
session.query(User).filter(User.age > 18).all()
  • filter_by是基于属性名和属性值的查询方法,可以直接指定属性名和属性值进行过滤。例如,可以使用filter_by方法查询用户名为"John"的用户:
session.query(User).filter_by(username="John").all()

总结来说,filter方法更加灵活,可以使用各种条件进行过滤,而filter_by方法更加简洁,适合于直接根据属性名和属性值进行过滤。

mina/pages/cart/index.js

//index.js
var app = getApp();
Page({
    data: {},
    onLoad: function () {
        this.getCartList();
    },
    //每项前面的选中框
    selectTap: function (e) {
        var index = e.currentTarget.dataset.index;
        var list = this.data.list;
        if (index !== "" && index != null) {
            list[ parseInt(index) ].active = !list[ parseInt(index) ].active;
            this.setPageData(this.getSaveHide(), this.totalPrice(), this.allSelect(), this.noSelect(), list);
        }
    },
    //计算是否全选了
    allSelect: function () {
        var list = this.data.list;
        var allSelect = false;
        for (var i = 0; i < list.length; i++) {
            var curItem = list[i];
            if (curItem.active) {
                allSelect = true;
            } else {
                allSelect = false;
                break;
            }
        }
        return allSelect;
    },
    //计算是否都没有选
    noSelect: function () {
        var list = this.data.list;
        var noSelect = 0;
        for (var i = 0; i < list.length; i++) {
            var curItem = list[i];
            if (!curItem.active) {
                noSelect++;
            }
        }
        if (noSelect == list.length) {
            return true;
        } else {
            return false;
        }
    },
    //全选和全部选按钮
    bindAllSelect: function () {
        var currentAllSelect = this.data.allSelect;
        var list = this.data.list;
        for (var i = 0; i < list.length; i++) {
            list[i].active = !currentAllSelect;
        }
        this.setPageData(this.getSaveHide(), this.totalPrice(), !currentAllSelect, this.noSelect(), list);
    },
    //加数量
    jiaBtnTap: function (e) {
        var that = this;
        var index = e.currentTarget.dataset.index;
        var list = that.data.list;
        list[parseInt(index)].number++;
        that.setPageData(that.getSaveHide(), that.totalPrice(), that.allSelect(), that.noSelect(), list);
    },
    //减数量
    jianBtnTap: function (e) {
        var index = e.currentTarget.dataset.index;
        var list = this.data.list;
        if (list[parseInt(index)].number > 1) {
            list[parseInt(index)].number--;
            this.setPageData(this.getSaveHide(), this.totalPrice(), this.allSelect(), this.noSelect(), list);
        }
    },
    //编辑默认全不选
    editTap: function () {
        var list = this.data.list;
        for (var i = 0; i < list.length; i++) {
            var curItem = list[i];
            curItem.active = false;
        }
        this.setPageData(!this.getSaveHide(), this.totalPrice(), this.allSelect(), this.noSelect(), list);
    },
    //选中完成默认全选
    saveTap: function () {
        var list = this.data.list;
        for (var i = 0; i < list.length; i++) {
            var curItem = list[i];
            curItem.active = true;
        }
        this.setPageData(!this.getSaveHide(), this.totalPrice(), this.allSelect(), this.noSelect(), list);
    },
    getSaveHide: function () {
        return this.data.saveHidden;
    },
    totalPrice: function () {
        var list = this.data.list;
        var totalPrice = 0.00;
        for (var i = 0; i < list.length; i++) {
            if ( !list[i].active) {
                continue;
            }
            totalPrice = totalPrice + parseFloat( list[i].price );
        }
        return totalPrice;
    },
    setPageData: function (saveHidden, total, allSelect, noSelect, list) {
        this.setData({
            list: list,
            saveHidden: saveHidden,
            totalPrice: total,
            allSelect: allSelect,
            noSelect: noSelect,
        });
    },
    //去结算
    toPayOrder: function () {
        wx.navigateTo({
            url: "/pages/order/index"
        });
    },
    //如果没有显示去光光按钮事件
    toIndexPage: function () {
        wx.switchTab({
            url: "/pages/food/index"
        });
    },
    //选中删除的数据
    deleteSelected: function () {
        var list = this.data.list;
        var cart_ids = [];
        list = list.filter(function ( item ) {
            if( !item.active ){
                cart_ids.append( item.id );
            }
            return !item.active;
        });
        this.setPageData( this.getSaveHide(), this.totalPrice(), this.allSelect(), this.noSelect(), list);
        //发送请求到后台删除数据
    },
    getCartList: function () {
        this.setData({
            list: [
                {
                    "id": 1080,
					"food_id":"5",
                    "pic_url": "/images/food.jpg",
                    "name": "小鸡炖蘑菇-1",
                    "price": "85.00",
                    "active": true,
                    "number": 1
                },
                {
                    "id": 1081,
					"food_id":"6",
                    "pic_url": "/images/food.jpg",
                    "name": "小鸡炖蘑菇-2",
                    "price": "85.00",
                    "active": true,
                    "number": 1
                }
            ],
            saveHidden: true,
            totalPrice: "85.00",
            allSelect: true,
            noSelect: false,
        });
        this.setPageData( this.getSaveHide(), this.totalPrice(), this.allSelect(), this.noSelect(), this.data.list);
    }
});

加数量

这段代码是一个小程序中的一个函数,它用于点击加号按钮时执行的操作。具体来说,它会将对应的课程数量加1,并更新页面上的数据。

解释:

  • jiaBtnTap是一个函数名,用于点击加号按钮时触发。
  • var that = this;将当前页面的上下文保存在变量that中,以便在函数内部使用。
  • JavaScript 作用域_w3cschool
  • var index = e.currentTarget.dataset.index;获取当前点击按钮的索引值。
  • JavaScript Event 对象_w3cschool  
  • var list = that.data.list;获取当前页面的数据列表。

  • list[parseInt(index)].number++;将对应索引的课程数量加1 。
  • JavaScript parseInt() 函数_w3cschool

parseInt() 函数可解析一个字符串,并返回一个整数。

当参数 radix 的值为 0,或没有设置该参数时,parseInt() 会根据 string 来判断数字的基数。

当忽略参数 radix , JavaScript 默认数字的基数如下:

  • 如果 string 以 "0x" 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数。
  • 如果 string 以 0 开头,那么 ECMAScript v3 允许 parseInt() 的一个实现把其后的字符解析为八进制或十六进制的数字。
  • 如果 string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数。
  • parseInt(string, radix)

     
    参数 描述
    string 必需。要被解析的字符串。
    radix 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。

  • that.setPageData(that.getSaveHide(), that.totalPrice(), that.allSelect(), that.noSelect(), list);更新页面上的数据。

示例: 假设当前页面的数据列表为list = [{name: '课程1', number: 2}, {name: '课程2', number: 3}],点击第一个课程的加号按钮后,函数执行后的结果为list = [{name: '课程1', number: 3}, {name: '课程2', number: 3}]

问题1:为什么在加数量中用that,而在减数量中用this?

这两段代码中使用了不同的变量名来引用当前对象

第一段代码中,使用了变量名"that"来引用当前对象

而在第二段代码中,直接使用了关键字"this"来引用当前对象

使用"that"的目的是为了避免在嵌套函数中出现作用域问题。在JavaScript中,函数内部的this指向的是函数的调用者,而不是定义函数的对象。

因此,在嵌套函数中,如果直接使用this来引用当前对象,可能会导致this指向错误的对象。

为了解决这个问题,可以在外层函数中将this赋值给一个变量that,然后在嵌套函数中使用that来引用当前对象,以确保引用的是正确的对象。

而在第二段代码中,没有出现嵌套函数,所以直接使用this来引用当前对象是没有问题的。

在提供的加减函数代码中,没有明确指出哪个是嵌套函数。嵌套函数是指在一个函数内部定义的函数。根据提供的代码,没有函数在其他函数内部定义,因此没有嵌套函数。

你可能感兴趣的:(flask,小程序,windows)