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.mzph.cn/news/639531.shtml

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

相关文章

Flutter 综述

Flutter 综述 1 介绍1.1 概述1.2 重要节点1.3 移动开发中三种跨平台框架技术对比1.4 flutter 技术栈1.5 IDE1.6 Dart 语言1.7 应用1.8 框架 2 Flutter的主要组成部分3 资料书籍 《Flutter实战第二版》Dart 语言官网Flutter中文开发者社区flutter 官网 4 搭建Flutter开发环境参考…

【漏洞复现】CloudPanel makefile接口远程命令执行漏洞(CVE-2023-35885)

文章目录 前言声明一、CloudPanel 简介二、漏洞描述三、影响版本四、漏洞复现五、修复建议 前言 CloudPanel 是一个基于 Web 的控制面板或管理界面&#xff0c;旨在简化云托管环境的管理。它提供了一个集中式平台&#xff0c;用于管理云基础架构的各个方面&#xff0c;包括 &a…

nginx基于IP的多虚拟主机

结合这篇文章一起&#xff1a;nginx虚拟主机-CSDN博客文章浏览阅读63次。虚拟主机指的就是一个独立的站点配置&#xff0c;是nginx默认支持的一个功能&#xff0c;它能够有自己独立的域名&#xff0c;独立的ip&#xff0c;独立的端口配置&#xff0c;能够配置完整的www服务&…

网络编程 | 网络综合

一、网络综合 1、从浏览器地址栏输入URL到显示主页的过程 大致会经历下面这些流程&#xff0c;如下&#xff1a; DNS解析&#xff1a;将域名解析成对应的IP地址TCP链接&#xff1a;与服务器通过三次握手&#xff0c;建立TCP链接向服务器发送HTTP请求服务器处理请求&#xff0c…

ubuntu安装vm和Linux,安装python环境,docker和部署项目(一篇从零到部署)

1、下载Ubuntu Index of /releaseshttps://old-releases.ubuntu.com/releases/ 2、下载VMware 官方正版VMware下载&#xff08;16 pro&#xff09;&#xff1a;https://www.aliyundrive.com/s/wF66w8kW9ac 下载Linux系统镜像&#xff08;阿里云盘不限速&#xff09;&#xff…

JavaScript 学习笔记(WEB APIs Day2)

「写在前面」 本文为 b 站黑马程序员 pink 老师 JavaScript 教程的学习笔记。本着自己学习、分享他人的态度&#xff0c;分享学习笔记&#xff0c;希望能对大家有所帮助。推荐先按顺序阅读往期内容&#xff1a; 1. JavaScript 学习笔记&#xff08;Day1&#xff09; 2. JavaSc…

算法每日一题:按分隔符拆分字符串 | 字符串 | 特殊位置判断

题目&#xff1a;leetcode 2788给你一个字符串数组 words 和一个字符 separator &#xff0c;请你按 separator 拆分 words 中的每个字符串。返回一个由拆分后的新字符串组成的字符串数组&#xff0c;不包括空字符串 。注意 separator 用于决定拆分发生的位置&#xff0c;但它…

【概率统计】区间估计 假设检验公式汇总

区间估计 假设检验公式汇总 最简单的一集

工业控制系统:HSLCommunication可以与PLC进行通信详解:C# HSLCommunication可以与 modbus tcp通信demo

当使用C#编程语言时&#xff0c;HSLCommunication库是一种常用的工具&#xff0c;用于实现与Modbus TCP通信。在本文中&#xff0c;我将为您提供详细的步骤和示例代码&#xff0c;以帮助您开始使用HSLCommunication库与Modbus TCP通信。 步骤1&#xff1a;安装HSLCommunicatio…

爬虫逆向开发教程1-介绍,入门案例

爬虫前景 在互联网的世界里&#xff0c;数据就是新时代的“黄金”。而爬虫&#xff0c;就是帮助我们淘金的“工具”。随着互联网的不断发展&#xff0c;数据量呈现指数级的增长&#xff0c;在数据为王的时代&#xff0c;有效的挖掘数据和利用&#xff0c;你会得到更多东西。 学…

SqlAlchemy使用教程(五) ORM API 编程入门

SqlAlchemy使用教程(一) 原理与环境搭建SqlAlchemy使用教程(二) 入门示例及编程步骤SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用SqlAlchemy使用教程(五) ORM API 编程入门 前一章用SQL表达式(SQL Expr…

POJ - 3311 Hie with the Pie(Java JS Python C)

题目来源 3311 -- Hie with the Pie (poj.org) 题目描述 Pizazz披萨店以尽可能快地将披萨送到顾客手中而自豪。 不幸的是&#xff0c;由于削减开支&#xff0c;他们只能雇一个司机来送货。 司机将等待 1 个或更多 (最多10个) 订单被下达后再开始送餐。 不用说&#xff0c;…

第12章 项目质量管理

文章目录 项目质量管理包括把组织的质量政策应用于规划、管理、控制项目和产品质量要求&#xff0c;以满足干系人目标的各个过程。此外&#xff0c;项目质量管理以执行组织的名义支持过程的待续改进活动。 12.1管理基础 12.1.1质量与项目质量 1质量 国际标准化组织(ISO)对质量…

用于垃圾回收的运行时配置选项

反馈 本文内容 指定配置的方法垃圾回收的风格管理资源使用情况大型页面 显示另外 4 个 此页面包含有关 .NET 运行时垃圾回收器 (GC) 设置的信息。 如果你要尝试让正在运行的应用达到最佳性能&#xff0c;请考虑使用这些设置。 然而&#xff0c;在特定情况下&#xff0c;默认…

基于大整形的运算收录

目录 目录 目录 前言 为什么要大整数 大整形的加/减法 大整形的乘法 大整形除法 大整形开方 代码实现 前言 好久没有更新博客了&#xff0c;hhh。时隔三个月&#xff0c;我又回来了。先来点简单的大整形&#xff0c;虽说简单&#xff0c;但是在编写的时候还是debug了…

学校门禁管理技巧,一招轻松学会!

随着社会的不断发展和科技的不断进步&#xff0c;安全管理成为各个领域至关重要的议题之一。门禁监控系统作为现代安全管理的关键组成部分&#xff0c;不仅为建筑物提供了有效的访问控制&#xff0c;还在提高整体安全性和管理效率方面发挥了关键作用。 客户案例 公司办公楼门禁…

C# 用于准确地测量运行时间的Stopwatch中.Start 方法和Stopwatch.Stop 方法

一、Stopwatch 类 提供一组方法和属性&#xff0c;可用于准确地测量运行时间。 public class Stopwatch 使用 Stopwatch 类来确定应用程序的执行时间。 // 使用 Stopwatch 类来确定应用程序的执行时间 using System.Diagnostics; class Program {static void Main(string[] a…

php no input file specified

一、修改 .user.ini 文件 内容 open_basedir/wab/led-sportslight.com/:/tmp/ led-sportslight.com是项目根目录位置 改好后保存并清空缓存硬刷新网站就行了 二、mkdir(): Permission denied /core/library/think/cache/driver/File.php 第 84 行左右 mkdir(): Permission de…

2024最新最全【网络安全面试题含答案】(非常详细),零基础入门到精通

防范常见的 Web 攻击 什么是SQL注入攻击 攻击者在HTTP请求中注入恶意的SQL代码&#xff0c;服务器使用参数构建数据库SQL命令时&#xff0c;恶意SQL被一起构造&#xff0c;并在数据库中执行。 用户登录&#xff0c;输入用户名 lianggzone&#xff0c;密码 ‘ or ‘1’’1 &a…

力扣刷题第八天 最大交换

给定一个非负整数&#xff0c;你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释: 交换数字2和数字7。示例 2 : 输入: 9973 输出: 9973 解释: 不需要交换。注意: 给定数字的范围是 [0, 10^8] 方法一&#xff1a;直接遍历 由于对…