Vue + Django 2.0.6 学习笔记11.1-11.4 轮播图接口实现、新品功能开发、商品分类显示功能

1.轮播图

轮播图没东西 因为之前涉及了model 所以直接使用ListModelMixin就好了 Serializer也是获得所有即可。

代码:

# models.py


class GoodsImage(models.Model):
    """
    商品轮播图
    """
    goods = models.ForeignKey(Goods, verbose_name=u'商品', related_name = 'images', on_delete=models.CASCADE)
    image = models.ImageField(upload_to='', verbose_name=u'图片', null=True, blank=True)
    index = models.IntegerField(default=0, verbose_name=u'轮播顺序')
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间')

    class Meta:
        verbose_name = u'商品图片'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.goods.name




# views.py


from .models import Banner
from .serializers import  BannerSerializer

class BannerViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
    """
    获取轮播图列表
    """
    queryset = Banner.objects.all().order_by("index")
    serializer_class = BannerSerializer



# serializers.py


from goods.models import Banner
class BannerSerializer(serializers.ModelSerializer):

    class Meta:
        model = Banner
        fields = "__all__"


# urls.py
from goods.views import BannerViewset

router.register('banners', BannerViewset, base_name='banners')

这样轮播图就完成了

 

2.新品功能开发;

因为新品是goods(model)中的一个字段名 所以只需要将过滤条件增加一个就可以了

# 之前写的那个fitlers.py 在fields中增加一个‘is_new’元素即可

# encoding:utf-8


import django_filters

from django.db.models import Q

from .models import Goods


class GoodsFilter(django_filters.rest_framework.FilterSet):
    """
    商品的过滤类
    """
    pricemin = django_filters.NumberFilter(field_name='shop_price', lookup_expr='gte', help_text="最低价格")
    pricemax = django_filters.NumberFilter(field_name='shop_price', lookup_expr='lte')
    # 获取相应类别下的所有商品
    top_category = django_filters.NumberFilter(method='top_category_filter')
    # 这是全部匹配
    name = django_filters.CharFilter(field_name='name')
# 这是部分匹配 不分大小写
#     name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')

    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', 'name', 'is_hot', 'is_new']

3. 商品分类显示

主页的这部分

Vue + Django 2.0.6 学习笔记11.1-11.4 轮播图接口实现、新品功能开发、商品分类显示功能_第1张图片

这里面涉及了很多内容 多层级的1对多的关系 

先做商品类型的展示,就是图片左下角的那些

class IndexCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = "__all__"

首先先做品牌展示 利用商品类别来方向选择对应类别的品牌

在model中我们添加related_name参数,这样方便做反向选择

# models.py/class GoodsCategoryBrand
# Django2.0以上需要增加on_delete参数 针对外键

    category = models.ForeignKey(GoodsCategory, related_name="brands", null=True, blank=True, verbose_name=u'商品类目', on_delete=models.CASCADE)

这样在goods_category中就可以反向拿到brand(品牌)了

然后我们在写一个brand的Serializer 然后嵌套到IndexSerializer中

这里有一个要明确 indexSerializer是包含上面截的整张图的所有信息。所以 相关的Serializer都会嵌套进去 统一返回给前端

# Serializers.py

class BannerSerializer(serializers.ModelSerializer):

    class Meta:
        model = Banner
        fields = "__all__"


class IndexCategorySerializer(serializers.ModelSerializer):
    brands = BrandSerializer(many=True)


    class Meta:
        model = GoodsCategory
        fields = "__all__"

为什么不能直接用goods的Serializer。

goods中确实有一个外键指向我们的category。为什么不能反向取。

>因为商品选择哪个类别的时候,往往选择的是最小的类别。(第三类)
而不是直接从属于第一类。

获取商品:

外键指向的第三类。而我们要拿到第一类别的数据。直接使用goods的Serializer取不出来。

自定义商品(取相应类别的商品,使用自定义函数Serializer字段)

class IndexCategorySerializer(serializers.ModelSerializer):
    brands = BrandSerializer(many=True)
    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

 

获取二类商品类别,利用之前做过的那个GategorySerializer2

class IndexCategorySerializer(serializers.ModelSerializer):
    brands = BrandSerializer(many=True)
    goods = serializers.SerializerMethodField()
    sub_cat = CategorySerializer2(many=True)




# 这是之前做的
class CategorySerializer2(serializers.ModelSerializer):
    sub_cat = CategorySerializer3(many=True)
    class Meta:
        model = GoodsCategory
        fields = "__all__"

最后搞右边的那7张图片

先去建model

class IndexAd(models.Model):
    """
    首页类别标签右边展示的七个商品广告
    """
    category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, related_name='category', verbose_name="商品类目")
    goods = models.ForeignKey(Goods, on_delete=models.CASCADE, related_name='goods')

    class Meta:
        verbose_name = '首页广告'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.goods.name

然后在IndexCategorySerializer中增加这些广告

from goods.models import IndexAd


class IndexCategorySerializer(serializers.ModelSerializer):
    brands = BrandSerializer(many=True)
    goods = serializers.SerializerMethodField()
    sub_cat = CategorySerializer2(many=True)
    ad_goods = serializers.SerializerMethodField()

    def get_ad_goods(self, obj):
        goods_json = {}
        ad_goods = IndexAd.objects.filter(category_id = obj.id)
        if ad_goods:
            goods_ins = ad_goods[0].goods
            goods_json = GoodsSerializer(goods_ins, many=False).data
        return goods_json

这时候输出到前端的img路径是不包含url地址的。 因为我们在Serializer中嵌套了serializer 并且还自定义了序列化方法。 这样的形式默认是不会加上url的 所以我们需要在嵌套的Serializer中加上context参数

    def get_ad_goods(self, obj):
        goods_json = {}
        ad_goods = IndexAd.objects.filter(category_id = obj.id)
        if ad_goods:
            goods_ins = ad_goods[0].goods
# --------------------------------------------------------------> 这里
            goods_json = GoodsSerializer(goods_ins, many=False, context={'request': self.context['request']}).data
        return goods_json

这样输出到前端的图片路径就是包含URL域名的了。 帖完整的Serializer代码

from goods.models import Goods, GoodsCategory, GoodsImage, Banner, GoodsCategoryBrand, IndexAd
from django.db.models import Q


class IndexCategorySerializer(serializers.ModelSerializer):
    brands = BrandSerializer(many=True)
    goods = serializers.SerializerMethodField()
    sub_cat = CategorySerializer2(many=True)
    ad_goods = serializers.SerializerMethodField()

    def get_ad_goods(self, obj):
        goods_json = {}
        ad_goods = IndexAd.objects.filter(category_id = obj.id)
        if ad_goods:
            goods_ins = ad_goods[0].goods
            goods_json = GoodsSerializer(goods_ins, many=False, context={'request': self.context['request']}).data
        return goods_json


    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

    class Meta:
        model = GoodsCategory
        fields = "__all__"

然后我们来写view

class IndexCategoryViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
    """
    首页商品分类数据
    """

# 限定了是否是用于导航 并且限定了两类商品(正式环境是不限定商品类型)
    queryset = GoodsCategory.objects.filter(is_tab=True, name__in=["生鲜食品","酒水饮料"])
    serializer_class = IndexCategorySerializer

urls.py:

#主页商品系列数据
router.register('indexgoods', IndexCategoryViewset, base_name='indexgoods')

 

你可能感兴趣的:(Django)