礼物列表
需求:从挑选礼物中到礼物列表,列表中有礼物分类。点击分类获取分类礼物
小程序端
app.json文件,由于json数据不能注释,所有注释添加在开头,添加商品列表页路由。
{ "pages": [ "pages/list/list", ], "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#e50e38", "navigationBarTitleText": "百步生活", "navigationBarTextStyle": "#fff", "enablePullDownRefresh": false, "backgroundColor": "#e50e38" }, }
app.js
在app.js文件中配置我们接口的域名
App({ //设置全局的变量,apiDomain这是我们接口的ip globalData: { apiDomain:'http://127.0.0.1:8000', } })
list.json
在list.json配置当前list页面的信息
{ "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#da2a2a", "navigationBarTitleText": "选择礼物", "navigationBarTextStyle": "#fff", "enablePullDownRefresh": "true", "enablePullDownRefresh": false, "onReachBottomDistance": 100 }
list.wxml
<view class="container"> <view class="searcher"> <navigator class="inner" url="/pages/list/search/search"> <image class="icon-search" src='../../images/searcher.png'></image> <text>搜索热门礼物</text> </navigator> </view> <!--分类横向滑动--> <scroll-view scroll-x="true" class="category"> <!--如果curId等于0,则添加active属性,bindtap='loadLists',将此标签绑定该方法,在方法中我们可以获取data-index和data-id的值--> <view class="cateItem {{curId==0?'active':''}}" data-index="0" data-id="0" bindtap='loadLists'> <text>全部</text> </view> <!--循环category,其他的标签的意思同上--> <block wx:for="{{category}}" wx:for-index="index" wx:key="key"> <view class="cateItem {{curId==item.cat_id?'active':''}}" data-index="{{index+1}}" data-id="{{item.cat_id}}" bindtap='loadLists'> <text>{{item.category_name}}</text> </view> </block> </scroll-view> <view class="line"></view> <scroll-view class="lists"> <!--循环contentlist商品列表,其他的标签的意思同上--> <block wx:for="{{contentlist}}" wx:for-index="index" wx:key="key"> <view class="item" data-url="{{item.product_id}}" data-img="{{item.m_url}}" data-brief="{{item.brief}}" data-price="{{item.price}}" bindtap="loadDetail"> <view class="inner"> <image class="p-image" src="{{item.m_url}}" mode="aspectFill" style="width:100%;"/> <view class="p-name">{{item.name}}</view> <view class="p-brief">{{item.brief}}</view> <view class="p-price">¥{{item.price}}</view> </view> </view> </block> </scroll-view> </view>
list.wxss
/* pages/list/list.wxss */ .searcher{ height: 80rpx; width: 100%; position: fixed; top: 0; border-bottom: 2rpx solid #f2f2f2; line-height: 80rpx; font-size: 24rpx; z-index: 999; background-color: #fff; } .searcher .inner{ width: 670rpx; background: #f2f2f2; height: 60rpx; line-height: 60rpx; position: absolute; left: 40rpx; top: 10rpx; border-radius: 8rpx; } .icon-search{ width: 36rpx; height: 36rpx; position: absolute; left: 12rpx; top: 12rpx; } .searcher .inner text{ color: #999; padding-left: 80rpx; } .category{ height: 80rpx; white-space: nowrap; position: fixed; z-index: 999; top: 82rpx; background-color: #fff; } .cateItem{ display: inline-block; line-height: 80rpx; width: 115rpx; text-align: center; white-space: nowrap; font-size: 24rpx; } .cateItem.active text{ line-height: 74rpx; border-bottom:2rpx solid #e03131; display: inline-block; } .line{ border-top: 2rpx solid #eee; width: 100%; } .container{ padding: 0; } .lists{ padding-top: 162rpx; } .item{ width: 335rpx; float: left; padding: 20rpx; } .p-image{ width: 335rpx; height: 335rpx; } .p-name{ width: 100%; height: 40rpx; font-size: 14px; line-height: 40rpx; word-break: break-all; -webkit-box-orient: vertical; -webkit-line-clamp:1; overflow: hidden; text-overflow:ellipsis; display: -webkit-box; } .p-brief{ width: 100%; font-size: 13px; height: 40rpx; color: #ccc; line-height: 40rpx; word-break: break-all; -webkit-box-orient: vertical; -webkit-line-clamp:1; overflow: hidden; text-overflow:ellipsis; display: -webkit-box; } .p-price{ width: 100%; font-size: 16px; height: 40rpx; color: #e03131; line-height: 50rpx; word-break: break-all; -webkit-box-orient: vertical; -webkit-line-clamp:1; overflow: hidden; text-overflow:ellipsis; display: -webkit-box; } .intro{ transform: rotate(45deg); background: #e03131; color: #fff; font-size: 14px; text-align: center; position: absolute; right:-112rpx; width:100%; top:36rpx; } .inner{ overflow: hidden; position: relative; }
list.js
const app = getApp(); Page({ /** * 页面的初始数据 */ data: { category:[], page: 1, pageSize: 30, hasMoreData: true, contentlist: [],//全部列表 cateLists:[],//保存分类列表缓存数据 curId:0,//头部分类默认选中的分类id curIndex:0//当前选中分类的index索引值 }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) {//初始化加载首页全部数据 wx.showLoading({ title: '加载中', }) var _self = this; wx.request({//获取分类数据 url: app.globalData.apiDomain +'/api/indexlist/categoryList', data: { }, header: { 'content-type': 'application/json' // 默认值 }, success: function (res) { console.log(res.data.data) _self.setData({ category: res.data.data },function(){ var tmp_Lists = []; tmp_Lists.push(new Array()); for(var j=1;j<=res.data.data.length;j++){ tmp_Lists.push(new Array()); }; _self.setData({ cateLists:tmp_Lists },function(){ wx.request({//获取分类首页列表数据 url: app.globalData.apiDomain + '/api/indexlist/IndexProductList', data: { 'page': _self.data.page, }, method: 'POST', header: { 'content-type': 'application/json' // 默认值 }, success: function (res) { console.log(res) _self.setData({ page: _self.data.page + 1 }); if (res.data.data.prev < res.data.data.sums_page) {//下一页有数据 _self.setData({ hasMoreData: true }); } else { _self.setData({ hasMoreData: false }); }; var homeListsName = 'cateLists[0]'; _self.setData({ [homeListsName]: res.data.data, contentlist: res.data.data.list }); wx.hideLoading(); } }) }) }); } }); }, getMoreLists:function(){//加载更多列表 var _this = this; //全部列表接口 var _url = app.globalData.apiDomain + '/api/indexlist/IndexProductList'; var _data = ''; if (_this.data.curId!=0){ //分类列表接口 _url = app.globalData.apiDomain + '/api/indexlist/categoryProductsList'; _data = { 'page': _this.data.page, 'category_id': _this.data.curId } }else{ _data = { 'page': _this.data.page } }; wx.request({ url: _url, data:_data, method: 'POST', header: { 'content-type': 'application/json' // 默认值 }, success: function (res) { _this.setData({ page: _this.data.page + 1 }); if (res.data.data.prev < res.data.data.sums_page) {//下一页有数据 _this.setData({ hasMoreData: true }); } else { _this.setData({ hasMoreData: false }); } var tmpArr = _this.data.contentlist; for(var i=0;i<res.data.data.list.length;i++){ tmpArr.push(res.data.data.list[i]); } var homeListsName = 'cateLists[' + _this.data.curIndex+']'; var curListsName = 'cateLists[' + _this.data.curIndex + '].list'; _this.setData({ contentlist: tmpArr, [homeListsName]: res.data.data },function(){ _this.setData({ [curListsName]: tmpArr }) }); wx.hideLoading(); } }) }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { var _this = this; if (_this.data.hasMoreData) { wx.showLoading({ title: '加载更多数据', }); _this.getMoreLists(); } else { wx.showToast({ title: '没有更多数据', }) } }, loadDetail: function (e) {//跳转详情页 var pid = e.currentTarget.dataset.url; var img = e.currentTarget.dataset.img; var brief = e.currentTarget.dataset.brief; var price = e.currentTarget.dataset.price; wx.navigateTo({ url: '../item/item?id=' + pid + '&img=' + img + '&brief=' + brief + '&price=' + price, success: function (res) { }, fail: function (res) { }, complete: function (res) { }, }) }, loadLists: function (e) {//点击分类tab事件 var id = e.currentTarget.dataset.id; var index = e.currentTarget.dataset.index; var _this = this; _this.setData({ curIndex:index },function(){ if (id != _this.data.curId) {//点击的不是当前选中项 _this.setData({ curId: id },function(){ console.log(id); if (id != 0) {//不是全部 if (_this.data.cateLists[index].list) {//判断当前分类的列表数据是否存在 //console.log('已有数据'); _this.showLists(); } else {//不存在加载第一页的数据 //console.log('没有数据'); _this.getCateLists(); } } else if(id==0) {//首页 if (_this.data.cateLists[index].list) {//判断当前分类的列表数据是否存在 //console.log('首页已有数据'); _this.showLists(); } else { //console.log('首页没有数据'); //_this.getCateLists(); } }; }) }; }) }, getCateLists:function(){//获取当前分类的第一页数据 var _this = this; var cate_id = _this.data.curId; wx.showLoading({ title: '加载中', }); wx.pageScrollTo({ scrollTop: 0, }) wx.request({ url: app.globalData.apiDomain + '/api/indexlist/categoryProductsList', data: { 'page': 1, 'category_id': _this.data.curId}, method: 'POST', header: { 'content-type': 'application/json' // 默认值 }, success: function (res) { _this.setData({ page: 2 }); if (res.data.data.prev < res.data.data.sums_page) {//下一页有数据 _this.setData({ hasMoreData: true }); } else { _this.setData({ hasMoreData: false }); } var tmpArr = []; for (var i = 0; i < res.data.data.list.length; i++) { tmpArr.push(res.data.data.list[i]); } var homeListsName = 'cateLists[' + _this.data.curIndex + ']'; var curListsName = 'cateLists[' + _this.data.curIndex + '].list'; _this.setData({ contentlist: tmpArr, [homeListsName]: res.data.data }, function () { _this.setData({ [curListsName]: tmpArr }) }); wx.hideLoading(); } }) }, showLists:function(){//存在数据,显示切换 var _this = this; wx.pageScrollTo({ scrollTop: 0, }) if (_this.data.cateLists[_this.data.curIndex].sums_page >= _this.data.cateLists[_this.data.curIndex].next) {//有下一页 _this.setData({ hasMoreData: true }) } else { _this.setData({ hasMoreData: false }) }; _this.setData({//更新列表数据和其他相关数据 contentlist:_this.data.cateLists[_this.data.curIndex].list,//列表内容 }); } })
服务端
1.创建获取分类列表product.caetgoryList.as_view()
2.获所有商品列表product.ProductList.as_view()
3.获取分类下的商品列表 product.categoryProductsList
url.py
from django.contrib import admin from django.urls import path from django.conf.urls import url from api.views import product urlpatterns = [ path('admin/', admin.site.urls), url(r'^api/indexlist/categoryList$', product.caetgoryList.as_view()), url(r'^api/indexlist/IndexProductList$', product.ProductList.as_view()), url(r'^api/indexlist/categoryProductsList$', product.categoryProductsList.as_view()), ]
product.py
from rest_framework.views import APIView from api import baseResponse from api import models from django.http import JsonResponse from rest_framework.pagination import PageNumberPagination import math from api.MySer.MySer import ProductsSerializer,CategorySerializer #分类列表接口 class caetgoryList(APIView): def get(self, request): #这里因为模拟数据,我这里将分类id固定 data_obj = models.Category.objects.filter(cat_id__in=[6458,6460,6477,6486,6481,6500,6552]).order_by('p_order') #序列化组件,序列化返回的数据 data_list=CategorySerializer(instance=data_obj, many=True) data=data_list.data re_data = baseResponse.resdic("success", "查询成功",data) return JsonResponse(re_data) #所有商品列表接口 class ProductList(APIView,): def post(self,request): params = request.data #判断是否有页数参数 if params.get('page'): page=params['page'] ret = models.Products.objects.all() count=ret.count() sums_page=math.ceil(count/10) next= page + 1 if (page+1) <sums_page else sums_page prev = page - 1 if (page - 1) > 0 else 1 # 创建分页对象 page_obj = PageNumberPagination() page_obj.page_size = 10 page_obj.page_query_param = 'page' # 定制传参 page_obj.page_size_query_param = 'size' # 最大一页的数据 page_obj.max_page_size = 10 # 在数据库中获取分页的数据 page_list = page_obj.paginate_queryset(ret, request, view=self) # 对分页进行序列化 data_list=ProductsSerializer(instance=page_list, many=True) p_data={} p_data['sums_page'] = sums_page p_data['next'] =next p_data['prev'] = prev p_data['list'] = data_list.data print('list') print(type(data_list.data)) re_data = baseResponse.resdic("success", "查询成功", p_data) return JsonResponse(re_data) else: re_data = baseResponse.resdic("error", "缺少参数") return JsonResponse(re_data) #分类商品列表 class categoryProductsList(APIView): def post(self,request): params = request.data if params.get('page') and params.get('category_id'): page=params['page'] category_id=params['category_id'] ret = models.Products.objects.filter(cat_id__cat_id=category_id) count=ret.count() sums_page=math.ceil(count/10) #值1 if 条件 else 值2 next= page + 1 if (page+1) <sums_page else sums_page prev = page - 1 if (page - 1) > 0 else 1 # 创建分页对象 page_obj = PageNumberPagination() page_obj.page_size = 10 page_obj.page_query_param = 'page' # 定制传参 page_obj.page_size_query_param = 'size' # 最大一页的数据 page_obj.max_page_size = 10 # 在数据库中获取分页的数据 page_list = page_obj.paginate_queryset(ret, request, view=self) # 对分页进行序列化 data_list=ProductsSerializer(instance=page_list, many=True) p_data={} p_data['sums_page'] = sums_page p_data['next'] =next p_data['prev'] = prev p_data['list'] = data_list.data print('list') print(data_list.data) re_data = baseResponse.resdic("success", "查询成功", p_data) return JsonResponse(re_data) else: re_data = baseResponse.resdic("error", "缺少参数") return JsonResponse(re_data)