目錄
生鮮超市(十) 生鮮超市(十一) 生鮮超市(十二) 生鮮超市(十三)
代碼下載
教程
學習自慕課網-前端vue結合后端DjangoFramework的在線生鮮超市
六、商品類別數據展示
6.1. 商品類別數據接口
(1)商品分類有兩個接口:
一種是全部分類:一級二級三級

一種是某一類的分類以及商品詳細信息:

開始寫商品分類的接口
(2)序列化
給分類添加三級分類的serializer
goods/serializers.py
from rest_framework import serializers from .models import Goods,GoodsCategory class CategorySerializer3(serializers.ModelSerializer): '''三級分類''' class Meta: model = GoodsCategory fields = "__all__" class CategorySerializer2(serializers.ModelSerializer): ''' 二級分類 ''' #在parent_category字段中定義的related_name="sub_cat" sub_cat = CategorySerializer3(many=True) class Meta: model = GoodsCategory fields = "__all__" class CategorySerializer(serializers.ModelSerializer): """ 商品一級類別序列化 """ sub_cat = CategorySerializer2(many=True) class Meta: model = GoodsCategory fields = "__all__"
(3)views.py
class CategoryViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): ''' list: 商品分類列表數據 ''' queryset = GoodsCategory.objects.filter(category_type=1)
serializer_class = CategorySerializer
說明:
- 注釋的內容,在后面生成drf文檔的時候會顯示出來,所有要寫清楚
- 要想獲取某一個商品的詳情的時候,繼承 mixins.RetrieveModelMixin 就可以了
(4)url配置
# 配置Category的url router.register(r'categorys', CategoryViewSet, base_name="categorys")

6.2.vue展示商品分類數據
接口相關代碼都放在src/api/api.js里面,調試接口的時候我們首先需要新建一個自己的host,然后替換要調試的host
(1)新建local_host
let local_host = 'http://127.0.0.1:8000'
(2)替換商品類別默認的host
//獲取商品類別信息 export const getCategory = params => { if('id' in params){ return axios.get(`${local_host}/categorys/`+params.id+'/'); } else { return axios.get(`${local_host}/categorys/`, params); } };
這個時候訪問 http://127.0.0.1:8080/#/app/home/index
發現不顯示商品分類了,是因為這涉及到了跨域問題,接下來就解決跨域的問題

drf跨域問題
后端服務器解決跨域問題的方法
(1)安裝模塊
pip install django-cors-headers
django-cors-headers 使用說明:https://github.com/ottoyiu/django-cors-headers
(2)添加到INSTALL_APPS中
INSTALLED_APPS = (
...
'coreschema',
... )
(3)添加中間件
下面添加中間件的說明:
CorsMiddleware should be placed as high as possible, especially before any middleware that can generate responses such as Django's CommonMiddleware or Whitenoise's WhiteNoiseMiddleware. If it is not before, it will not be able to add the CORS headers to these responses.
Also if you are using CORS_REPLACE_HTTPS_REFERER it should be placed before Django's CsrfViewMiddleware (see more below).
意思就是 要放的盡可能靠前,必須在CsrfViewMiddleware之前。我們直接放在第一個位置就好了
MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
(4)設置為True
CORS_ORIGIN_ALLOW_ALL = True
現在再訪問 http://127.0.0.1:8080/#/app/home/index 數據就可以填充進來了

在一級分類中設置為True


6.3.vue展示商品列表頁數據
商品列表頁會判斷我們是serach還是getGoods
getListData() { if(this.pageType=='search'){ getGoods({ search: this.searchWord, //搜索關鍵詞 }).then((response)=> { this.listData = response.data.results; this.proNum = response.data.count; }).catch(function (error) { console.log(error); }); }else { getGoods({ page: this.curPage, //當前頁碼 top_category: this.top_category, //商品類型 ordering: this.ordering, //排序類型 pricemin: this.pricemin, //價格最低 默認為‘’ 即為不選價格區間 pricemax: this.pricemax // 價格最高 默認為‘’ }).then((response)=> { this.listData = response.data.results; this.proNum = response.data.count; }).catch(function (error) { console.log(error); }); } },
說明:
(1)page分頁
page_size數量與前端一致
頁碼參數與起前端一致"page"
class GoodsPagination(PageNumberPagination): ''' 商品列表自定義分頁 ''' #默認每頁顯示的個數 page_size = 12 #可以動態改變每頁顯示的個數 page_size_query_param = 'page_size' #頁碼參數 page_query_param = 'page' #最多能顯示多少頁 max_page_size = 100
(2)過濾
top_category是商品的一級分類,需要傳入參數:一級分類的id
pricemin和pricemax與前端保持一致
獲取一級分類下的所有商品
# goods/filters.py import django_filters from .models import Goods from django.db.models import Q class GoodsFilter(django_filters.rest_framework.FilterSet): ''' 商品過濾的類 ''' #兩個參數,name是要過濾的字段,lookup是執行的行為,‘小與等於本店價格’ pricemin = django_filters.NumberFilter(name="shop_price", lookup_expr='gte') pricemax = django_filters.NumberFilter(name="shop_price", lookup_expr='lte') top_category = django_filters.NumberFilter(name="category", method='top_category_filter') def top_category_filter(self, queryset, name, value): # 不管當前點擊的是一級分類二級分類還是三級分類,都能找到。 return queryset.filter(Q(category_id=value) | Q(category__parent_category_id=value) | Q( category__parent_category__parent_category_id=value)) class Meta: model = Goods fields = ['pricemin', 'pricemax']
(3)排序
GoodsListViewSet中ording與前端要一致

#排序 ordering_fields = ('sold_num', 'shop_price')
(4)替換為local_host
//獲取商品列表 export const getGoods = params => { return axios.get(`${local_host}/goods/`, { params: params }) }
(5)搜索
#搜索 search_fields = ('name', 'goods_brief', 'goods_desc')
現在就可以從后台獲取商品的數據了,主要功能
- 分類過濾
- 價格區間過濾
- 顯示商品數量
- 分頁
- 搜索

所有代碼:
# MxShop/urls.py __author__ = 'derek' from django.urls import path,include,re_path import xadmin from django.views.static import serve from MxShop.settings import MEDIA_ROOT # from goods.view_base import GoodsListView from rest_framework.documentation import include_docs_urls from goods.views import GoodsListViewSet,CategoryViewSet from rest_framework.routers import DefaultRouter router = DefaultRouter() #配置goods的url router.register(r'goods', GoodsListViewSet,base_name='goods') # 配置Category的url router.register(r'categorys', CategoryViewSet, base_name="categorys") urlpatterns = [ path('xadmin/', xadmin.site.urls), path('api-auth/',include('rest_framework.urls')), path('ueditor/',include('DjangoUeditor.urls' )), #文件 path('media/<path:path>',serve,{'document_root':MEDIA_ROOT}), #drf文檔,title自定義 path('docs',include_docs_urls(title='仙劍奇俠傳')), #商品列表頁 re_path('^', include(router.urls)), ]
# goods/filters.py import django_filters from .models import Goods from django.db.models import Q class GoodsFilter(django_filters.rest_framework.FilterSet): ''' 商品過濾的類 ''' #兩個參數,name是要過濾的字段,lookup是執行的行為,‘小與等於本店價格’ pricemin = django_filters.NumberFilter(name="shop_price", lookup_expr='gte') pricemax = django_filters.NumberFilter(name="shop_price", lookup_expr='lte') top_category = django_filters.NumberFilter(name="category", method='top_category_filter') def top_category_filter(self, queryset, name, value): # 不管當前點擊的是一級分類二級分類還是三級分類,都能找到。 return queryset.filter(Q(category_id=value) | Q(category__parent_category_id=value) | Q( category__parent_category__parent_category_id=value)) class Meta: model = Goods fields = ['pricemin', 'pricemax']
# goods/serializers.py from rest_framework import serializers from .models import Goods,GoodsCategory class CategorySerializer3(serializers.ModelSerializer): '''三級分類''' class Meta: model = GoodsCategory fields = "__all__" class CategorySerializer2(serializers.ModelSerializer): ''' 二級分類 ''' #在parent_category字段中定義的related_name="sub_cat" sub_cat = CategorySerializer3(many=True) class Meta: model = GoodsCategory fields = "__all__" class CategorySerializer(serializers.ModelSerializer): """ 商品一級類別序列化 """ sub_cat = CategorySerializer2(many=True) class Meta: model = GoodsCategory fields = "__all__" #ModelSerializer實現商品列表頁 class GoodsSerializer(serializers.ModelSerializer): #覆蓋外鍵字段 category = CategorySerializer() class Meta: model = Goods fields = '__all__'
# googd/views.py from rest_framework.views import APIView from goods.serializers import GoodsSerializer,CategorySerializer from .models import Goods,GoodsCategory from rest_framework.response import Response from rest_framework import mixins from rest_framework import generics from rest_framework.pagination import PageNumberPagination from rest_framework import viewsets from .filters import GoodsFilter from django_filters.rest_framework import DjangoFilterBackend from rest_framework import filters class GoodsPagination(PageNumberPagination): ''' 商品列表自定義分頁 ''' #默認每頁顯示的個數 page_size = 12 #可以動態改變每頁顯示的個數 page_size_query_param = 'page_size' #頁碼參數 page_query_param = 'page' #最多能顯示多少頁 max_page_size = 100 class GoodsListViewSet(mixins.ListModelMixin,viewsets.GenericViewSet): ''' 商品列表,分頁,搜索,過濾,排序 ''' #這里必須要定義一個默認的排序,否則會報錯 queryset = Goods.objects.all() # 分頁 pagination_class = GoodsPagination #序列化 serializer_class = GoodsSerializer filter_backends = (DjangoFilterBackend,filters.SearchFilter,filters.OrderingFilter) # 設置filter的類為我們自定義的類 #過濾 filter_class = GoodsFilter #搜索 search_fields = ('name', 'goods_brief', 'goods_desc') #排序 ordering_fields = ('sold_num', 'shop_price') class CategoryViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): ''' list: 商品分類列表數據 ''' queryset = GoodsCategory.objects.filter(category_type=1) serializer_class = CategorySerializer
Django REST framework+Vue 打造生鮮超市(四)
Django REST framework+Vue 打造生鮮超市(三)
Django REST framework+Vue 打造生鮮超市(二)
Django REST framework+Vue 打造生鮮超市(一)
