我给我大姨用Django+Vue开发生鲜电商平台!在乡下也能网购了

一、首页功能完善

首页待完善的功能包括轮播图、新品尝鲜、系列商品等。

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开发生鲜电商平台!在乡下也能网购了

可以看到,开始没有轮播图数据,经过在管理后台添加数据后,即同步数据。

前端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开发生鲜电商平台!在乡下也能网购了

显然,请求的图片数据已从本地加载,并且点击轮播图片会调皮转到相应的商品链接。

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>

演示如下:

我给我大姨用Django+Vue开发生鲜电商平台!在乡下也能网购了

显然,在手动添加新品之后,新品数据即同步,请求的参数中包含is_new=true。

前端src/views/index/news.vue如下:

可以看到,在初始化时,调用getOpro()方法,在调用getGoods接口时传入参数is_new,来获取新品,与之前获取商品调用的接口相同,获取到数据后通过for循环显示出来。

访问示意如下:

我给我大姨用Django+Vue开发生鲜电商平台!在乡下也能网购了

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>

进行测试:

我给我大姨用Django+Vue开发生鲜电商平台!在乡下也能网购了

可以看到,再添加数据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>

此时再查看如下:

我给我大姨用Django+Vue开发生鲜电商平台!在乡下也能网购了

显然,已经将域名显示出来。

前端src/views/index/series-list.vue如下:


分享到:


相關文章: