(專案)生鮮超市(五)
六、商品類別資料展示
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 }) }
現在就可以從後臺獲取商品的資料了: