一、首頁功能完善
首頁待完善的功能包括輪播圖、新品嚐鮮、系列商品等。
1.輪播圖實現
輪播圖包括3張圖片,鏈接對應3個商品,先在apps/goods/serializers.py中定義序列化如下:
<code>class BannerSerializer(serializers.ModelSerializer): class Meta: model = Banner fields = '__all__'/<code>
再在views.py中定義視圖如下:
<code>class BannerViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): ''' list: 輪播圖列表 ''' queryset = Banner.objects.filter(is_delete=False).order_by('index') serializer_class = BannerSerializer/<code>
再在urls.py中定義路由如下:
<code># 配置輪播圖路由 router.register(r'banners', BannerViewSet, basename='banners')/<code>
測試如下:
![我給我大姨用Django+Vue開發生鮮電商平臺!在鄉下也能網購了](http://p2.ttnews.xyz/loading.gif)
可以看到,開始沒有輪播圖數據,經過在管理後臺添加數據後,即同步數據。
前端src/views/index/banners.vue如下:
<code>methods:{ getBanner(){ bannerGoods() .then((response)=> { console.log(response) //跳轉到首頁頁response.body面 this.banners = response.data }) .catch(function (error) { console.log(error); }); } }, created(){ this.getBanner(); }/<code>
在初始化時調用getBanner()方法,在調用bannerGoods接口請求數據,請求到的數據再通過for循環展示出來。
api.js修改如下:
<code>//獲取輪播圖 export const bannerGoods = params => { return axios.get(`${local_host}/banners/`) }/<code>
此時再進行測試如下:
![我給我大姨用Django+Vue開發生鮮電商平臺!在鄉下也能網購了](http://p2.ttnews.xyz/loading.gif)
顯然,請求的圖片數據已從本地加載,並且點擊輪播圖片會調皮轉到相應的商品鏈接。
2.新品功能開發
在定義商品模型時定義了is_new字段表示是否是新品,再實現新品功能時需要用到該字段,直接使用Goods接口並在filters.py過濾器中定義即可,如下:
<code>class GoodsFilter(django_filters.rest_framework.FilterSet): '''商品過濾類''' name = django_filters.CharFilter(field_name="name", lookup_expr='contains') pricemin = django_filters.NumberFilter(field_name="market_price", lookup_expr='gte') pricemax = django_filters.NumberFilter(field_name="market_price", lookup_expr='lte') top_category = django_filters.NumberFilter(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 = ['name', 'pricemin', 'pricemax', 'is_hot', 'is_new']/<code>
演示如下:
顯然,在手動添加新品之後,新品數據即同步,請求的參數中包含is_new=true。
前端src/views/index/news.vue如下:
可以看到,在初始化時,調用getOpro()方法,在調用getGoods接口時傳入參數is_new,來獲取新品,與之前獲取商品調用的接口相同,獲取到數據後通過for循環顯示出來。
訪問示意如下:
3.商品系列分類展示功能
商品系列分類包括左側的導航欄和右側的商品列表,大類對應多個品牌、大類對應多個小類、大類對應多個商品,即包含3個一對多關係,在定義序列化時需要嵌套定義。
為了實現嵌套,在定義GoodsCategoryBrand模型時需要指定related_name屬性,如下:
<code>class GoodsCategoryBrand(models.Model): '''品牌名''' category = models.ForeignKey(GoodsCategory, verbose_name='商品類目', related_name='brands', null=True, on_delete=models.SET_NULL) name = models.CharField(default='', max_length=30, verbose_name='品牌名', help_text='品牌名') desc = models.TextField(default='', max_length=200, verbose_name='品牌描述', help_text='品牌描述') image = models.ImageField(max_length=200, upload_to='brands/') add_time = models.DateTimeField(default=datetime.now, verbose_name=u'添加時間') is_delete = models.BooleanField(default=False, verbose_name='是否刪除') class Meta: verbose_name = '品牌' verbose_name_plural = verbose_name def __str__(self): return self.name class IndexAd(models.Model): category = models.ForeignKey(GoodsCategory, verbose_name='商品類目', related_name='category', null=True, on_delete=models.SET_NULL) goods = models.ForeignKey(Goods, verbose_name='商品', related_name='goods', null=True, on_delete=models.SET_NULL) class Meta: verbose_name = '首頁商品類別廣告' verbose_name_plural = verbose_name def __str__(self): return self.goods.name/<code>
完成後需要進行數據映射。
為了在創建brand時只顯示一級類別,在adminx.py中定義GoodsBrandAdmin類時重寫了get_context()方法,其中獲取到category字段只取category_type為1的數據,如下:
<code>定義序列化如下: class BannerSerializer(serializers.ModelSerializer): class Meta: model = Banner fields = '__all__' class BrandSerializer(serializers.ModelSerializer): class Meta: model = GoodsCategoryBrand fields = '__all__' class IndexCategorySerializer(serializers.ModelSerializer): brands = BrandSerializer(many=True) goods = serializers.SerializerMethodField() sub_cat = SecCategorySerializer(many=True) ad_goods = serializers.SerializerMethodField() def get_goods(self, obj): all_goods = Goods.objects.filter(Q(category_id=obj.id)|Q(category__parent_category_id=obj.id)|Q(category__parent_category__parent_category_id=obj.id)) goods_serializer = GoodsSerializer(all_goods, many=True) return goods_serializer.data def get_ad_goods(self, obj): goods_json = {} ad_goods = IndexAd.objects.filter(category_id=obj.id) if ad_goods: good_instance = ad_goods[0].goods goods_json = GoodsSerializer(good_instance, many=False).data return goods_json class Meta: model = GoodsCategory fields = '__all__'class GoodsBrandAdmin(object): list_display = ["category", "image", "name", "desc"] def get_context(self): context = super(GoodsBrandAdmin, self).get_context() if 'form' in context: context['form'].fields['category'].queryset = GoodsCategory.objects.filter(category_type=1) return context/<code>
定義序列化如下:
<code>class BannerSerializer(serializers.ModelSerializer): class Meta: model = Banner fields = '__all__' class BrandSerializer(serializers.ModelSerializer): class Meta: model = GoodsCategoryBrand fields = '__all__' class IndexCategorySerializer(serializers.ModelSerializer): brands = BrandSerializer(many=True) goods = serializers.SerializerMethodField() sub_cat = SecCategorySerializer(many=True) ad_goods = serializers.SerializerMethodField() def get_goods(self, obj): all_goods = Goods.objects.filter(Q(category_id=obj.id)|Q(category__parent_category_id=obj.id)|Q(category__parent_category__parent_category_id=obj.id)) goods_serializer = GoodsSerializer(all_goods, many=True) return goods_serializer.data def get_ad_goods(self, obj): goods_json = {} ad_goods = IndexAd.objects.filter(category_id=obj.id) if ad_goods: good_instance = ad_goods[0].goods goods_json = GoodsSerializer(good_instance, many=False).data return goods_json class Meta: model = GoodsCategory fields = '__all__'/<code>
可以看到,定義了多個一對多的關係和一個一對一的關係,視圖如下:
<code>定義路由如下: # 配置首頁商品系列路由 router.register(r'indexgoods', IndexCategoryViewSet, basename='indexgoods')class IndexCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): ''' list: 商品分類數據 ''' queryset = GoodsCategory.objects.filter(is_delete=False, is_tab=True, name__in=['生鮮食品', '酒水飲料']) serializer_class = IndexCategorySerializer /<code>
定義路由如下:
<code># 配置首頁商品系列路由 router.register(r'indexgoods', IndexCategoryViewSet, basename='indexgoods')/<code>
進行測試:
可以看到,再添加數據brands和ad_goods之前這兩類數據為空,添加之後數據同步。
但是同時也可以看到,在商品的image屬性的值即圖片鏈接中未自動添加域名,這是因為進行嵌套序列化默認不會添加域名,需要給字段設置
context屬性,配置如下:<code>class IndexCategorySerializer(serializers.ModelSerializer): brands = BrandSerializer(many=True) goods = serializers.SerializerMethodField() sub_cat = SecCategorySerializer(many=True) ad_goods = serializers.SerializerMethodField() def get_goods(self, obj): all_goods = Goods.objects.filter(Q(category_id=obj.id)|Q(category__parent_category_id=obj.id)|Q(category__parent_category__parent_category_id=obj.id)) goods_serializer = GoodsSerializer(all_goods, many=True, context={'request': self.context['request']}) return goods_serializer.data def get_ad_goods(self, obj): goods_json = {} ad_goods = IndexAd.objects.filter(category_id=obj.id) if ad_goods: good_instance = ad_goods[0].goods goods_json = GoodsSerializer(good_instance, many=False, context={'request': self.context['request']}).data return goods_json class Meta: model = GoodsCategory fields = '__all__'/<code>
此時再查看如下:
顯然,已經將域名顯示出來。
前端src/views/index/series-list.vue如下:
關鍵字: serializers ad 輪播