1. 程式人生 > >(專案)生鮮超市(五)

(專案)生鮮超市(五)

六、商品類別資料展示

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

  現在就可以從後臺獲取商品的資料了: