Django+Vue开发生鲜电商平台之6.使用Vue实现商品类别和商品数据前台显示(上)

简介: 由之前的效果图和需求分析可知,首页全部商品分类需要展示一级、二级和三级分类,而在搜索结果页只展示一级和二级分类,分类有两个Vue组件,即Header中的全部商品分类和左侧的某以及类别对应的分类导航栏,也对应两个数据接口。

一、商品类别数据接口

由之前的效果图和需求分析可知,首页全部商品分类需要展示一级、二级和三级分类,而在搜索结果页只展示一级和二级分类,分类有两个Vue组件,即Header中的全部商品分类和左侧的某以及类别对应的分类导航栏,也对应两个数据接口。


先在apps/goods/views.py中定义商品类别数据View如下:

from rest_framework import mixins, viewsets, filters
from rest_framework.pagination import PageNumberPagination
from django_filters.rest_framework import DjangoFilterBackend
from .models import Goods, GoodsCategory
from .serializers import GoodsSerializer, CategorySerializer
from .filters import GoodsFilter
# Create your views here.
class GoodsPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'page_size'
    page_query_param = 'p'
    max_page_size = 100
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    '''商品列表页,并实现分页、搜索、过滤、排序'''
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filter_class = GoodsFilter
    search_fields = ['name', 'goods_brief', 'goods_desc']
    ordering_fields = ['sold_num', 'market_price']
class CategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    '''商品分类列表数据'''
    queryset = GoodsCategory.objects.all()
    serializer_class = CategorySerializer

再在urls.py中配置路由如下:

from django.conf.urls import url, include
from django.views.static import serve
from rest_framework.documentation import include_docs_urls
from rest_framework.routers import DefaultRouter
import xadmin
from .settings import MEDIA_ROOT
from goods.views import GoodsListViewSet, CategoryViewSet
# Create a router and register our viewsets with it.
router = DefaultRouter()
# 配置goods的路由
router.register(r'goods', GoodsListViewSet, basename='goods')
# 配置categories的路由
router.register(r'categories', CategoryViewSet, basename='categories')

访问http://127.0.0.1:8000/categories/,显示:


2345_image_file_copy_19.jpg


显然,将所有的数据都发送到前端,但是根据前端的要求,不同级之间的类别具有附属和依赖的关系,而不是平级的关系,显然还没有达到效果,需要进行改进。


此时需要用到才定义模型GoodsCategory的字段parent_category时指定的related_name属性,即related_name='sub_cat',此属性表示可以反向引用,即通过夫类别可以通过该属性查询子类别,利用该属性实现Serializer的三层嵌套引用,从而实现类别的嵌套显示,serializers.py 如下:

from rest_framework import serializers
from .models import Goods, GoodsCategory
class TerCategorySerializer(serializers.ModelSerializer):
    '''三级商品子类别序列化'''
    class Meta:
        model = GoodsCategory
        fields = '__all__'
class SecCategorySerializer(serializers.ModelSerializer):
    '''二级商品子类别序列化'''
    sub_cat = TerCategorySerializer(many=True)
    class Meta:
        model = GoodsCategory
        fields = '__all__'
class CategorySerializer(serializers.ModelSerializer):
    '''一级商品类别序列化'''
    sub_cat = SecCategorySerializer(many=True)
    class Meta:
        model = GoodsCategory
        fields = '__all__'
class GoodsSerializer(serializers.ModelSerializer):
    '''商品序列化'''
    category = CategorySerializer()
    class Meta:
        model = Goods
        fields = '__all__'

此时再访问http://127.0.0.1:8000/categories/,显示:


2345_image_file_copy_20.jpg


此时,以嵌套的形式在父类别中显示出子类别,并且属于三层嵌套。


现在需要实现获取某一个具体类别的详情(包括其基本信息和子类别),此时需要在路由中加入商品对应的id,只要使CategoryViewSet继承自mixins.RetrieveModelMixin,即可自动配置路由,无需再额外配置,即views.py如下:

class CategoryViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    '''商品分类列表数据'''
    queryset = GoodsCategory.objects.all()
    serializer_class = CategorySerializer

显示:


image.jpeg


显然,此时地址中传入指定的id,只显示该id对应的类别的信息和其子类别的信息。

二、Vue展示商品分类

在测试前需要先在fresh_online目录下执行命令cnpm run dev启动前端项目,启动后访问http://127.0.0.1:8080,可以看到:


2345_image_file_copy_22.jpg


显然,商品分类展示完整。


为了只是单独测试某一类数据而不影响其他数据的显示,因此其他数据都通过线上接口显示、待测试的数据通过本地接口测试。


在前端项目fresh_online中,在src/api/api.js中定义了数据API接口:

import axios from 'axios';
let host = 'http://shop.projectsedu.com';
let local_host = 'http://127.0.0.1:8000';
//获取商品类别信息
export const queryCategorygoods = params => { return axios.get(`${host}/indexgoods/`) }
//获取首页中的新品
export const newGoods = params => { return axios.get(`${host}/newgoods/`) }
//获取轮播图
export const bannerGoods = params => { return axios.get(`${host}/banners/`) }
//获取商品类别信息
export const getCategory = params => {
  if('id' in params){
    return axios.get(`${local_host}/categorys/`+params.id+'/');
  }
  else {
    return axios.get(`${local_host}/categorys/`, params);
  }
};
//获取热门搜索关键词
export const getHotSearch = params => { return axios.get(`${host}/hotsearchs/`) }
//获取商品列表
export const getGoods = params => { return axios.get(`${host}/goods/`, { params: params }) }
//商品详情
export const getGoodsDetail = goodId => { return axios.get(`${host}/goods/${goodId}`+'/') }
//获取购物车商品
export const getShopCarts = params => { return axios.get(`${host}/shopcarts/`) }
// 添加商品到购物车
export const addShopCart = params => { return axios.post(`${host}/shopcarts/`, params) }
//更新购物车商品信息
export const updateShopCart = (goodsId, params) => { return axios.patch(`${host}/shopcarts/`+goodsId+'/', params) }
//删除某个商品的购物记录
export const deleteShopCart = goodsId => { return axios.delete(`${host}/shopcarts/`+goodsId+'/') }
//收藏
export const addFav = params => { return axios.post(`${host}/userfavs/`, params) }
//取消收藏
export const delFav = goodsId => { return axios.delete(`${host}/userfavs/`+goodsId+'/') }
export const getAllFavs = () => { return axios.get(`${host}/userfavs/`) }
//判断是否收藏
export const getFav = goodsId => { return axios.get(`${host}/userfavs/`+goodsId+'/') }
//登录
export const login = params => {
  return axios.post(`${host}/login/`, params)
}
//注册
export const register = parmas => { return axios.post(`${host}/users/`, parmas) }
//短信
export const getMessage = parmas => { return axios.post(`${host}/code/`, parmas) }
//获取用户信息
export const getUserDetail = () => { return axios.get(`${host}/users/1/`) }
//修改用户信息
export const updateUserInfo = params => { return axios.patch(`${host}/users/1/`, params) }
//获取订单
export const getOrders = () => { return axios.get(`${host}/orders/`) }
//删除订单
export const delOrder = orderId => { return axios.delete(`${host}/orders/`+orderId+'/') }
//添加订单
export const createOrder = params => {return axios.post(`${host}/orders/`, params)}
//获取订单详情
export const getOrderDetail = orderId => {return axios.get(`${host}/orders/`+orderId+'/')}
//获取留言
export const getMessages = () => {return axios.get(`${host}/messages/`)}
//添加留言
export const addMessage = params => {return axios.post(`${host}/messages/`, params, {headers:{ 'Content-Type': 'multipart/form-data' }})}
//删除留言
export const delMessages = messageId => {return axios.delete(`${host}/messages/`+messageId+'/')}
//添加收货地址
export const addAddress = params => {return axios.post(`${host}/address/`, params)}
//删除收货地址
export const delAddress = addressId => {return axios.delete(`${host}/address/`+addressId+'/')}
//修改收货地址
export const updateAddress = (addressId, params) => {return axios.patch(`${host}/address/`+addressId+'/', params)}
//获取收货地址
export const getAddress = () => {return axios.get(`${host}/address/`)}

其中,获取商品分类的接口为:

export const getCategory = params => {
  if('id' in params){
    return axios.get(`${host}/categorys/`+params.id+'/');
  }
  else {
    return axios.get(`${host}/categorys/`, params);
  }
};

显然,可以看到,如果参数中传入了id,则返回单个类别,否则返回所有类别。


而负责将类别数据显示到前端的是head.vue组件,位于src/views/head目录下,其通过赋值和循环将类别遍历出来:

<div class="main_cata" id="J_mainCata" v-show="showAllmenu">
    <ul>
        <li class="first" v-for="(item,index) in allMenuLabel" @mouseover="overChildrenmenu(index)" @mouseout="outChildrenmenu(index)">
          <h3 style="background:url(../images/1449088788518670880.png) 20px center no-repeat;">
            <router-link :to="'/app/home/list/'+item.id">{{item.name}}</router-link> </h3>
            <div class="J_subCata" id="J_subCata" v-show="showChildrenMenu ===index"  style=" left: 215px; top: 0px;">
                <div class="J_subView" >
                  <div v-for="list in item.sub_cat">
                    <dl>
                      <dt>
                        <router-link :to="'/app/home/list/'+list.id">{{list.name}}</router-link>
                      </dt>
                      <dd>
                        <router-link  v-for="childrenList in list.sub_cat" :key="childrenList.id" :to="'/app/home/list/'+childrenList.id">{{childrenList.name}}</router-link>
                      </dd>
                    </dl>
                    <div class="clear"></div>
                  </div>
                </div>
            </div>
        </li>
    </ul>
</div>
// ...
getMenu(){//获取菜单
    getCategory({
      params:{}
    }).then((response)=> {
              console.log(response)
              this.allMenuLabel = response.data
          })
          .catch(function (error) {
            console.log(error);
          });
},


相关文章
|
4天前
|
存储 前端开发 关系型数据库
108-Django开发在线书店
该项目是一个使用Python Django框架开发的在线书店系统,提供用户管理(包括普通用户、管理员和匿名用户)、权限管理、书籍管理、订单管理和额外功能(搜索、购物车、支付和评论)。系统支持安全的HTTPS传输和加密密码存储,保证用户数据安全。通过Django实现了用户购书、管理员后台管理的全面功能,兼顾易用性和可维护性。
12 0
|
5天前
|
缓存 数据挖掘 数据库
104-Django开发在线美食购物网站
美味小厨在线购物网站是基于Python和Django构建的电商平台,提供商品展示、搜索过滤、问题反馈、购物功能、商品详情查看、产品编辑添加、多用户及站点管理、订单管理等服务。采用Django框架实现高效、稳定且可扩展的系统,前后端分离以提升性能,支持数据库优化和缓存技术,注重用户数据安全。未来计划优化用户体验,拓展更多功能,并加强数据分析。
11 1
|
2天前
|
前端开发 JavaScript 数据库
110-Django开发社交聊天网站
该内容描述了一个聊天网站的功能模块和技术实现要点,主要包括: 1. 用户管理:用户注册、登录/登出、信息编辑和密码管理。 2. 权限管理:角色定义、权限分配和访问控制。 3. 好友管理:添加、查看、删除好友及处理好友请求。 4. 通讯管理:创建聊天室、在线聊天、消息发送/接收、历史记录和实时通知。 5. 技术实现:使用Django认证系统、channels库支持WebSocket、MySQL数据库、前端技术(如HTML/CSS/JavaScript)以及性能优化。 请注意,由于字符限制,部分图片无法在摘要中展示。
18 6
|
2天前
|
监控 安全 NoSQL
采用java+springboot+vue.js+uniapp开发的一整套云MES系统源码 MES制造管理系统源码
MES系统是一套具备实时管理能力,建立一个全面的、集成的、稳定的制造物流质量控制体系;对生产线、工艺、人员、品质、效率等多方位的监控、分析、改进,满足精细化、透明化、自动化、实时化、数据化、一体化管理,实现企业柔性化制造管理。
21 3
|
3天前
|
前端开发 关系型数据库 MySQL
109-Django开发考试与问卷系统
该项目描述了用户、测试和权限三个核心模块的详细需求。用户模块包括注册(需验证信息并唯一性检查,密码安全存储,确认邮件)和登录(凭据验证,可选的“记住我”功能,防止暴力破解)。测试模块涉及题目、选项和分数设置,支持创建、编辑及自动评分。权限模块关注用户角色和权限管理,实现访问控制。其他考虑因素涵盖用户界面、数据库选择(如SQLite3和MySQL)、安全性最佳实践以及系统的可维护性和可扩展性。
14 3
|
4天前
|
JavaScript
Vue中避免滥用this去读取data中数据
Vue中避免滥用this去读取data中数据
|
4天前
|
JavaScript 前端开发 开发者
Vue.js过滤器:让数据展示更灵活
Vue.js过滤器:让数据展示更灵活
|
5天前
|
前端开发 JavaScript 测试技术
107-Django开发医院管理系统(医生-患者-医院管理员)
该内容描述了一个基于Python和Django的医疗管理系统的开发步骤。主要涵盖以下关键点: 1. 环境搭建:安装Python和Django,创建项目和应用。 2. 数据库模型:设计用户、医生、患者、发票和预约等模型。 3. 用户认证和权限:使用Django内置系统,创建自定义角色和权限。 4. 视图和模板:处理用户请求,渲染HTML页面,包括医生列表、患者注册、管理界面等。 5. 表单处理:创建表单处理用户输入,验证数据并保存到数据库。 6. PDF生成:利用xhtml2pdf库生成治疗发票的PDF。 7. 路由配置:设置URL路由以连接视图。
19 7
107-Django开发医院管理系统(医生-患者-医院管理员)
|
5天前
|
JavaScript
Vue3之Props组件数据传递
Vue3之Props组件数据传递
7 0
|
5天前
|
数据库 数据安全/隐私保护 开发者
106-Django开发在线交易网站
该内容是关于使用Django框架开发电子商务网站的步骤摘要:
16 2