Flask 与小程序 的图片数据交互 过程及探讨研究学习

今天不知道怎么的,之前拿编程浪子地作品抄过来粘上用好好的,昨天开始照片突的就不显示了。

今天不妨再耐味地细细探究一下微信小程序wxml 和flask服务器端是怎么jpg图片数据交互的。

mina/pages/food/index.wxml

<!--index.wxml-->
<!--1px = 750/320 = 2.34rpx;-->
<view class="container">
  <!--轮播图-->
  <view class="swiper-container">
    <swiper class="swiper_box" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" bindchange="swiperchange">
      <block wx:for="{{banners}}" wx:key="id">
        <swiper-item>
          <image bindtap="tapBanner" data-id="{{item.id}}" src="{{item.pic_url}}" class="slide-image" width="750rpx" height="562.5rpx" />
        </swiper-item>
      </block>
    </swiper>
    <view class="dots">
      <block wx:for="{{banners}}" wx:key="unique">
        <view class="dot{{index == swiperCurrent ? ' active' : ''}}"></view>
      </block>
    </view>
  </view>
  <!--分类展示-->
  <view class="type-container">
    <scroll-view class="type-navbar" scroll-x="true">
      <view class="type-box" wx:for-items="{{categories}}" wx:key="id">
        <view id="{{item.id}}" class="type-navbar-item {{activeCategoryId == item.id ? 'type-item-on' : ''}}" bindtap="catClick">
          {{item.name}}
        </view>
      </view>
<!--      这段代码是一个小程序中的一个视图组件,它使用了小程序的模板语法。具体来说,这段代码定义了一个视图组件,其中包含一个view标签,
        该标签具有id属性和class属性,并且绑定了一个tap事件处理函数"catClick"。
    在view标签内部,使用了双花括号语法来插入动态数据,其中item.id和item.name是动态的数据,根据实际情况进行渲染。-->
    </scroll-view>
  </view>
  <!--搜索框-->
  <view class="search-view" style="background:{{ scrollTop === 0 ?'-webkit-linear-gradient(top, rgba(105,195,170, 1), rgba(105,195,170, 0.3))' :( scrollTop<200 ? 'rgba(105,195,170,'+(scrollTop/400+0.3) +')' : 'rgba(105,195,170,1)')  }} ">
    <view class="search-content">
      <image src="/images/search-pic.png" class="search-icon" />
      <input placeholder="请输入搜索内容" class="search-input" maxlength="30" confirm-type="搜索" bindinput='listenerSearchInput'>
      </input>
      <button class='search-btn' bindtap="toSearch">搜索</button>
    </view>
  </view>

  <view class="goods-container">
    <!--    wx:for-items="{{goods}}" 是一个循环遍历的功能,将 goods 数组中的每个元素都渲染成一个 goods-box 组件。-->
    <view class="goods-box" wx:for-items="{{goods}}"  bindtap="toDetailsTap" data-id="{{item.id}}">
      <view class="img-box">
        <image src="{{item.pic_url}}" class="image" mode="aspectFill" lazy-load="true" />
      </view>
      <view class="goods-title">{{item.name}}</view>
      <view style='display:flex;'>
        <view class="goods-price">¥ {{item.min_price}}</view>
        <view wx:if="{{item.price && item.price > 0 && item.min_price != item.price}}" class="goods-price" style='color:#aaa;text-decoration:line-through'>¥ {{item.price}}</view>
      </view>
    </view>
  </view>
  <view hidden="{{loadingMoreHidden ? true : false}}" class="no-more-goods">哥也是有底线的</view>
</view>

如上例代码所示,图片的展示是通过一个image src='{{item.pic_url}}'标签引入的。通常情况下,item是一个对象或数组,它包含了多个属性,其中pic_url就是其中一个属性。在这个例子中,item.pic_url表示图片的URL地址,通过该地址可以加载并显示对应的图片。

总之,image 标签是小程序中用于显示图片的组件,通过 src="{{item.pic_url}}" 绑定了图片的地址。追根溯源,找goods数组是从哪里传来的。

goods数组是通过小程序端地js文件绑定的一个getBannerAndCat()函数,并将其设置在onshow生命周期里,通过调用getFoodList(),自动进行的数据读取和刷新。

 //解决切换不刷新维内托,每次展示都会调用这个方法
    onShow:function(){
        this.getBannerAndCat();
    },

问题: 这个item对象或数组从何而来?是小程序端的js文件吗?

mina/pages/food/index.js

//index.js
//获取应用实例
var app = getApp();
Page({
    data: {
        indicatorDots: true,
        autoplay: true,
        interval: 3000,
        duration: 1000,
        loadingHidden: false, // loading
        swiperCurrent: 0,
        categories: [],
        activeCategoryId: 0,
        goods: [],
        scrollTop: "0",
        loadingMoreHidden: true,
        searchInput: '',
        p:1,
        processing:false
    },
    onLoad: function () {
        var that = this;
        wx.setNavigationBarTitle({
            title: app.globalData.shopName
        });
    },
    //解决切换不刷新维内托,每次展示都会调用这个方法
    onShow:function(){
        this.getBannerAndCat();
    },
    scroll: function (e) {
        var that = this, scrollTop = that.data.scrollTop;
        that.setData({
            scrollTop: e.detail.scrollTop
        });
    },
    //事件处理函数
    swiperchange: function (e) {
        this.setData({
            swiperCurrent: e.detail.current
        })
    },
    listenerSearchInput:function( e ){
        this.setData({
            searchInput: e.detail.value
        });
    },
    toSearch:function( e ){
        this.setData({
            p:1,
            goods:[],
            loadingMoreHidden:true
        });
        this.getFoodList();
	},
    // tapBanner是一个函数,它用于处理轮播图的点击事件具体的实现逻辑如下:
    tapBanner: function (e) {
        // 首先,通过e.currentTarget.dataset.id获取到当前点击的轮播图的id。
        // 然后,判断id是否为0,如果不为0,则执行以下操作:
        if (e.currentTarget.dataset.id != 0) {
            // 使用wx.navigateTo函数进行页面跳转,跳转到指定的页面。
            wx.navigateTo({
                // 跳转的目标页面是"/pages/food/info",并且通过url参数传递了点击轮播图的id,参数名为id。
                url: "/pages/food/info?id=" + e.currentTarget.dataset.id
            });
        //     这段代码的作用是当用户点击轮播图,如果轮播图的id不为0,则跳转到指定的页面,并将点击轮播图的id作为参数传递给标页面。
        }
    },
    // toDetailsTap是一个函数,它是在小程序中用于点击事件的回调函数。当触发点击事件时,会执行该函数。
    toDetailsTap: function (e) {
        // 该函数的作用是跳转到指定的页面。在函数内部,通过调用wx.navigateTo方法来实现页面跳转。
        // 其中,url参数指定了跳转的目标页面路径,通过拼接字符串的方式将参数id传递给目标页面。
        // 总结一下,toDetailsTap函数的作用是在点击事件发生时,跳转到指定的页面,并将参数id传递给目标页面。
        wx.navigateTo({
            url: "/pages/food/info?id=" + e.currentTarget.dataset.id
        });
    },
    getBannerAndCat: function () {
        var that = this;
        // 使用微信小程序的wx.request方法发送一个请求。
        wx.request({
            // 请求的URL是通过app.buildUrl(“/food/index”)方法构建的
            url: app.buildUrl("/food/index"),
            // 请求头部信息通过app.getRequestHeader()方法获取
            header: app.getRequestHeader(),
            // 请求成功后,会将返回的数据保存在resp变量中。
            success: function (res) {
                var resp = res.data;
                // 如果返回的code不等于200,会通过app.alert方法弹出一个提示框显示返回的错误信息,并结束函数的执行。
                if (resp.code != 200) {
                    app.alert({"content": resp.msg});
                    return;
                }
                // 如果返回的code等于200,会将返回的banner_list和cat_list数据分别保存在banners和categories变量中,
                that.setData({
                    banners: resp.data.banner_list,
                    categories: resp.data.cat_list
                });
                // 并调用getFoodList方法
                that.getFoodList();
            }
        });
    },
    // 这段代码是一个小程序中的一个函数,名为catClick。它的作用是在点击某个分类时,根据点击的分类id更新数据,并调用getFoodList函数获取对应分类的商品列表。
    catClick: function (e) {
        this.setData({
            // 通过e.currentTarget.id获取点击的分类id。
            activeCategoryId: e.currentTarget.id
        });
        // 使用setData方法更新数据,将activeCategoryId设置为点击的分类id。
        this.setData({
            // 将loadingMoreHidden设置为true,p设置为1(表示当前页数为1),goods设置为空数组(清空商品列表)。
            loadingMoreHidden: true,
            p:1,
            goods:[]
        });
        // 调用getFoodList函数获取对应分类的商品列表。
        this.getFoodList();
    },
    onReachBottom: function () {
        var that = this;
        setTimeout(function () {
            that.getFoodList();
        }, 500);
    },
    // 通过发送请求获取食品列表,并将获取到的数据更新到页面上。
    getFoodList: function () {
        var that = this;
        // 首先,函数会检查是否正在处理其他请求,如果是,则直接返回,避免重复请求。
        if( that.data.processing ){
            return;
        }
        // 接着,函数会检查是否还有更多数据需要加载,如果没有,则直接返回。
        if( !that.data.loadingMoreHidden ){
            return;
        }
        // 然后,函数会将processing标志设置为true,表示正在处理请求。
        that.setData({
            processing:true
        });
        // 接下来,函数会发送一个请求到服务器,请求的URL是"/food/search",并且会带上一些参数,
        // 如cat_id(食品分类ID)、mix_kw(搜索关键词)、p(页码)等。
        wx.request({
            url: app.buildUrl("/food/search"),
            header: app.getRequestHeader(),
            data: {
                cat_id: that.data.activeCategoryId,
                mix_kw: that.data.searchInput,
                p: that.data.p,
            },
            // 当服务器返回响应时,函数会判断响应的状态码是否为200,如果不是,则弹出一个提示框显示错误信息,并返回。
            success: function (res) {
                var resp = res.data;
                if (resp.code != 200) {
                    app.alert({"content": resp.msg});
                    return;
                }
                // 如果响应的状态码为200,则从响应数据中获取到食品列表,并将其与之前已有的食品列表进行合并。
                var goods = resp.data.list;
                that.setData({
                    goods: that.data.goods.concat( goods ),
                    p: that.data.p + 1,
                    //最后,函数会更新页面上的数据,包括goods(食品列表)、p(页码)和processing(处理状态),
                    // 并将processing标志设置为false,表示请求处理完成。
                    processing:false
                });
                // 判断变量resp.data.has_more的值是否为0。如果resp.data.has_more的值为0,
                // 则执行setData方法,将loadingMoreHidden属性设置为false。
                if( resp.data.has_more == 0 ){
                    that.setData({
                        loadingMoreHidden: false
                    });
                }

            }
        });
    }
});

那接下来,就去flask服务器端看看/food/search路由是什么情况,图片传参是怎么传的。

web/controllers/api/Food.py

# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from  flask import request,jsonify,g
from common.models.food.FoodCat import FoodCat
from common.models.food.Food import Food
from common.models.member.MemberCart import MemberCart
from common.models.member.MemberComments import MemberComments
from common.models.member.Member import Member
from common.libs.UrlManager import UrlManager
from common.libs.Helper import getCurrentDate,getDictFilterField,selectFilterObj
from app import app,db
from sqlalchemy import  or_

@route_api.route("/food/index" )
def foodIndex():
    resp = { 'code':200 ,'msg':'操作成功~','data':{} }
    cat_list = FoodCat.query.filter_by( status = 1 ).order_by( FoodCat.weight.desc() ).all()
    data_cat_list = []
    data_cat_list.append({
        'id': 0,
        'name': "全部"
    })
    if cat_list:
        for item in cat_list:
            tmp_data = {
                'id':item.id,
                'name':item.name
            }
            data_cat_list.append( tmp_data  )
    resp['data']['cat_list'] = data_cat_list

    food_list = Food.query.filter_by( status = 1 )\
        .order_by( Food.total_count.desc(),Food.id.desc() ).limit(3).all()

    data_food_list = []
    if food_list:
        for item in food_list:
            tmp_data = {
                'id':item.id,
                'pic_url':UrlManager.buildImageUrl( item.main_image )
            }
            data_food_list.append( tmp_data )

    resp['data']['banner_list'] = data_food_list
    return jsonify( resp )

@route_api.route("/food/search" )
def foodSearch():
    resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
    req = request.values
    cat_id = int( req['cat_id'] ) if 'cat_id' in req else 0
    mix_kw = str(req['mix_kw']) if 'mix_kw' in req else ''
    p = int( req['p'] ) if 'p' in req else 1

    if p < 1:
        p = 1

    page_size = 10
    offset = ( p - 1 ) * page_size
    query = Food.query.filter_by(status=1 )
    if cat_id > 0:
        query = query.filter_by(cat_id = cat_id)

    if mix_kw:
        rule = or_(Food.name.ilike("%{0}%".format(mix_kw)), Food.tags.ilike("%{0}%".format(mix_kw)))
        query = query.filter(rule)

    food_list = query.order_by(Food.total_count.desc(), Food.id.desc())\
        .offset( offset ).limit( page_size ).all()

    data_food_list = []
    if food_list:
        for item in food_list:
            tmp_data = {
                'id': item.id,
                'name': "%s"%( item.name ),
                'price': str( item.price ),
                'min_price':str( item.price ),
                'pic_url': UrlManager.buildImageUrl(item.main_image)
            }
            data_food_list.append(tmp_data)
    resp['data']['list'] = data_food_list
    resp['data']['has_more'] = 0 if len( data_food_list ) < page_size else 1
    return jsonify(resp)

@route_api.route("/food/info" )
def foodInfo():
    resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
    req = request.values
    id = int(req['id']) if 'id' in req else 0
    food_info = Food.query.filter_by( id = id ).first()
    if not food_info or not food_info.status :
        resp['code'] = -1
        resp['msg'] = "美食已下架"
        return jsonify(resp)

    member_info = g.member_info
    cart_number = 0
    if member_info:
        cart_number = MemberCart.query.filter_by( member_id =  member_info.id ).count()
    resp['data']['info'] = {
        "id":food_info.id,
        "name":food_info.name,
        "summary":food_info.summary,
        "total_count":food_info.total_count,
        "comment_count":food_info.comment_count,
        'main_image':UrlManager.buildImageUrl( food_info.main_image ),
        "price":str( food_info.price ),
        "stock":food_info.stock,
        "pics":[ UrlManager.buildImageUrl( food_info.main_image ) ]
    }
    resp['data']['cart_number'] = cart_number
    return jsonify(resp)


@route_api.route("/food/comments")
def foodComments():
    resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
    req = request.values
    id = int(req['id']) if 'id' in req else 0
    query = MemberComments.query.filter( MemberComments.food_ids.ilike("%_{0}_%".format(id)) )
    list = query.order_by( MemberComments.id.desc() ).limit(5).all()
    data_list = []
    if list:
        member_map = getDictFilterField( Member,Member.id,"id",selectFilterObj( list,"member_id" ) )
        for item in list:
            if item.member_id not in member_map:
                continue
            tmp_member_info = member_map[ item.member_id ]
            tmp_data = {
                'score':item.score_desc,
                'date': item.created_time.strftime("%Y-%m-%d %H:%M:%S"),
                "content":item.content,
                "user":{
                    'nickname':tmp_member_info.nickname,
                    'avatar_url':tmp_member_info.avatar,
                }
            }
            data_list.append( tmp_data )
    resp['data']['list'] = data_list
    resp['data']['count'] = query.count()
    return jsonify(resp)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32CubeMX学习笔记22---FreeRTOS(任务创建和删除)

一、FreeRTOS简介 FreeRTOS 是一个可裁剪、可剥夺型的多任务内核&#xff0c;而且没有任务数限制。FreeRTOS 提供了实时操作系统所需的所有功能&#xff0c;包括资源管理、同步、任务通信等。 FreeRTOS 是用 C 和汇编来写的&#xff0c;其中绝大部分都是用 C 语言编写的&#x…

LabVIEW柴油机安保监控系统

LabVIEW柴油机安保监控系统 随着航运业的快速发展&#xff0c;确保船舶柴油机的安全稳定运行变得尤为重要。船舶柴油机故障不仅会导致重大的经济损失&#xff0c;还可能危及人员安全和环境。设计并开发了一套基于LabVIEW平台的柴油机安保监控系统&#xff0c;旨在通过实时监控…

VMware 虚拟机安装 CentOS Stream 9【图文详细教程】

系统需要开启虚拟化 VMware Pro 17 安装&#xff1a;https://www.yuque.com/u27599042/ccv8wh/ztmn0vkg3iimqyed CentOS Stream 9 镜像下载 https://www.centos.org/centos-stream/根据你电脑的操作系统类型&#xff0c;选择点击下载 创建虚拟机 在 VMware 中&#xff0c;…

JavaScript 权威指南第七版(GPT 重译)(六)

第十五章&#xff1a;JavaScript 在 Web 浏览器中 JavaScript 语言是在 1994 年创建的&#xff0c;旨在使 Web 浏览器显示的文档具有动态行为。自那时以来&#xff0c;该语言已经发生了显著的演变&#xff0c;与此同时&#xff0c;Web 平台的范围和功能也迅速增长。今天&#…

ES 8.x的多实例集群搭建与角色规划

ES 8 多实例集群搭建与角色规划 ES 8版本与之前版本存在较大改变&#xff0c;第一个区别就是启动时默认开启了安全模式&#xff0c;也就是即便是测试环境也需要用户名密码和https传输层安全证书。此外&#xff0c;集群节点的角色也与之前不同&#xff0c;除了新增角色外在配置…

设计技能UP UP UP!揭秘电路仿真软件高级技巧,让您成为设计大神

电路设计是一门技术活&#xff0c;而精湛的技巧往往决定了设计的成败。今天&#xff0c;让我们一起探讨电路仿真软件的高级技巧&#xff0c;助您在设计领域中实现技能的飙升&#xff01; 电路仿真软件的高级功能解析 电路仿真软件不仅仅是简单的模拟工具&#xff0c;它还具备许…

Superstate 创始人 Robert Leshner 确认出席 Hack.Summit() 2024 区块链开发者大会

随着Web3技术的日新月异&#xff0c;一场备受瞩目的区块链盛会——Hack.Summit() 2024区块链开发者大会&#xff0c;即将于2024年4月9日至10日在香港数码港璀璨启幕。此次大会不仅是Hack.Summit()系列在亚洲的首度亮相&#xff0c;更象征着区块链行业对亚洲&#xff0c;特别是香…

txt、pdf等文件转为一行一行的doccano数据集输入格式

文章目录 doccano 数据集导入简介代码实现代码运行结果代码公开 doccano 数据集导入 在Doccano 导入数据集时&#xff0c;使用TextLine的文件格式&#xff0c;导入的文件需要为一行一行文本的数据格式&#xff0c;每一行文本在导入Doccano后就是一条数据。 简介 主要工作说明…

AndroidStudio相关

1、AndroidStudio 改变.gradle .AndroidStudio 默认存储位置 1、AndroidStudio安装路径下 -> bin -> idea.properties 文件 将1和2的路径设置为自己的路径&#xff0c;将3和4取消注释或复制在下方 注意&#xff1a; idea.plugins.path 和 idea.log.path 必须去掉注释或重…

Etcd Raft 协议(进阶篇)

前言 在正式开始介绍 Raft 协议之间&#xff0c;我们有必要简单介绍一下其相关概念。在分布式系统中&#xff0c;一致性是比较常见的概念&#xff0c;所谓一致性指的是集群中的多个节点在状态上达成一致。在程序和操作系统不会崩溃、硬件不会损坏、服务器不会掉电、网络绝对可靠…

基于SpringBoot精品在线试题库系统

采用技术 基于SpringBoot精品在线试题库系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 系统功能结构图 学生管理 教师管理 专业管理 试卷管理 …

MySQL索引优化,MySQL索引失效的场景(超详细!)

目录 1.不遵循最左前缀原则 2.在索引列上使用&#xff08;计算&#xff0c;函数&#xff0c;or&#xff0c;类型转换&#xff09;&#xff0c;都是导致失效而导致全表扫描 3.范围查询 4.Select * 导致回表查询 5.不等空值还有or导致索引失效 6.like %写在左边导致索引失…

计算机408网课评测+资料分享

408当然有比较好的网课推荐&#xff0c;比如王道的视频课 现在大部分人备战408基本都用王道的讲义&#xff0c;然后再搭配王道408的课程来听&#xff0c;可以学的很好。 其中408视频课中&#xff0c;我认为讲的比较好的是数据结构&#xff0c;和操作系统&#xff0c;计算机组…

Talk|Mila研究所蒙特利尔大学刘圳:三维表征和三维网格的重建与生成

本期为TechBeat人工智能社区第580期线上Talk。 北京时间3月21日(周四)20:00&#xff0c;Mila研究所&蒙特利尔大学博士生—刘圳的Talk已经准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “三维表征和三维网格的重建与生成”&#xff0c;向大家系统地介…

基于Java的校园疫情防控管理系统(Vue.js+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生2.2 老师2.3 学校管理部门 三、系统展示四、核心代码4.1 新增健康情况上报4.2 查询健康咨询4.3 新增离返校申请4.4 查询防疫物资4.5 查询防控宣传数据 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBoot…

收割互联网大厂Offer面经

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…

paddlepaddle框架构建数据集进行分类问题的时候,会发现数据集在构建的过程中不会构建标签(花分类)

问题描述 在做一个paddlepaddle项目的时候&#xff0c;需要使用神经网络对他进行分类&#xff0c;数据集的结构如下图&#xff0c;这时候我们可以使用常用dataset方法对数据集进行构建。 这时候我们就会发现一个问题&#xff0c;就是这个矿建不是构建标签&#xff0c;也就是说…

vue在页面使用Vue.prototype全局变量

文章目录 Vue.prototype 的基本概念使用 Vue.prototype 添加全局属性和方法添加全局属性添加全局方法 使用场景注意事项在模板中使用全局变量和方法方法1方法2方法3 Vue.prototype 的基本概念 Vue.prototype 是 Vue 实例的原型对象。在 JavaScript 中&#xff0c;每个构造函数…

【Java】Java程序员必备的一些流程图

一、spring的生命周期 Spring作为当前Java最流行、最强大的轻量级容器框架&#xff0c;了解熟悉spring的生命周期非常有必要&#xff1b; 首先容器启动后&#xff0c;对bean进行初始化按照bean的定义&#xff0c;注入属性检测该对象是否实现了xxxAware接口&#xff0c;并将相…

openlayers 入门教程(四):layers 篇

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…