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

mina/pages/cart/index.wxml

<!--index.wxml-->
<view class="container"><view class="title-box" wx:if="{{ !list.length }}">购物车空空如也~</view><view class="to-index-btn" bindtap="toIndexPage" wx:if="{{ !list.length }}">去逛逛</view><view class="list-top" wx:if="{{ list.length }}"><view class="label">购物车</view><view class="edit-btn" hidden="{{!saveHidden}}" bindtap="editTap">编辑</view><view class="edit-btn" hidden="{{saveHidden}}" bindtap="saveTap">完成</view></view><view class="goodsList" wx:if="{{ list.length }}"><view class="a-gooods" wx:for="{{ list }}"  wx:key="{{index}}" ><view class="a-goods-conts {{item.active? 'active':''}}" bindtap="selectTap" data-index="{{index}}"><view class="goods-info"><view class="img-box"><image src="{{item.pic_url}}" class="img"/></view><view class="text-box"><view class="goods-title">{{item.name}}</view><view class="goods-price">¥ {{item.price}}</view><view class="buy-num"><view class="jian-btn" catchtap="jianBtnTap" data-index="{{index}}">-</view><input  type="number" value="{{item.number}}" disabled/><view class="jia-btn" catchtap="jiaBtnTap" data-index="{{index}}">+</view></view></view></view></view></view></view><view class="jiesuan-box" wx:if="{{ list.length }}"><view class="left-price"><view class="all-selected  {{allSelect?'active':''}}" bindtap="bindAllSelect">全选</view><view class="total" hidden="{{noSelect}}">合计:¥ {{totalPrice}}</view></view><view class="to-pay-btn {{noSelect?'no-select':''}}" hidden="{{!saveHidden}}" bindtap="toPayOrder">去结算</view><view class="to-pay-btn {{noSelect?'no-select':''}}" hidden="{{saveHidden}}" bindtap="deleteSelected">删除</view></view>
</view>

知识点一:简要代码分析

<view class="to-pay-btn {{noSelect?'no-select':''}}" hidden="{{!saveHidden}}" bindtap="toPayOrder">去结算</view>

根据提供的代码,<view class="to-pay-btn {{noSelect?'no-select':''}}" hidden="{{!saveHidden}}" bindtap="toPayOrder">去结算</view>是一个视图组件,它有一个类名为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_infoif not member_info:resp['code'] = -1resp['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_listreturn jsonify(resp)

common/libs/Helper.py

'''
根据某个字段获取一个dic出来
'''
def getDictFilterField( db_model,select_filed,key_field,id_list ):ret = {}query = db_model.queryif id_list and len( id_list ) > 0:query = query.filter( select_filed.in_( id_list ) )list = query.all()if not list:return retfor item in list:if not hasattr( item,key_field ):breakret[ getattr( item,key_field ) ] = itemreturn retdef selectFilterObj( obj,field ):ret = []for item in obj:if not hasattr(item, field ):breakif getattr( item,field )  in ret:continueret.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来引用当前对象是没有问题的。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/419000.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在k8s上部署ClickHouse

概述 clickhouse的容器化部署&#xff0c;已经有非常成熟的生态了。在一些互联网大厂也已经得到了大规模的应用。 clickhouse作为一款数据库&#xff0c;其容器化的主要难点在于它是有状态的服务&#xff0c;因此&#xff0c;我们需要配置PVC。 目前业界比较流行的部署方式有…

[每日一题] 01.20

文章目录 Apples Plus找最小值分类平均一尺之棰 Apples Plus L int(input()) for i in range(1,L 1):if i 1:print(fToday, I ate 1 apple.)else:print(fToday, I ate {i} apples.)找最小值 a int(input()) b list(map(int,input().split())) print(min(b))分类平均 n,k …

有什么提高编程能力的书籍推荐吗?

数据密集型应用系统设计 原文完整版PDF&#xff1a;https://pan.quark.cn/s/d5a34151fee9 这本书的作者是少有的从工业界干到学术界的牛人&#xff0c;知识面广得惊人&#xff0c;也善于举一反三&#xff0c;知识之间互相关联&#xff0c;比如有个地方把读路径比作programming …

esp32-idf Eclipse Log日志打印demo

Log日志打印demo 1、代码例程 esp32-S2 芯片 / Eclipse软件 开发环境 #include <stdio.h> #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" #include "esp_…

力扣hot100 找到字符串中所有字母异位词 滑动窗口 双指针 一题双解

Problem: 438. 找到字符串中所有字母异位词 文章目录 思路滑动窗口 数组滑动窗口 双指针 思路 &#x1f469;‍&#x1f3eb; 参考题解 滑动窗口 数组 ⏰ 时间复杂度: O ( n ) O(n) O(n) &#x1f30e; 空间复杂度: O ( 1 ) O(1) O(1) class Solution { // 滑动窗口 …

mfc110.dll丢失是什么意思?全面解析mfc110.dll丢失的解决方法

在使用计算机的过程中&#xff0c;用户可能会遭遇一个常见的困扰&#xff0c;即系统提示无法找到mfc110.dll文件。这个动态链接库文件&#xff08;DLL&#xff09;是Microsoft Foundation Classes&#xff08;MFC&#xff09;库的重要组成部分&#xff0c;对于许多基于Windows的…

Go语言基础快速上手

1、Go语言关键字 2、Go数据类型 3、特殊的操作 3.1、iota关键字 Go中没有明确意思上的enum&#xff08;枚举&#xff09;定义&#xff0c;不过可以借用iota标识符实现一组自增常亮值来实现枚举类型。 const (a iota // 0b // 1c 100 // 100d // 100 (与上一…

GitHub提交 / 拉取时 443 fatal: unable to access ‘https:

这个问题嘛 懂得都懂 但是用了魔法后依旧会出现443错误 排查了工具发现并不是工具的问题 修改一下git代理即可解决 解决方法如下 确保魔法可用的情况下 打开魔法 打开系统设置 > 网络和Internet > 代理 找到自己的代理IP 如下 这里以我的代理IP和端口举例 在…

svg矢量图标在wpf中的使用

在wpf应用程序开发中&#xff0c;为支持图标的矢量缩放&#xff0c;及在不同分辨率下界面中图标元素的矢量无损缩放&#xff0c;所以常常用到svg图标&#xff0c;那么如果完 美的将svg图标运用到wpf日常的项目开发中呢&#xff0c;这里分享一下我的个人使用经验和详细步骤。 步…

Pygame库中Surface 对象介绍

Pygame库中Surface 对象介绍 关于Python中pygame游戏模块的安装使用可见 https://blog.csdn.net/cnds123/article/details/119514520 Pygame库中Surface 对象 在Pygame库中&#xff0c;Surface 对象是一个非常核心的概念&#xff0c;它代表了一个二维的矩形画布&#xff0c;…

LSTM时间序列预测

本文借鉴了数学建模清风老师的课件与思路&#xff0c;可以点击查看链接查看清风老师视频讲解&#xff1a;【1】演示&#xff1a;基于LSTM深度学习网络预测时间序列&#xff08;MATLAB工具箱&#xff09;_哔哩哔哩_bilibili % Forecast of time series based on LSTM deep learn…

2024美赛数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法&#xff0c;其…