(项目)生鲜超市(五)

六、商品类别数据展示

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 }) }

  现在就可以从后台获取商品的数据了:

猜你喜欢

转载自www.cnblogs.com/Sweltering/p/10016685.html