六、商品类别数据展示
1、商品类别数据接口
商品分类有两个接口,一种是全部分类,一级二级三级:
另一种是某一类的分类及商品的展示:
首先在serializers.py编写类别的序列化:
1 class CategorySerializer3(serializers.ModelSerializer): 2 '''三级分类''' 3 4 class Meta: 5 model = GoodsCategory 6 fields = "__all__" 7 8 9 class CategorySerializer2(serializers.ModelSerializer): 10 '''二级分类''' 11 12 # 在parent_category字段中定义的related_name="sub_cat" 13 sub_cat = CategorySerializer3(many=True) 14 15 class Meta: 16 model = GoodsCategory 17 fields = "__all__" 18 19 20 class CategorySerializer(serializers.ModelSerializer): 21 """一级类别""" 22 23 sub_cat = CategorySerializer2(many=True) 24 25 class Meta: 26 model = GoodsCategory 27 fields = "__all__"
然后编写商品类别接口:
1 class CategoryViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): 2 """ 3 list: 4 商品分类列表数据 5 """ 6 7 queryset = GoodsCategory.objects.filter(category_type=1) 8 serializer_class = CategorySerializer
- 注释的内容在后面生成drf文档的时候会显示出来,所以要写清楚
- RetrieveModelMixin,获取某一个商品的详情的时候,继承这个类就可以了
然后在router中注册url:
1 router.register(r'categorys', CategoryViewSet, base_name='categorys') # 商品类别
2、Vue展示商品分类数据
Vue接口的相关代码都放在src/api/api.js里面,调试接口的时候我们首先需要新建一个自己的host,然后替换要调试的host,现在修改Vue中的接口代码:
1 let host = 'http://127.0.0.1:8000';
然后替换商品类别接口中默认的host:
1 //获取商品类别信息 2 export const getCategory = params => { 3 if('id' in params){ 4 return axios.get(`${host}/categorys/`+params.id+'/'); 5 } 6 else { 7 return axios.get(`${host}/categorys/`, params); 8 } 9 };
现在访问http://127.0.0.1:8080/#/app/home/index,发现商品类别的数据不见了:
这是因为涉及到了跨域的问题,解决办法如下:
后端服务器解决跨域问题,安装模块pip install django-cors-headers,然后在INSTALLED_APPS 中注册'coreschema',然后添加中间件CorsMiddleware
这些英文的意思就是要放到CsrfViewMiddleware之前,那我们直接放在第一个位置就好了:
1 MIDDLEWARE = [ 2 'corsheaders.middleware.CorsMiddleware', 3 'django.middleware.security.SecurityMiddleware', 4 'django.contrib.sessions.middleware.SessionMiddleware', 5 'django.middleware.common.CommonMiddleware', 6 'django.middleware.csrf.CsrfViewMiddleware', 7 'django.contrib.auth.middleware.AuthenticationMiddleware', 8 'django.contrib.messages.middleware.MessageMiddleware', 9 'django.middleware.clickjacking.XFrameOptionsMiddleware', 10 ]
然后设置CORS_ORIGIN_ALLOW_ALL = True
现在访问http://127.0.0.1:8080/#/app/home/index:
在后台中将一级分类中的类别设置是否导航:
3、Vue展示商品列表页数据
商品列表页面会判断是search还是getGoods:
1 getListData() { 2 if(this.pageType=='search'){ 3 getGoods({ 4 search: this.searchWord, //搜索关键词 5 }).then((response)=> { 6 this.listData = response.data.results; 7 this.proNum = response.data.count; 8 }).catch(function (error) { 9 console.log(error); 10 }); 11 }else { 12 getGoods({ 13 page: this.curPage, //当前页码 14 top_category: this.top_category, //商品类型 15 ordering: this.ordering, //排序类型 16 pricemin: this.pricemin, //价格最低 默认为‘’ 即为不选价格区间 17 pricemax: this.pricemax // 价格最高 默认为‘’ 18 }).then((response)=> { 19 20 this.listData = response.data.results; 21 this.proNum = response.data.count; 22 }).catch(function (error) { 23 console.log(error); 24 }); 25 } 26 27 },
这段代码中,pag是分页,后端的分页信息要与前端保持一致:
1 class GoodsPagination(PageNumberPagination): 2 """商品自定义分页""" 3 4 page_size = 12 # 每页显示个数 5 page_size_query_param = 'page_size' # 动态改变每页显示的个数 6 page_query_param = 'page' # 页码参数 7 max_page_size = 100 # 最多显示页数
top_category是商品的一级分类,需要传入参数:一级分类的id,pricemin和pricemax与前端保持一致,然后完善过滤的代码:
1 class GoodsFilter(django_filters.rest_framework.FilterSet): 2 """商品过滤""" 3 4 # name是要过滤的字段,lookup是执行的行为 5 pricemin = django_filters.NumberFilter(field_name="shop_price", lookup_expr='gte') 6 pricemax = django_filters.NumberFilter(field_name="shop_price", lookup_expr='lte') 7 top_category = django_filters.NumberFilter(field_name="category", method='top_category_filter') 8 9 def top_category_filter(self, queryset, name, value): 10 # 不管当前点击的是一级分类二级分类还是三级分类,都能找到 11 return queryset.filter(Q(category_id=value) | Q(category__parent_category_id=value) | Q( 12 category__parent_category__parent_category_id=value)) 13 14 class Meta: 15 model = Goods 16 fields = ['pricemin', 'pricemax']
后端的GoodsListViewSet中ording与前端要一致:
1 class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): 2 """商品列表页面""" 3 4 pagination_class = GoodsPagination 5 queryset = Goods.objects.all().order_by('id') # 必须定义一个默认的排序,否则会报错 6 serializer_class = GoodsSerializer 7 filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter) 8 9 # 自定义过滤类 10 filter_class = GoodsFilter 11 12 # 搜索,=name表示精确搜索,也可以使用正则 13 search_fields = ('name', 'goods_brief', 'goods_desc') 14 15 # 排序 16 ordering_fields = ('sold_num', 'shop_price')
将Vue中的获取商品列表接口的host修改:
1 //获取商品列表 2 export const getGoods = params => { return axios.get(`${host}/goods/`, { params: params }) }
现在就可以从后台获取商品的数据了: